Alıcı kayıtlı değil istisna hatası?


112

Geliştirici konsolumda insanlar, sahip olduğum herhangi bir telefonda yeniden oluşturamadığım bir hatayı bildirmeye devam ediyor. Bir kişi pil servisimin ayarlar ekranını açmaya çalıştıklarında aldığını söyleyen bir mesaj bıraktı. Hatadan da görebileceğiniz gibi, alıcının kayıtlı olmadığını söylüyor.

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)

Kaydoldum onCreate'imde

@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'daki ve ayrıca bir tercih dinleyicisi ile kaydını iptal edin

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

}

ve bu servisteki alıcım

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

Neden bu hatayı aldıklarına dair bir fikriniz var mı?

Yanıtlar:


207

Sorununuzun kökü burada bulunur:

 unregisterReceiver(batteryNotifyReceiver);

Alıcı zaten (muhtemelen Bu yayına dahil etmedi kodunda) ruhsatlı olmayan edildi veya kayıtlı değil ise, o zaman çağırmak unregisterReceiveratar IllegalArgumentException. Sizin durumunuzda, bu istisna için özel bir dene / yakala koymanız ve onu görmezden gelmeniz gerekir ( unregisterReceiveraynı alıcıda arama sayınızı kontrol edemeyeceğinizi veya kontrol etmek istemeyeceğinizi varsayarak).


31
Android platformunun bunu yapması mümkün mü? Yukarıdakine benzer bir kodum vardı, ancak hizmetin kaydını silecek başka bir kod yoktu ve aynı istisnayı alıyorum.
electrichead

2
Aynı sorunu yaşıyorum @electrichead, Android benim için bir yerde yapmadığı sürece alıcının onDestroy () 'dan önce nerede kayıtsız olacağını göremiyorum ....
user1088166

@ user1088166, etkinliğiniz için onStop () yöntemini geçersiz kılmayı deneyin. Orada bir try catch (IllegalArgumentException e) ekleyin ve kasıtlı olarak yayınınızın kaydını kaldırın - bunun yardımcı olup olmadığına bakın (bunun 3 yıllık bir yorum olduğunu fark ettim :))
Nactus

Benim durumumda suçlu tembel başlatmaydı - nesne başlatılmadığı için kaydı atladım, bu yüzden daha sonra başlatıldı ve alıcı kaydını unuttum.
Boris Treukhov

@electrichead hayır, sizin için yapmıyor, sadece doğru yöntemi seçmeniz gerekiyor: LocalBroadcastManager.getInstance(context).unregisterReceiver()veyacontext.unregisterReceiver()
user924

25

Tarafından kayıt olduğunuzda dikkatli olun

LocalBroadcastManager.getInstance(this).registerReceiver()

tarafından kaydını silemezsin

 unregisterReceiver()

kullanmalısın

LocalBroadcastManager.getInstance(this).unregisterReceiver()

veya uygulama çökecek, aşağıdaki gibi giriş yapın:

09-30 14: 00: 55.458 19064-19064 / com.jialan.guangdian.view E / AndroidRuntime: FATAL EXCEPTION: ana İşlem: com.jialan.guangdian.view, PID: 19064 java.lang.RuntimeException: Hizmet durdurulamıyor com.google.android.exoplayer.demo.player.PlayService@141ba331: java.lang.IllegalArgumentException: Alıcı kayıtlı değil: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584, android.app.ActivityThread. android.app.ActivityThread.access adresinde handleStopService (ActivityThread.java:2941) 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) java.lang.reflect.Method.invoke (Native Method), java.lang.reflect.Method.invoke (Method.java:372) com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run adresinde (ZygoteInit.java:901) com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696) Nedeni: java.lang.IllegalArgumentException : Alıcı kayıtlı değil: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584, android.app.LoadedApk.forgetReceiverDispatcher (LoadedApk.java:769), android.app.ContextImpl.unregister.java (ContextImpliver)1794) android.content.ContextWrapper.unregisterReceiver'da (ContextWrapper.java:510) com.google.android.exoplayer.demo.player.PlayService.onDestroy (PlayService.java:542), android.app.ActivityThread.handleStopService (ActivityThread) adresinde .java: 2924) android.app.ActivityThread.access adresinde $ 2200 (ActivityThread.java:148) android.app.ActivityThread $ H.handleMessage adresinde (ActivityThread.java:1395) android.os.Handler.dispatchMessage'da (Handler.java:102) android.os.Looper.loop'ta (Looper.java:135) android.app.ActivityThread.main'de (ActivityThread.java:5310) java'da. lang.reflect.Method.invoke (Native Method) java.lang.reflect.Method.invoke (Method.java:372), com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:901) com.android.internal.os.ZygoteInit.main adresinde (ZygoteInit.java:696) 


Bu, bu soruna gerçek bir cevaptır! Daha önce global veya yerel bir alıcı kaydettiyseniz unutmayın
user924

23

UnregisterReceiver için her yerde bu kodu kullanın:

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

6
Hala benim başıma geliyor. Try-catch kullanmak daha iyi.
palindrom

2
Try catch deyimi daha iyi
Rowland Mtetezi

16

Diğer yanıtlarda belirtildiği gibi, her çağrı için registerReceivertam olarak bir çağrı ile eşleştirilmediğinden istisna atılır unregisterReceiver. Neden olmasın?

An Activity, her onDestroyçağrı için her zaman eşleşen bir çağrıya sahip değildir onCreate. Sistemin hafızası biterse, uygulamanız arama yapılmadan kaldırılır onDestroy.

Bir koymak için doğru yer registerReceiverçağrısı olduğu onResumeçağrı ve unregisterReceiveriçinde onPause. Bu çağrı çifti her zaman eşleşir. Daha fazla ayrıntı için Etkinlik yaşam döngüsü şemasına bakın. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Kodunuz şu şekilde değişir:

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

Ancak bu, birçok kez kaydetme ve kayıt silme işleminin ek yüküne neden olur. Genel gider miktarından emin değilim, ancak kesin olarak bir miktar olacak.
Aman Derin Gautam

2
Geçersiz işleyiciyi yerinde bırakan bir istisna bırakmayı gerçekten mi öneriyorsunuz, çünkü kaldırmak için bazı CPU döngülerine mal olacak?
Curmudgeonlybumbly

11

DÜZENLEME: Bu, inazaruk ve electrichead için cevap ... Onlara benzer bir sorunla karşılaştım ve şunları öğrendim ...

Burada bu sorun için uzun süredir devam eden bir hata var: http://code.google.com/p/android/issues/detail?id=6191

Görünüşe göre Android 2.1 civarında başladı ve o zamandan beri tüm Android 2.x sürümlerinde mevcut. Yine de Android 3.x veya 4.x'te sorun olup olmadığından emin değilim.

Her neyse, bu StackOverflow gönderisi, sorunun nasıl doğru bir şekilde çözüleceğini açıklıyor (URL ile alakalı görünmüyor, ancak söz veriyorum)

Klavye kayması neden uygulamamı kilitliyor?


8

Sorunu geçici olarak çözmek için bir dene-yakala bloğu kullandım.

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

3

Alıcıyı boş olarak bildirin ve ardından sırasıyla etkinliğin onResume () ve onPause () öğelerine yazma ve kayıt silme yöntemlerini koyun.

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

0

BR'yi kaydeden UI bileşeni yok edildiğinde, BR de yok olur. Bu nedenle, kod kayıttan silindiğinde, BR çoktan yok edilmiş olabilir.


0

Bu problemle karşılaşan ve önerilenlerin hepsini deneyen ve hala hiçbir şey işe LocalBroadcastManager.getInstance(this).registerReceiver(...) yaramayan herkes için, problemimi bu şekilde sıraladım, yapmak yerine ilk olarak LocalBroadcastManager türünde bir yerel değişken oluşturdum,

private LocalBroadcastManager lbman;

Ve bu değişkeni yayın alıcısına kaydetme ve kayıt silme işlemlerini gerçekleştirmek için kullandı, yani

lbman.registerReceiver(bReceiver);

ve

lbman.unregisterReceiver(bReceiver);

0

Farz edelim ki, broadcastReceiverşu şekilde tanımlandı:

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        // your code

    }
};

Bir LocalBroadcastAktivitede kullanıyorsanız , kaydı şu şekilde iptal edeceksiniz:

LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);

LocalBroadcastBir Parçada kullanıyorsanız , kaydı şu şekilde iptal edeceksiniz:

LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(broadcastReceiver);

Bir Aktivitede normal yayın kullanıyorsanız, kaydı şu şekilde iptal edersiniz:

unregisterReceiver(broadcastReceiver);

Bir Parçada normal yayın kullanıyorsanız, o zaman kaydı şu şekilde iptal edersiniz:

getActivity().unregisterReceiver(broadcastReceiver);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.