接收方没有注册异常错误?

在我的开发者控制台中,人们不断地报告一个错误,我无法在任何手机上重现这个错误。一个人留言说,当他们试图打开我的电池服务设置屏幕时,他得到了它。正如您可以从错误中看到的,它说接收方未注册。

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)

I register 在我的 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);
}
}

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

119051 次浏览

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).

编辑: 这就是伊纳扎鲁克和电头的答案... ... 我遇到了与他们类似的问题,发现了以下... ..。

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

看起来它是从 Android 2.1开始的,并且一直存在于所有的 Android 2.x 版本中。不过我不确定这个问题在 Android 3.x 或者4. x 中是否仍然存在。

不管怎样,这篇 StackOverflow 的文章解释了如何正确地解决这个问题(从 URL 来看它并不相关,但我保证它是相关的)

Why does keyboard-slide crash my app?

正如在其他答案中提到的,引发异常是因为对 registerReceiver的每个调用没有与对 unregisterReceiver的一个调用完全匹配。为什么不呢?

对于每个 onCreate调用,Activity并不总是具有匹配的 onDestroy调用。如果系统内存不足,您的应用程序将在不调用 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);
}

将接收方声明为 null,然后将 register 和 unregister 方法分别放在活动的 onResume ()和 onPuse ()中。

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

在 unregisterReceiver 的任何地方使用这个代码:

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

我使用 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();
}
}
}

当注册 BR 的 UI 组件被销毁时,BR 也会被销毁。因此,当代码注销时,BR 可能已经被销毁。

注册时要小心

LocalBroadcastManager.getInstance(this).registerReceiver()

你不能取消注册

 unregisterReceiver()

你必须使用

LocalBroadcastManager.getInstance(this).unregisterReceiver()

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

09-3014:00:55.45819064-19064/com.jialan.guangdian.view E/AndroidRuntime: FATAL EXCEPTION: main 09-3014:00:55.45819064-19064/com.jialan.guangdian.view E/AndroidRuntime: FATAL EXCEPTION: main 过程: com.jialan.guangdian.view,PID: 19064 无法停止服务 com.google.android.exoplayer.demo.player. PlayService@141ba331: java.lang. IllegalArgumentException: 未注册的接收者: com.google.android.exoplayer.demo.player. PlayService $PlayStatusReceiver@19538584 ActivityThread.handleStopService (ActivityThread.java: 2941) ActivityThread.access $2200(ActivityThread.java: 148) ActivityThread $H.handleMessage (ActivityThread.java: 1395) 在 android.os 处理器。调度消息(Handler.java: 102) 在 android.os. Looper.loop (Looper.java: 135) ActivityThread.main (ActivityThread.java: 5310) at java.lang.reflect.Method.invoke(Native Method) 在 java.lang.response. Method.emon (Method.java: 372) ZygoteInit $MethodAndArgsCaller.run (ZygoteInit.java: 901) JygoteInit.main (ZygoteInit.java: 696) 由 java.lang. IllegalArgumentException: Receiver not regired: com.google.android.exoplayer.demo.player. PlayService $PlayStatusReceiver@19538584引起异常: Receiver not regired: com.google.android.exoplayer.demo.player. PlayService $PlayStatusReceiver@19538584 在 android.app. LoadedApk.forget ReceiverDispatcher (LoadedApk.java: 769) ContextImp.unregisterReceiver (ContextImp.java: 1794) 在 android.content. ContextWrapper.unregisterReceiver (ContextWrapper.java: 510) 在 com.google.android.exoplayer.demo.player. PlayService.onDestroy (PlayService.java: 542) ActivityThread.handleStopService (ActivityThread.java: 2924) ActivityThread.access $2200(ActivityThread.java: 148) ActivityThread $H.handleMessage (ActivityThread.java: 1395) 在 android.os 处理器。调度消息(Handler.java: 102) at android.os.Looper.loop(Looper.java:135)  ActivityThread.main (ActivityThread.java: 5310) 调用(本机方法) 在 java.lang.response. Method.emon (Method.java: 372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696) 

对于任何遇到这个问题的人来说,他们尝试了所有的建议,但没有一个仍然有效,这是我如何排序我的问题,而不是做 LocalBroadcastManager.getInstance(this).registerReceiver(...) 我首先创建了一个 LocalBroadcastManager 类型的局部变量,

private LocalBroadcastManager lbman;

并利用这个变量在广播接收机上进行注册和注销

lbman.registerReceiver(bReceiver);

还有

lbman.unregisterReceiver(bReceiver);

假设您的 broadcastReceiver是这样定义的:

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {


// your code


}
};

如果你在一个活动中使用 LocalBroadcast,那么这就是你注销的方式:

LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);

如果你在片段中使用 LocalBroadcast,那么这就是你注销的方式:

LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(broadcastReceiver);

如果你在一个活动中使用普通的广播,那么这就是你注销的方式:

unregisterReceiver(broadcastReceiver);

如果你在片段中使用普通的广播,那么这就是你注销的方式:

getActivity().unregisterReceiver(broadcastReceiver);

Unregister broadcast receiver in Try Catch

    try {
unregisterReceiver(receiver);
} catch (IllegalArgumentException e) {
System.out.printf(e.getMessage());
}