Приемник не зарегистрирован ошибка?

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

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.access00(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 ответов


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

 unregisterReceiver(batteryNotifyReceiver);

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


используйте этот код везде для unregisterReceiver:

if (batteryNotifyReceiver!=null) {
    unregisterReceiver(batteryNotifyReceiver);
    batteryNotifyReceiver=null;
}

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

LocalBroadcastManager.getInstance(this).registerReceiver()

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

 unregisterReceiver()

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

LocalBroadcastManager.getInstance(this).unregisterReceiver()

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

09-30 14:00:55.458 19064-19064/com.jialan.guangdian.просмотр E / AndroidRuntime: фатальное исключение: main Процесс: ком.jialan.guangdian.вид, PID: 19064 Ява.ленг.RuntimeException: не удалось остановить службу com.гуглить.андроид.экзопласт.демонстрация.игрок.PlayService@141ba331: java.ленг.IllegalArgumentException: приемник не зарегистрирован: com.гуглить.андроид.экзопласт.демонстрация.игрок.PlayService$PlayStatusReceiver@19538584 на Андроид.приложение.ActivityThread.handleStopService (ActivityThread.java: 2941) на Андроид.приложение.ActivityThread.доступ к$2200 (ActivityThread.java: 148) на Андроид.приложение.ActivityThread$H. handleMessage (ActivityThread.java: 1395) на Андроид.ОС.Обработчик.dispatchMessage(обработчика.java: 102) на Андроид.ОС.Петлитель.петля (Looper.java: 135) на Андроид.приложение.ActivityThread.main (ActivityThread.java: 5310) на Яве.ленг.отражать.Метод.invoke (собственный метод) на Яве.ленг.отражать.Метод.метод Invoke.java: 372) на com.андроид.внутренний.ОС.ZygoteInit$MethodAndArgsCaller.беги(Зайготейнит.java: 901) по ком.андроид.внутренний.ОС.Зиготейнит.main (ZygoteInit.java: 696) Вызвано: java.ленг.IllegalArgumentException: приемник не зарегистрирован: com.гуглить.андроид.экзопласт.демонстрация.игрок.PlayService$PlayStatusReceiver@19538584 на Андроид.приложение.LoadedApk.forgetReceiverDispatcher (LoadedApk.java: 769) на Андроид.приложение.ContextImpl.unregisterReceiver (ContextImpl.java: 1794) на Андроид.содержание.ContextWrapper.unregisterReceiver(ContextWrapper.java: 510) по ком.гуглить.андроид.экзопласт.демонстрация.игрок.PlayService.onDestroy(PlayService.java: 542) на Андроид.приложение.ActivityThread.handleStopService (ActivityThread.java: 2924) на Андроид.приложение.ActivityThread.доступ к$2200 (ActivityThread.java: 148)  на андроид.приложение.ActivityThread$H. handleMessage (ActivityThread.java: 1395)  на Андроид.ОС.Обработчик.dispatchMessage(обработчика.java: 102)  на Андроид.ОС.Петлитель.петля (Looper.java: 135)  на Андроид.приложение.ActivityThread.main (ActivityThread.java: 5310)  на Яве.ленг.отражать.Метод.invoke (собственный метод)  на Яве.ленг.отражать.Метод.метод Invoke.java: 372)  по ком.андроид.внутренний.ОС.ZygoteInit$MethodAndArgsCaller.беги(Зайготейнит.java: 901)  на com.андроид.внутренний.ОС.Зиготейнит.main (ZygoteInit.java: 696)


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

An 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);
}

EDIT: это ответ для inazaruk и electrichead... Я столкнулся с аналогичной проблемой для них и узнал следующее...

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

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

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

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


я использовал блок 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>http://stackoverflow.com/questions/6165070/receiver-not-registered-exception-error</a>
            try  {
                getContext().unregisterReceiver(mDataSetChangeObserver);
                mDataSetChangeObserver = null;
            }
            catch (IllegalArgumentException e) {
                // Check wether we are in debug mode
                if (BuildConfig.IS_DEBUG_MODE) {
                    e.printStackTrace();
                }
            }
        }

объявите receiver как null, а затем поместите методы register и unregister в 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;
                }



        }

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


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

private LocalBroadcastManager lbman;

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

lbman.registerReceiver(bReceiver);

и

lbman.unregisterReceiver(bReceiver);