Получатель не зарегистрировал ошибку исключения? - PullRequest
103 голосов
/ 29 мая 2011

В моей консоли разработчика люди продолжают сообщать об ошибке, которую я не могу воспроизвести на любом телефоне, который у меня есть. Один человек оставил сообщение о том, что получает его, когда они пытаются открыть экран настроек моей службы батареи. Как вы можете видеть из ошибки, это говорит о том, что получатель не зарегистрирован.

java.lang.RuntimeException: Unable to stop service .BatteryService@4616d688:  java.lang.IllegalArgumentException: Receiver not registered: com.app.notifyme.BatteryService$BatteryNotifyReceiver@4616d9d0
at android.app.ActivityThread.handleStopService(ActivityThread.java:3164)
at android.app.ActivityThread.access$3900(ActivityThread.java:129)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2173)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Receiver not registered:com..BatteryService$BatteryNotifyReceiver@4616d9d0
at android.app.ActivityThread$PackageInfo.forgetReceiverDispatcher(ActivityThread.java:805)
at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:859)
at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331)
at com.app.notifyme.BatteryService.onDestroy(BatteryService.java:128)
at android.app.ActivityThread.handleStopService(ActivityThread.java:3150)

Я зарегистрировался в моем onCreate

@Override
public void onCreate(){
    super.onCreate();
    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    filter.addAction(Intent.ACTION_POWER_CONNECTED);
    filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
    registerReceiver(batteryNotifyReceiver,filter);
    pref.registerOnSharedPreferenceChangeListener(this);
}

Отменить регистрацию в onDestroy, а также с прослушивателем предпочтений

    @Override
public void onDestroy(){
    super.onDestroy();
    unregisterReceiver(batteryNotifyReceiver);

}

а это мой приемник в сервисе

private final class BatteryNotifyReceiver extends BroadcastReceiver {

    boolean connected;
    @Override
    public void onReceive(Context context, Intent intent) {

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 
        SharedPreferences.Editor edit = prefs.edit();

            updatePreferences(prefs);

        level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);



        if(intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)){
            connected = true;
        }else if(intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)){
            connected = false;
        }else if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)){

                if(level < lastLevel){
                    if(level > 40){
                        edit.putBoolean("first", false).commit();
                        edit.putBoolean("second", false).commit();
                        edit.putBoolean("third", false).commit();
                       edit.putBoolean("fourth",false).commit();                            
                        edit.putBoolean("fifth", false).commit();
                    }
                    if(level == 40){
                        if(!first){
                        notification(context,battColor,battBlink,battVib,battSound);

                        edit.putBoolean("first", true).commit();
                        }
                    }else if(level == 30){
                        if(!second){
                        notification(context,battColor,battBlink,battVib,battSound);

                        edit.putBoolean("second", true).commit();
                        }
                    }else if(level == 20){
                        if(!third){
                        notification(context,battColor,battBlink,battVib,battSound);

                        edit.putBoolean("third", true).commit();
                        }
                    }else if(level == 15){
                        if(!fourth){
                        notification(context,battColor,battBlink,battVib,battSound);

                        edit.putBoolean("fourth", true).commit();
                        }
                    }else if(level == 5){
                        if(!fifth){
                        notification(context,battColor,battBlink,battVib,battSound);

                        edit.putBoolean("fifth", true).commit();
                        }
                    }
                lastLevel = temp;
            }
        }           

        Intent i = new Intent(context,BatteryNotifyReceiver.class);
        context.startService(i);
    }       
}

есть идеи, почему они получат эту ошибку?

Ответы [ 9 ]

199 голосов
/ 29 мая 2011

Корень вашей проблемы находится здесь:

 unregisterReceiver(batteryNotifyReceiver);

Если получатель уже был незарегистрирован (возможно, в коде, который вы не включили в это сообщение) или не был зарегистрирован, тогда позвоните по адресуunregisterReceiver бросков IllegalArgumentException.В вашем случае вам нужно просто добавить специальную попытку / перехват для этого исключения и проигнорировать его (при условии, что вы не можете или не хотите контролировать количество вызовов unregisterReceiver на одном и том же получателе).

21 голосов
/ 30 сентября 2016

Будьте осторожны, когда вы регистрируетесь по

LocalBroadcastManager.getInstance(this).registerReceiver()

, вы не можете отменить регистрацию по

 unregisterReceiver()

, вы должны использовать

LocalBroadcastManager.getInstance(this).unregisterReceiver()

, иначе приложение вылетит, зарегистрируйтесь следующим образом:

09-30 14: 00: 55.458 19064-19064 / com.jialan.guangdian.view E / AndroidRuntime: ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: основной Процесс: com.jialan.guangdian.view, PID: 19064 java.lang.RuntimeException: невозможно остановить службу com.google.android.exoplayer.demo.player.PlayService@141ba331: java.lang.IllegalArgumentException: получатель не зарегистрирован: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 в android.app.ActivityThread.handleStopService (ActivityThread.java:2941) в android.app.ActivityThread.access $ 2200 (ActivityThread.java:148) в android.app.ActivityThread $ H.handleMess (.java: 1395) на android.os.Handler.dispatchMessage (Handler.java:102) на android.os.Looper.loop (Looper.java:135) на android.app.ActivityThread.main (ActivityThread.java:5310)в java.lang.reflect.Method.invoke (НативМетод) в java.lang.reflect.Method.invoke (Method.java:372) в com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:901) в com.android.internal.os.ZygoteInit..java: 769) в android.app.ContextImpl.unregisterReceiver (ContextImpl.java:1794) в android.content.ContextWrapper.unregisterReceiver (ContextWrapper.java:510) в com.google.android.exoplayer.demo.player.PlayService.onDestroy (PlayService.java:542) в android.app.ActivityThread.handleStopService (ActivityThread.java:2924) в android.app.ActivityThread.access $ 2200 (ActivityThread.java:148) в android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1395) на android.os.Handler.dispatchMessage (Handler.java:102) на android.os.Looper.loop (Looper.java:135) на android.app.ActivityThread.main (ActivityThread.java:5310)в java.lang.reflect.Method.invoke (собственный метод) в java.lang.reflect.Method.invoke (Method.java:372) в com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:901) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696)

21 голосов
/ 12 января 2015

Используйте этот код везде для отмены регистрации Receiver:

if (batteryNotifyReceiver!=null) {
    unregisterReceiver(batteryNotifyReceiver);
    batteryNotifyReceiver=null;
}
15 голосов
/ 24 июня 2014

Как упоминалось в других ответах, возникает исключение, поскольку каждый вызов registerReceiver не соответствует ровно одному вызову unregisterReceiver.Почему бы нет?

Activity не всегда имеет соответствующий onDestroy вызов для каждого onCreate вызова.Если системе не хватает памяти, ваше приложение будет удалено без вызова onDestroy.

. Правильное место для вызова registerReceiver - в вызове onResume, а unregisterReceiver в onPause.,Эта пара вызовов всегда совпадает.См. Диаграмму жизненного цикла Activity для более подробной информации.http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Ваш код изменится на:

SharedPreferences mPref
IntentFilter mFilter;

@Override
public void onCreate(){
    super.onCreate();
    mPref = PreferenceManager.getDefaultSharedPreferences(this);
    mFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    filter.addAction(Intent.ACTION_POWER_CONNECTED);
    filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
 }

@Override
public void onResume() {
    registerReceiver(batteryNotifyReceiver,mFilter);
    mPref.registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause(){
     unregisterReceiver(batteryNotifyReceiver, mFilter);
     mPref.unregisterOnSharedPreferenceChangeListener(this);
}
11 голосов
/ 31 января 2012

РЕДАКТИРОВАТЬ: Это ответ для Иназарук и Electrichead ... Я столкнулся с аналогичной проблемой для них и обнаружил следующее ...

Существует давняя ошибка для этой проблемы здесь: http://code.google.com/p/android/issues/detail?id=6191

Похоже, что это началось с Android 2.1 и с тех пор присутствует во всех выпусках Android 2.x.Я не уверен, что это все еще проблема в Android 3.x или 4.x.

В любом случае, этот пост StackOverflow объясняет, как правильно обойти проблему (она не выглядит релевантной по URLно я обещаю, что это так)

Почему слайд с клавиатурой приводит к сбою моего приложения?

6 голосов
/ 23 декабря 2015

Я использовал блок try - catch для временного решения проблемы.

// Unregister Observer - Stop monitoring the underlying data source.
        if (mDataSetChangeObserver != null) {
            // Sometimes the Fragment onDestroy() unregisters the observer before calling below code
            // See <a>/6929563/poluchatel-ne-zaregistriroval-oshibku-isklycheniya</a>
            try  {
                getContext().unregisterReceiver(mDataSetChangeObserver);
                mDataSetChangeObserver = null;
            }
            catch (IllegalArgumentException e) {
                // Check wether we are in debug mode
                if (BuildConfig.IS_DEBUG_MODE) {
                    e.printStackTrace();
                }
            }
        }
3 голосов
/ 28 июля 2014

Объявите получатель как нулевой, а затем поместите методы регистрации и отмены регистрации в onResume () и onPause () операции соответственно.

@Override
        protected void onResume() {
                super.onResume();
                if (receiver == null) {
                        filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
                        filter.addCategory(Intent.CATEGORY_DEFAULT);
                        receiver = new ResponseReceiver();
                        registerReceiver(receiver, filter);
                }

        }      

        @Override
        protected void onPause() {
                super.onPause();
                if (receiver != null) {
                        unregisterReceiver(receiver);
                        receiver = null;
                }



        }
1 голос
/ 14 июля 2017

Для тех, кто столкнется с этой проблемой, и они попробовали все, что было предложено, и ничего не работает, вот как я решил свою проблему вместо того, чтобы делать LocalBroadcastManager.getInstance(this).registerReceiver(...) Сначала я создал локальную переменную типа LocalBroadcastManager,

private LocalBroadcastManager lbman;

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

lbman.registerReceiver(bReceiver);

и

lbman.unregisterReceiver(bReceiver);
0 голосов
/ 26 сентября 2016

Когда компонент пользовательского интерфейса, который регистрирует BR, уничтожается, так же как и BR.Поэтому, когда код становится незарегистрированным, БР уже может быть уничтожен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...