수신자가 등록되지 않은 예외 오류입니까?

내 개발자 콘솔에서 사람들은 내가 가지고있는 어떤 전화에서도 재현 할 수없는 오류를 계속보고합니다. 한 사람이 내 배터리 서비스의 설정 화면을 열려고하면받을 수 있다는 메시지를 남겼습니다. 오류에서 알 수 있듯이 수신자가 등록되지 않았 음을 나타냅니다.

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

왜 그 오류가 발생하는지 아십니까?



답변

문제의 원인은 다음과 같습니다.

 unregisterReceiver(batteryNotifyReceiver);

수신기가 이미 (아마 당신이 게시물에 포함하지 않았다 코드에서) 등록되지 않았거나 등록되지 않은 경우, 다음에 전화를 unregisterReceiver던졌습니다 IllegalArgumentException. 귀하의 경우에는이 예외에 대해 특별한 try / catch를 입력하고 무시해야합니다 ( unregisterReceiver동일한 수신자에게 전화를 거는 횟수를 제어 할 수 없거나 제어하고 싶지 않다고 가정 ).


답변

등록 할 때주의하세요.

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 : main Process : com.jialan.guangdian.view, PID : 19064 java.lang.RuntimeException : Unable to stop service com.google.android.exoplayer.demo.player.PlayService@141ba331 : java.lang.IllegalArgumentException : 수신기가 등록되지 않음 : 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) at 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.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 at android.app.LoadedApk.forgetReceiverDispatcher (LoadedApk.java:769) at android.app.ContextImpl.unregisterReceiver (ContextImpl.java :1794) at 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) 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) at java.lang.reflect.Method.invoke (Method.java:372) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java :901) com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696) 


답변

unregisterReceiver에 대해 모든 곳에서이 코드를 사용하십시오.

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

답변

다른 답변에서 언급했듯이에 대한 각 호출 registerReceiver이 정확히 하나의 호출과 일치하지 않기 때문에 예외가 발생 합니다 unregisterReceiver. 왜 안돼?

An 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);
}

답변

편집 : 이것은 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과 관련이없는 것처럼 보이지만 약속합니다)

키보드 슬라이드로 인해 앱이 충돌하는 이유는 무엇입니까?


답변

일시적으로 문제를 해결하기 위해 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();
                }
            }
        }

답변

수신자를 null로 선언 한 다음 각각 활동의 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;
    }
}