Receiver not registered exception error?

旧街凉风 提交于 2019-11-26 21:59:53

The root of your problem is located here:

 unregisterReceiver(batteryNotifyReceiver);

If the receiver was already unregistered (probably in the code that you didn't include in this post) or was not registered, then call to unregisterReceiver throws IllegalArgumentException. In your case you need to just put special try/catch for this exception and ignore it (assuming you can't or don't want to control number of times you call unregisterReceiver on the same recevier).

Use this code everywhere for unregisterReceiver:

if (batteryNotifyReceiver!=null) {
    unregisterReceiver(batteryNotifyReceiver);
    batteryNotifyReceiver=null;
}
Chuanhang.gu

Be careful, when you register by

LocalBroadcastManager.getInstance(this).registerReceiver()

you can't unregister by

 unregisterReceiver()

you must use

LocalBroadcastManager.getInstance(this).unregisterReceiver()

or app will crash, log as follow:

09-30 14:00:55.458 19064-19064/com.jialan.guangdian.view E/AndroidRuntime: FATAL EXCEPTION: main Process: com.jialan.guangdian.view, PID: 19064 java.lang.RuntimeException: Unable to stop service com.google.android.exoplayer.demo.player.PlayService@141ba331: java.lang.IllegalArgumentException: Receiver not registered: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at android.app.ActivityThread.handleStopService(ActivityThread.java:2941) at android.app.ActivityThread.access$2200(ActivityThread.java:148) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1395) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5310) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) Caused by: java.lang.IllegalArgumentException: Receiver not registered: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:769) at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1794) at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:510) at com.google.android.exoplayer.demo.player.PlayService.onDestroy(PlayService.java:542) at android.app.ActivityThread.handleStopService(ActivityThread.java:2924) at android.app.ActivityThread.access$2200(ActivityThread.java:148)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1395)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:135)  at android.app.ActivityThread.main(ActivityThread.java:5310)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) 

As mentioned in other answers, the exception is being thrown because each call to registerReceiver is not being matched by exactly one call to unregisterReceiver. Why not?

An Activity does not always have a matching onDestroy call for every onCreate call. If the system runs out of memory, your app is evicted without calling onDestroy.

The correct place to put a registerReceiver call is in the onResume call, and unregisterReceiver in onPause. This pair of calls is always matched. See the Activity lifecycle diagram for more details. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Your code would change to:

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

EDIT: This is the answer for inazaruk and electrichead... I had run into a similar issue to them and found out the following...

There is a long-standing bug for this problem here: http://code.google.com/p/android/issues/detail?id=6191

Looks like it started around Android 2.1 and has been present in all of the Android 2.x releases since. I'm not sure if it is still a problem in Android 3.x or 4.x though.

Anyway, this StackOverflow post explains how to workaround the problem correctly (it doesn't look relevant by the URL but I promise it is)

Why does keyboard-slide crash my app?

I used a try - catch block to solve the issue temporarily.

// 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();
                }
            }
        }

Declare receiver as null and then Put register and unregister methods in onResume() and onPause() of the activity respectively.

@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;
                }



        }

For anybody who will come upon this problem and they tried all that was suggested and nothing still works, this is how I sorted my problem, instead of doing LocalBroadcastManager.getInstance(this).registerReceiver(...) I first created a local variable of type LocalBroadcastManager,

private LocalBroadcastManager lbman;

And used this variable to carry out the registering and unregistering on the broadcastreceiver, that is

lbman.registerReceiver(bReceiver);

and

lbman.unregisterReceiver(bReceiver);

When the UI component that registers the BR is destroyed, so is the BR. Therefore when the code gets to unregistering, the BR may have already been destroyed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!