Наше приложение подключается к IPC Service
, отображаемому через интерфейс AIDL. До сих пор все работало нормально, но внезапно мы заметили, что исключение NullPointerException выбрано сразу после вызова обратного вызова onServiceConnected
.Android IPC: onServiceConnected, за которым следует NullPointerException
Мы связываем с услугой следующим образом:
boolean isServiceBound = context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Тогда мы гарантируем, что служба должна была успешно и фоновый поток ждет onServiceConnected
обратного вызова, который будет вызван:
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder binder) {
Log.d(TAG, "converting Binder into IAidlService");
aidlService = IAidlService.Stub.asInterface(binder);
serviceConnected(); // this call releases background thread that waits for connection to be established
}
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, "IAidlService disconnected unexpectedly");
aidlService = null;
}
};
После serviceConnected()
вызывается при вызове обратного вызова onServiceConnected
, мы предполагаем, что соединение установлено и была инициализирована переменная aidlService
(если только onServiceDisconnected
не получает i nvoked afterwards, но это не так).
Как я уже говорил, эта схема работала нормально в течение некоторого времени, но внезапно мы столкнулись с NullPointerException, возникающим сразу после onServiceConnected
. Выход Logcat:
01-21 14:06:32.717 22651-22651/com.xxx.xxx D/LocalService: converting Binder into IAidlService
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: FATAL EXCEPTION: IntentService[LocalService]
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: Process: com.xxx.xxx, PID: 22651
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'void com.yyy.yyy.IAidlService.someMethod(android.os.Bundle)' on a null object reference
Как вы можете видеть, aidlService
используется в фоновом потоке после onServiceConnected
был вызван на главном потоке. Я на 99,9% уверен, что здесь нет многопоточной проблемы, и логика, которая заставляет фоновый поток ждать до тех пор, пока serviceConnected()
не будет вызвана, отлично работает (и задержка в 4 мс, наблюдаемая в logcat, поддерживает это требование).
Мы не смогли воспроизвести это поведение.
Итак, мы знаем, что был вызван onServiceConnected
, но переменная не была инициализирована aidlService
. Я вижу только один потенциальную причину такого поведения: IBinder
объект передается onServiceConnected
системой была null
(я 100% уверен, что объект возвращается в onBind()
из с IPC службы был действительным)
я не мог найти какой-либо информацию по этому сценарию в Интернете, поэтому я задаю следующие вопросы:
- Неужели кто-нибудь сталкивался с подобным поведением?
- Есть ли какие-либо сценарии, в которых
onServiceConnected
будет переданnull
как второй параметр вместо действительногоIBinder
, возвращаемого удаленнымService
?
Что мешает вам войти в 'IAidlService.Stub.asInterface()' метод с отладчиком? – pskink
@pskink, этот код сгенерирован автоматически, и я его исследовал. Не могли бы вы объяснить, что я получу, пройдя через него с помощью отладчика, учитывая, что ошибка не воспроизводится? – Vasiliy
если вы его исследовали, то вы, вероятно, заметили, что 'asInterface (android.os.IBinder obj) 'может возвращать' null', только если 'obj' имеет значение null – pskink