web-dev-qa-db-fra.com

Erreur d'exception du destinataire non enregistré?

Dans ma console de développeur, les utilisateurs continuent de signaler une erreur que je ne peux pas reproduire sur aucun de mes téléphones. Une personne a laissé un message l'informant qu'elle l'obtient lorsqu'elle tente d'ouvrir l'écran des paramètres de mon service de batterie. Comme vous pouvez le constater, il est indiqué 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.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)

Je m'inscris 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);
}

Se désinscrire dans onDestroy et aussi avec un écouteur de préférence

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

}

et ceci est mon récepteur au 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);
    }       
}

aucune idée pourquoi ils obtiendraient cette erreur?

104
tyczj

La racine de votre problème se trouve ici:

 unregisterReceiver(batteryNotifyReceiver);

Si le destinataire était déjà désinscrit (probablement dans le code que vous n'avez pas inclus dans ce message) ou n'était pas enregistré, appelez alors unregisterReceiver jette IllegalArgumentException. Dans votre cas, vous avez juste besoin de mettre try/catch spécial pour cette exception et de l'ignorer (en supposant que vous ne pouvez ou ne voulez pas contrôler le nombre de fois que vous appelez unregisterReceiver sur le même destinataire).

200
inazaruk

Attention, lorsque vous vous inscrivez par

LocalBroadcastManager.getInstance(this).registerReceiver()

vous ne pouvez pas vous désinscrire par

 unregisterReceiver()

tu dois utiliser

LocalBroadcastManager.getInstance(this).unregisterReceiver()

ou l'application va planter, connectez-vous comme suit:

09-30 14: 00: 55.458 19064-19064/com.jialan.guangdian.view E/AndroidRuntime: EXCEPTION FATALE: processus principal: com.jialan.guangdian.view, PID: 19064 Java.lang.RuntimeException: Impossible d'arrêter le service com.google.Android.exoplayer.demo.player.PlayService@141ba331: Java.lang.IllegalArgumentException: Récepteur non enregistré: com.google.Android.exoplayer.demo.player.PlayService$PlayServus$PlayStatusReceiver@19538584 sur Android.application. handleStopService (ActivityThread.Java:2941) à Android.app.ActivityThread.access $ 2200 (ActivityThread.Java:148) à Android.app.ActivityThread $ H.handleMessage (ActivityThread.Java:1395) à Android.os.Handler.dispatchMessage ( Handler.Java:102) à Android.os.Looper.loop (Looper.Java:135) à Android.app.ActivityThread.main (ActivityThread.Java:5310) à Java.lang.reflect.Method.invoke (Méthode native) à Java.lang.reflect.Method.invoke (Method.Java:372) à com.Android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.Java:901) à com.Android.internal.os.ZygoteInit.main (ZygoteInit.Java:696) Causée par: Java.lang.IllegalArgumentException: Récepteur non enregistré: com.google.Android.exoplayer.demo.player.PlayStatusReceiver@19538584 à Android.app.LoadedApk 769) sur Android.app.ContextImpl.unregisterReceiver (ContextImpl.Java:1794) sur Android.content.ContextWrapper.unregisterReceiver (ContextWrapper.Java:510) sur com.google.Android.exoplayer.demo.player.PlayService.onDestroy (PlayServ .Java: 542) à Android.app.ActivityThread.handleStopService (ActivityThread.Java:2924) à Android.app.ActivityThread.access $ 2200 (ActivityThread.Java:148) à Android.app.ActivitéThread $ H.handleMessage (ActivityThread.Java : 1395) sur Android.os.Handler.dispatchMessage (Handler.Java:102) sur Android.os.Looper.loop (Looper.Java:135) sur Android.app.ActivityThread.main (ActivityThread.Java:5310) sur Java .lang.reflect.Method.invoke (Méthode native) sur Java.lang.reflect.Method.invoke (Method.Java:372) sur com.Android.internal.os.Zygo teInit $ MethodAndArgsCaller.run (ZygoteInit.Java:901) sur com.Android.internal.os.ZygoteInit.main (ZygoteInit.Java:696)

21
Chuanhang.gu

Utilisez ce code partout pour unregisterReceiver:

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

Comme mentionné dans d'autres réponses, l'exception est levée car chaque appel à registerReceiver ne correspond pas à un seul appel à unregisterReceiver. Pourquoi pas?

Un Activity ne possède pas toujours un appel onDestroy correspondant pour chaque appel onCreate. Si le système manque de mémoire, votre application est expulsée sans appeler onDestroy.

Le bon endroit pour mettre un appel registerReceiver est dans l'appel onResume et unregisterReceiver dans onPause. Cette paire d'appels est toujours appariée. Voir le diagramme de cycle de vie d'activité pour plus de détails. http://developer.Android.com/reference/Android/app/Activity.html#ActivityLifecycle

Votre code changerait à:

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);
}
15
Curmudgeonlybumbly

EDIT: C’est la réponse pour inazaruk et electrichead ... Je leur avais rencontré un problème similaire et découvert ce qui suit ...

Il existe un bogue de longue date concernant ce problème ici: http://code.google.com/p/Android/issues/detail?id=6191

On dirait que cela a commencé autour de Android 2.1 et est présent dans toutes les Android 2.x versions depuis. Je ne suis pas sûr qu'il s'agisse toujours d'une problème dans Android 3.x ou 4.x cependant.

Quoi qu'il en soit, cet article de StackOverflow explique comment résoudre correctement le problème (il n'a pas l'air pertinent par l'URL, mais je vous promets que c'est le cas)

Pourquoi le clavier glisse-t-il en panne mon application?

11
Justin

J'ai utilisé un bloc try - catch 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();
                }
            }
        }
6
Rowland Mtetezi

Déclarez le destinataire comme nul, puis placez les méthodes register et unsregister 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;
                }



        }
3
Sagar D

Pour tous ceux qui rencontreront ce problème et essaieront tout ce qui a été suggéré et que rien ne fonctionne toujours, c’est ainsi que 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 l’annulation de l’enregistrement sur le destinataire, c’est-à-dire

lbman.registerReceiver(bReceiver);

et

lbman.unregisterReceiver(bReceiver);
1
nada

Lorsque le composant d'interface utilisateur qui enregistre le BR est détruit, le BR l'est également. Par conséquent, lorsque le code se désinscrit, le BR peut déjà avoir été détruit.

0
ousanmaz