2016-01-24 2 views
1

Наше приложение подключается к 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 службы был действительным)

я не мог найти какой-либо информацию по этому сценарию в Интернете, поэтому я задаю следующие вопросы:

  1. Неужели кто-нибудь сталкивался с подобным поведением?
  2. Есть ли какие-либо сценарии, в которых onServiceConnected будет передан null как второй параметр вместо действительного IBinder, возвращаемого удаленным Service?
+0

Что мешает вам войти в 'IAidlService.Stub.asInterface()' метод с отладчиком? – pskink

+0

@pskink, этот код сгенерирован автоматически, и я его исследовал. Не могли бы вы объяснить, что я получу, пройдя через него с помощью отладчика, учитывая, что ошибка не воспроизводится? – Vasiliy

+0

если вы его исследовали, то вы, вероятно, заметили, что 'asInterface (android.os.IBinder obj) 'может возвращать' null', только если 'obj' имеет значение null – pskink

ответ

1

Благодаря помощи @ pskink, я понял, что ни onServiceConnected может быть вызвана с нулевым IBinder, ни AIDL-х Stub.asInterface может возвращать нуль.

Нижняя линия: нет необходимости в нулевых проверках в onServiceConnected обратном вызове.

Смежные вопросы