接收方未注册异常错误?

tyc*_*czj 106 android broadcastreceiver illegalargumentexception

在我的开发者控制台中,人们不断报告我无法在任何手机上重现的错误.一个人在尝试打开电池服务的设置屏幕时留下了一条消息说他得到了它.从错误中可以看出,它表示接收器未注册.

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)
Run Code Online (Sandbox Code Playgroud)

我注册的是我的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);
}
Run Code Online (Sandbox Code Playgroud)

取消注册onDestroy以及首选项侦听器

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

}
Run Code Online (Sandbox Code Playgroud)

这是我服务的接收者

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);
    }       
}
Run Code Online (Sandbox Code Playgroud)

知道他们为什么会得到那个错误吗?

ina*_*ruk 201

问题的根源在于:

 unregisterReceiver(batteryNotifyReceiver);
Run Code Online (Sandbox Code Playgroud)

如果接收方已经取消注册(可能在您未在此帖中包含的代码中)或未注册,则调用unregisterReceiverthrows IllegalArgumentException.在您的情况下,您需要为此异常添加特殊的try/catch并忽略它(假设您不能或不想控制unregisterReceiver在同一个接收器上调用的次数).

  • Android平台本身可以做到这一点吗?我有类似于上面的代码,但没有其他代码可以取消注册服务,我得到相同的异常. (31认同)
  • 我有同样的问题@ electrichead,我看不到接收器在onDestroy()之前取消注册的位置,除非Android在某处为我做这个.... (2认同)

xna*_*gyg 21

对于unregisterReceiver,请到处使用此代码:

if (batteryNotifyReceiver!=null) {
    unregisterReceiver(batteryNotifyReceiver);
    batteryNotifyReceiver=null;
}
Run Code Online (Sandbox Code Playgroud)

  • 还是发生在我身上.更好地使用try-catch. (6认同)
  • 尝试catch语句更好 (2认同)

Chu*_*.gu 21

注册时要小心

LocalBroadcastManager.getInstance(this).registerReceiver()
Run Code Online (Sandbox Code Playgroud)

你无法取消注册

 unregisterReceiver()
Run Code Online (Sandbox Code Playgroud)

你必须使用

LocalBroadcastManager.getInstance(this).unregisterReceiver()
Run Code Online (Sandbox Code Playgroud)

或应用程序将崩溃,记录如下:

09-30 14:00:55.458 19064-19064/com.jialan.guangdian.view E/AndroidRuntime:FATAL EXCEPTION:main进程:com.jialan.guangdian.view,PID:19064 java.lang.RuntimeException:无法停止服务com.google.android.exoplayer.demo.player.PlayService@141ba331:java.lang.IllegalArgumentException:Receiver未注册:android.app.ActivityThread中的com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584. android.app.Handler.dispatchMessage上的android.app.ActivityThread.access $ 2200(ActivityThread.java:148)android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1395)上的handleStopService(ActivityThread.java:2941) Handler.java:102)在android.app.Looper.loop(Looper.java:135)的android.app.ActivityThread.main(ActivityThread.java:5310)at java.lang.reflect.Method.invoke(Native Method)在java.lang.reflect.Method.invoke(Method.java:372)的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:901)at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696)引起:java.lang.IllegalArgumentException:Receiver未注册:com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java: 769)在android.apptent.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.access $ 2200(ActivityThread.java:148)的android.app.ActivityThread.handleStopService(ActivityThread.java:2924)android.app.ActivityThread $ H.handleMessage(ActivityThread.java) :1395)在Android.os.Handler.dispatchMessage(Handler.java:102)的android.app.Looper.loop(Looper.java:135)在android.app.ActivityThread.main(ActivityThread.java:5310)在java位于com.android.internal.os.ZygoteInit $ MethodA的java.lang.reflect.Method.invoke(Method.java:372)上的.lang.reflect.Method.invoke(Native Method)ndArgsCaller.run(ZygoteInit.java:901)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) 


Cur*_*bly 16

正如在其他答案中所提到的,异常被抛出,因为每次调用registerReceiver都没有被一次调用匹配unregisterReceiver.为什么不?

一个Activity并不总是有一个匹配onDestroy呼吁每个onCreate呼叫.如果系统内存不足,您的应用程序将在不调用的情况下被逐出onDestroy.

registerReceiver拨打电话的正确位置在onResume通话中,并且unregisterReceiver在通话中onPause.这对呼叫始终匹配.有关更多详细信息,请参阅活动生命周期图. 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);
}
Run Code Online (Sandbox Code Playgroud)

  • 您是否真的建议留下一个抛出无效处理程序的异常,因为删除它会花费一些CPU周期? (2认同)

Jus*_*tin 11

编辑:这是inazaruk和electrichead的答案......我遇到了类似的问题并发现了以下内容......

这里有一个长期存在的问题:http://code.google.com/p/android/issues/detail?id = 6191

看起来它始于Android 2.1并且已经出现在所有Android 2.x版本中.我不确定它是否仍然是Android 3.x或4.x中的问题.

无论如何,这篇StackOverflow文章解释了如何正确解决问题(它看起来与URL无关,但我保证是这样)

为什么键盘滑动会导致我的应用崩溃?


Row*_*ezi 7

我使用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();
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)