Ошибка регистрации зарегистрированного получателя?
В моей консоли разработчика люди сообщают об ошибке, которую я не могу воспроизвести на каком-либо телефоне, который у меня есть. Один человек оставил сообщение о том, что он получает его, когда они пытаются открыть экран настроек моей службы батарей. Как вы можете видеть из этой ошибки, он говорит, что приемник не зарегистрирован.
java.lang.RuntimeException: Unable to stop service [email protected]: java.lang.IllegalArgumentException: Receiver not registered: [email protected]
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$B[email protected]
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);
}
}
любая идея, почему они получат эту ошибку?
Ответы
Ответ 1
Корень проблемы находится здесь:
unregisterReceiver(batteryNotifyReceiver);
Если получатель уже был незарегистрирован (возможно, в коде, который вы не включили в этот пост) или не был зарегистрирован, вызовите unregisterReceiver
throws IllegalArgumentException
. В вашем случае вам нужно просто добавить специальный try/catch для этого исключения и игнорировать его (если вы не можете или не хотите контролировать количество раз, когда вы вызываете unregisterReceiver
на том же получателе).
Ответ 2
Используйте этот код везде для unregisterReceiver:
if (batteryNotifyReceiver!=null) {
unregisterReceiver(batteryNotifyReceiver);
batteryNotifyReceiver=null;
}
Ответ 3
Как упоминалось в других ответах, исключение возникает потому, что каждый вызов registerReceiver
не соответствует точно одному вызову unregisterReceiver
. Почему бы и нет?
An 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);
}
Ответ 4
РЕДАКТИРОВАТЬ: Это ответ для инзазарука и электрогитара... Я столкнулся с подобной проблемой и выяснил следующее...
Здесь существует давняя ошибка: http://code.google.com/p/android/issues/detail?id=6191
Похоже, что он начинался с Android 2.1 и с тех пор присутствует во всех версиях Android 2.x. Я не уверен, что это все еще проблема в Android 3.x или 4.x.
В любом случае, эта статья StackOverflow объясняет, как правильно решить проблему (она не выглядит релевантной URL-адресом, но я обещаю, что это так)
Почему сканирование со слайдов на клавиатуре моего приложения?
Ответ 5
Будьте осторожны, когда вы зарегистрируетесь на
LocalBroadcastManager.getInstance(this).registerReceiver()
вы не можете отменить регистрацию
unregisterReceiver()
вы должны использовать
LocalBroadcastManager.getInstance(this).unregisterReceiver()
или приложение выйдет из строя, залогинится следующим образом:
09-30 14: 00: 55.458 19064-19064/com.jialan.guangdian.view E/AndroidRuntime: FATAL EXCEPTION: главная Процесс: com.jialan.guangdian.view, PID: 19064 java.lang.RuntimeException: невозможно остановить службу [email protected]: java.lang.IllegalArgumentException: Получатель не зарегистрирован: com.google.android.exoplayer.demo.player.PlayService $PlayStatusReceiver @19538584 на 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) на android.os.Handler.dispatchMessage(Handler.java:102) на android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5310) в java.lang.reflect.Method.invoke(собственный метод) в 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) Причина: java.lang.IllegalArgumentException: Получатель не зарегистрирован: com.goog[email protected]19538584 at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:769) в android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1794) at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:510) на 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) на android.os.Handler.dispatchMessage(Handler.java:102) на android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5310) в java.lang.reflect.Method.invoke(собственный метод) в 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)
Ответ 6
Я использовал блок 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();
}
}
}
Ответ 7
Объявите приемник как нуль, а затем поместите методы регистрации и отмены регистрации в 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;
}
}
Ответ 8
Когда компонент пользовательского интерфейса, который регистрирует BR, уничтожается, так же как и BR. Поэтому, когда код доходит до регистрации, BR может быть уже уничтожен.
Ответ 9
Для всех, кто столкнется с этой проблемой, и они попробовали все, что было предложено, и ничего не работает, вот как я отсортировал свою проблему, а не выполнил LocalBroadcastManager.getInstance(this).registerReceiver(...)
Сначала я создал локальную переменную типа LocalBroadcastManager,
private LocalBroadcastManager lbman;
И использовал эту переменную для регистрации и отмены регистрации в трансляторе вещания, то есть
lbman.registerReceiver(bReceiver);
и
lbman.unregisterReceiver(bReceiver);