W mojej konsoli programisty ludzie zgłaszają błąd, którego nie mogę odtworzyć na żadnym moim telefonie. Jedna osoba zostawiła wiadomość, że dostaje ją, gdy próbują otworzyć ekran ustawień mojej usługi baterii. Jak widać po błędzie jest napisane, że odbiornik nie jest zarejestrowany.
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)
Rejestruję się w moim 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);
}
Wyrejestruj się z onDestroy, a także z odbiornikiem preferencji
@Override
public void onDestroy(){
super.onDestroy();
unregisterReceiver(batteryNotifyReceiver);
}
a to jest mój odbiornik w serwisie
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);
}
}
masz pojęcie, dlaczego otrzymają ten błąd?
LocalBroadcastManager.getInstance(context).unregisterReceiver()
lubcontext.unregisterReceiver()
Uważaj, rejestrując się do
nie możesz się wyrejestrować
musisz użyć
lub aplikacja ulegnie awarii, zaloguj się w następujący sposób:
źródło
Użyj tego kodu wszędzie, aby wyrejestrować odbiorcę:
źródło
Jak wspomniano w innych odpowiedziach, wyjątek jest generowany, ponieważ każde wywołanie funkcji
registerReceiver
nie jest dopasowywane przez dokładnie jedno wywołanie dounregisterReceiver
. Dlaczego nie?An
Activity
nie zawsze ma pasująceonDestroy
wywołanie dla każdegoonCreate
połączenia. Jeśli w systemie zabraknie pamięci, Twoja aplikacja zostanie usunięta bez dzwonieniaonDestroy
.Właściwe miejsce do wykonania
registerReceiver
połączenia toonResume
wezwanie iunregisterReceiver
wejścieonPause
. Ta para wywołań jest zawsze dopasowana. Aby uzyskać więcej informacji, zobacz diagram cyklu życia działania. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycleTwój kod zmieniłby się na:
źródło
EDYCJA: To jest odpowiedź na inazaruk i electrichead ... Napotkałem podobny problem do nich i dowiedziałem się, co następuje ...
Ten problem istnieje od dawna tutaj: http://code.google.com/p/android/issues/detail?id=6191
Wygląda na to, że zaczęło się od Androida 2.1 i od tego czasu było obecne we wszystkich wydaniach Androida 2.x. Nie jestem pewien, czy nadal jest to problem w systemie Android 3.x lub 4.x.
W każdym razie ten post StackOverflow wyjaśnia, jak poprawnie obejść problem (nie wygląda to na odpowiedni adres URL, ale obiecuję, że tak jest)
Dlaczego keyboard-slide powoduje awarię mojej aplikacji?
źródło
Użyłem bloku try - catch, aby tymczasowo rozwiązać problem.
źródło
Zadeklaruj odbiorcę jako null, a następnie umieść register i wyrejestruj metody odpowiednio w onResume () i onPause () działania.
źródło
Kiedy komponent UI, który rejestruje BR jest zniszczony, tak samo jest BR. Dlatego, gdy kod zostanie wyrejestrowany, BR może już zostać zniszczona.
źródło
Dla każdego, kto napotka ten problem i wypróbował wszystko, co zostało zasugerowane, i nic nadal nie działa, tak posortowałem mój problem, zamiast robić
LocalBroadcastManager.getInstance(this).registerReceiver(...)
, najpierw utworzyłem lokalną zmienną typu LocalBroadcastManager,I użył tej zmiennej do przeprowadzenia rejestracji i wyrejestrowania w odbiorniku
i
źródło
Załóżmy, że twój
broadcastReceiver
jest zdefiniowany w ten sposób:Jeśli używasz
LocalBroadcast
w działaniu, wyrejestrujesz się w następujący sposób:Jeśli używasz
LocalBroadcast
we fragmencie, wyrejestrujesz się w następujący sposób:Jeśli używasz normalnej transmisji w działaniu, wyrejestrujesz się w następujący sposób:
Jeśli używasz normalnej transmisji we fragmencie, wyrejestrujesz się w ten sposób:
źródło