Подтвердить что ты не робот

Случайное исключение "Получатель не зарегистрировано"

В onResume() я делаю:

registerReceiver(timeTickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));

и в onPause():

unregisterReceiver(timeTickReceiver);

Я вижу "java.lang.IllegalArgumentException: Receiver not registered" отчеты в Android Developer Console (есть только 2 отчета, а в моем приложении тысячи пользователей). Исключение инициируется unregisterReceiver(). Что может случиться? Я не чувствую себя очень уверенно, чтобы просто окружить его попыткой.

4b9b3361

Ответ 1

Мы видели эту ошибку при длительном нажатии на конкретном экране, а затем сразу же делаем два изменения ориентации (например, переверните устройство вверх ногами).

В документах API для unregisterReceiver говорится:

Отменить регистрацию ранее зарегистрированного BroadcastReceiver.

Он не говорит явно, но, как вы видели, вы попадаете в IllegalArgumentException: Receiver not registered, если он еще не зарегистрирован.

Обходной путь, который я использую, заключается в том, чтобы сохранить мой приемник в качестве поля-члена и установить его равным null, когда он не зарегистрирован, т.е. я инициализирую его до нуля, а затем устанавливаю его только при регистрации. Это может быть не идеально, но это решает мои аварии!

private Receiver mReceiver = null;

Из моего onServiceConnected:

sLog.debug("Registering receiver");
mReceiver = new Receiver();
registerReceiver(mReceiver, filter);

Из моего onServiceDisconnected:

if (mReceiver == null)
{
  sLog.info("Do not unregister receiver as it was never registered");
}
else
{
  sLog.debug("Unregister receiver");
  unregisterReceiver(mReceiver);
  mReceiver = null;
}

Ответ 2

Радиовещательный приемник должен отменить регистрацию в методе жизненного цикла onPause()

protected void onPause() {
    this.unregisterReceiver(reciever);
    super.onPause();
}

Ответ 3

Я предполагаю, что могут быть некоторые состояния, где приемник фактически не зарегистрирован до, например, пользователь выходит из приложения.

Возможно, вам захочется попробовать добавить проверку для получателя, прежде чем запускать отмену регистрации (я делал это в нескольких случаях):

protected void onPause() {
  if(timeTickReceiver != null) {
    unregisterReceiver(timeTickReceiver);
  }
}

Ответ 4

Самый простой вариант - обернуть блок try/catch вокруг кода.

try{
    ...
    this.unregisterReceiver(reciever);
   }
    catch(IllegalArgumentException e)
    {
        // TODO: handle exception
    }
    catch (Exception e) {
        // TODO: handle exception
    }

Ответ 5

A BroadcastReceiver должен быть зарегистрирован в методе жизненного цикла onCreate():

private BroadcastReceiver receiver;

@Overrride
public void onCreate(Bundle savedInstanceState){
    IntentFilter filter = new IntentFilter();

    receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            ...
        }
    }

    registerReceiver(receiver, filter);
}    

И BroadcastReceiver должен быть незарегистрирован в методе жизненного цикла onDestory():

@Override
protected void onDestroy() {
    unregisterReceiver(receiver);
}

Это предотвратит сценарий отмены регистрации BroadcastReceiver, который еще не зарегистрирован.