web-dev-qa-db-ja.com

受信者が登録されていない例外エラーですか?

私の開発者コンソールでは、私が持っているどの電話でも再現できないエラーを報告し続けています。ある人は、私のバッテリーサービスの設定画面を開こうとするとメッセージが表示されるというメッセージを残しました。エラーからわかるように、レシーバーが登録されていないと表示されます。

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)

登録するのは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);
    }       
}

なぜ彼らはそのエラーを取得するのでしょうか?

104
tyczj

問題の根本は次の場所にあります。

 unregisterReceiver(batteryNotifyReceiver);

受信者が既に登録解除されている場合(おそらくこの投稿に含まれていないコードで)または登録されていない場合は、unregisterReceiverを呼び出してIllegalArgumentExceptionをスローします。あなたの場合、この例外に特別なtry/catchを入れて無視する必要があります(同じレシーバーでunregisterReceiverを呼び出す回数を制御できない、または制御したくない場合)。

200
inazaruk

で登録するときは注意してください

LocalBroadcastManager.getInstance(this).registerReceiver()

で登録を解除することはできません

 unregisterReceiver()

あなたは使わなければなりません

LocalBroadcastManager.getInstance(this).unregisterReceiver()

またはアプリがクラッシュします。次のようにログインします。

09-30 14:00:55.458 19064-19064/com.jialan.guangdian.view E/AndroidRuntime:致命的な例外:メインプロセス:com.jialan.guangdian.view、PID:19064 Java.lang.RuntimeException:サービスを停止できませんcom.google.Android.exoplayer.demo.player.PlayService@141ba331:Java.lang.IllegalArgumentException:Receiver not registered:com.google.Android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at 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)at Android.os.Handler.dispatchMessage( Handler.Java:102)at Android.os.Looper.loop(Looper.Java:135)at Android.app.ActivityThread.main(ActivityThread.Java:5310)at Java.lang.reflect.Method.invoke(Native Method) 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:Receiver not registered:com.google.Android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at Android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.Java: 769)at Android.app.ContextImpl.unregisterReceiver(ContextImpl.Java:1794)Android.content.ContextWrapper.unregisterReceiver(ContextWrapper.Java:510)at 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)Android.app.ActivityThread.main(ActivityThread.Java:5310)Java .lang.reflect.Method.invoke(Native Method)at Java.lang.reflect.Method.invoke(Method.Java:372)at com.Android.internal.os.Zygo com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:696)のteInit $ MethodAndArgsCaller.run(ZygoteInit.Java:901)

21
Chuanhang.gu

UnregisterReceiverにはどこでも次のコードを使用します。

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

他の回答で述べたように、registerReceiverへの各呼び出しはunregisterReceiverへの1回の呼び出しと一致しないため、例外がスローされます。何故なの?

Activityには、すべてのonDestroy呼び出しに対応するonCreate呼び出しが常にあるとは限りません。システムのメモリが不足すると、onDestroyを呼び出さずにアプリが削除されます。

registerReceiver呼び出しを配置する正しい場所は、onResume呼び出しにあり、unregisterReceiveronPauseにあります。この呼び出しのペアは常に一致します。詳細については、アクティビティのライフサイクル図をご覧ください。 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);
}
15

編集:これはinazarukとelectricheadの答えです...私は彼らと同様の問題に遭遇し、以下を見つけました...

この問題には長年のバグがあります: http://code.google.com/p/Android/issues/detail?id=6191

Android 2.1から始まり、それ以降Android 2.xリリースのすべてに存在しているようです。ただし、Android 3.xまたは4.xの問題であるかどうかはわかりません。

とにかく、このStackOverflowの投稿では、問題を正しく回避する方法について説明しています(URLからは関連性がないようですが、そうすることをお約束します)

キーボードスライドがアプリをクラッシュさせるのはなぜですか?

11
Justin

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();
                }
            }
        }
6
Rowland Mtetezi

レシーバをnullとして宣言してから、アクティビティのonResume()およびonPause()にそれぞれregisterおよびunregisterメソッドを配置します。

@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

この問題に遭遇し、提案されたすべてを試してもまだ何も動作しない人のために、これはLocalBroadcastManager.getInstance(this).registerReceiver(...)を実行する代わりに私の問題をソートする方法です。

private LocalBroadcastManager lbman;

そして、この変数を使用して、broadcastreceiverで登録と登録解除を実行しました。

lbman.registerReceiver(bReceiver);

そして

lbman.unregisterReceiver(bReceiver);
1
nada

BRを登録するUIコンポーネントが破壊されると、BRも破壊されます。したがって、コードが登録解除されると、BRはすでに破棄されている可能性があります。

0
ousanmaz