Récepteur non enregistré erreur d'exception?
dans ma console de développeur, les gens continuent de signaler une erreur que je ne peux reproduire sur Aucun téléphone que j'ai. Une personne a laissé un message disant qu'il obtient quand ils essaient d'ouvrir l'écran des paramètres de la batterie de mon service. Comme vous pouvez le voir à partir de l'erreur, il dit que le récepteur n'est pas enregistré.
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.access00(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)
je le registre est dans mon 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);
}
annuler l'inscription dans onDestroy et aussi avec une préférence listener
@Override
public void onDestroy(){
super.onDestroy();
unregisterReceiver(batteryNotifyReceiver);
}
et voici mon récepteur dans le service
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);
}
}
vous savez pourquoi ils ont eu cette erreur?
9 réponses
la racine de votre problème se trouve ici:
unregisterReceiver(batteryNotifyReceiver);
si le destinataire n'était pas déjà enregistré (probablement dans le code que vous n'avez pas inclus dans ce message) ou n'était pas enregistré, alors appeler unregisterReceiver
lance IllegalArgumentException
. Dans votre cas, vous avez juste besoin de mettre spécial essayer / attraper pour cette exception et l'ignorer (en supposant que vous ne pouvez pas ou ne voulez pas contrôler le nombre de fois où vous appelez unregisterReceiver
sur le même receveur).
utilisez ce code partout pour non-livraison:
if (batteryNotifyReceiver!=null) {
unregisterReceiver(batteryNotifyReceiver);
batteryNotifyReceiver=null;
}
attention, quand vous vous enregistrez par
LocalBroadcastManager.getInstance(this).registerReceiver()
vous ne pouvez pas annuler l'enregistrement par
unregisterReceiver()
vous devez utiliser
LocalBroadcastManager.getInstance(this).unregisterReceiver()
ou app crash, se connecter comme suit:
09-30 14:00:55.458 19064-19064/com.jialan.guangdian.vue E/AndroidRuntime: FATAL EXCEPTION: main Processus: com.jialan.guangdian.vue, PID: 19064 Java.lang.RuntimeException: impossible d'arrêter le service com.Google.Android.exoplayer.démo.joueur.PlayService@141ba331: java.lang.IllegalArgumentException: récepteur non enregistré: com.Google.Android.exoplayer.démo.joueur.PlayService$PlayStatusReceiver@19538584 à Android.App.ActivityThread.handleStopService (ActivityThread.java: 2941) au android.App.ActivityThread.accès 2200$(ActivityThread.java: 148) au android.App.ActivityThread$H. handleMessage (ActivityThread.java: 1395) à Android.OS.Manipulateur.dispatchMessage (Handler.java: 102) au android.OS.Looper.boucle (Looper.java: 135) au android.App.ActivityThread.main (ActivityThread.java: 5310) à java.lang.refléter.Méthode.invoke (méthode Native)) à java.lang.refléter.Méthode.invoke(la Méthode.java: 372) au com.Android.interne.OS.ZygoteInit $ MethodAndArgsCaller.exécuter(ZygoteInit.java: 901) au com.Android.interne.OS.ZygoteInit.main(ZygoteInit.java: 696) Causées par: Java.lang.IllegalArgumentException: récepteur non enregistré: com.Google.Android.exoplayer.démo.joueur.PlayService$PlayStatusReceiver@19538584 au android.App.LoadedApk.forget receiverdispatcher (LoadedApk.java: 769) au android.App.ContextImpl.unmisterreceiver (ContextImpl.java: 1794) au android.contenu.ContextWrapper.unmisterreceiver (ContextWrapper.java: 510) au com.Google.Android.exoplayer.démo.joueur.PlayService.onDestroy (PlayService.java: 542) au android.App.ActivityThread.handleStopService (ActivityThread.java: 2924) au android.App.ActivityThread.accès 2200$(ActivityThread.java: 148) au android.App.ActivityThread$H. handleMessage (ActivityThread.java: 1395) au android.OS.Manipulateur.dispatchMessage (Handler.java: 102) au android.OS.Looper.boucle (Looper.java: 135) au android.App.ActivityThread.main (ActivityThread.java: 5310) à java.lang.refléter.Méthode.invoke (méthode Native)) à java.lang.refléter.Méthode.invoke(la Méthode.java: 372) à COM.Android.interne.OS.ZygoteInit $ MethodAndArgsCaller.exécuter(ZygoteInit.java: 901) au com.Android.interne.OS.ZygoteInit.main(ZygoteInit.java: 696)
comme mentionné dans d'autres réponses, l'exception est lancée parce que chaque appel à registerReceiver
ne correspond pas exactement à un appel à unregisterReceiver
. Pourquoi pas?
Un Activity
n'a pas toujours une correspondance onDestroy
appel à tous onCreate
appel. Si le système manque de mémoire, votre application est expulsé sans appel onDestroy
.
l'endroit approprié pour placer un appel registerReceiver
est dans l'appel onResume
, et unregisterReceiver
dans onPause
. Cette paire d'appels est toujours accompagnée. Voir le diagramme du cycle de vie des activités pour plus de détails.
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
votre code changerait en:
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);
}
EDIT: C'est la réponse pour inazaruk et electrichead... J'avais rencontré un problème similaire à eux et j'ai découvert ce qui suit...
il y a un bug de longue date pour ce problème ici: http://code.google.com/p/android/issues/detail?id=6191
semble comme il a commencé autour D'Android 2.1 et a été présent dans tous les Android 2.X sort depuis. Je ne suis pas sûr que ce soit toujours un problème sur Android 3.x ou 4.x bien.
quoi qu'il en soit, ce post StackOverflow explique comment contourner le problème correctement (il ne semble pas pertinent par L'URL mais je vous promets qu'il est)
j'ai utilisé un bloc d'essai pour résoudre le problème temporairement.
// 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();
}
}
}
déclare le récepteur nul et met les méthodes de registre et de non-enregistrement dans onResume() et onPause() de l'activité respectivement.
@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;
}
}
lorsque la composante D'assurance-chômage qui enregistre le re est détruite, il en est de même pour le re. Par conséquent, lorsque le code arrive à se désinscrire, le BR peut avoir déjà été détruit.
pour tous ceux qui vont venir sur ce problème et ils ont essayé tout ce qui a été suggéré et rien ne fonctionne encore, c'est comment j'ai réglé mon problème, au lieu de faire LocalBroadcastManager.getInstance(this).registerReceiver(...)
J'ai d'abord créé une variable locale de type LocalBroadcastManager,
private LocalBroadcastManager lbman;
et utilisé cette variable pour effectuer l'enregistrement et le désenregistrement sur le broadcastreceiver, c'est-à-dire
lbman.registerReceiver(bReceiver);
et
lbman.unregisterReceiver(bReceiver);