Penerima tidak terdaftar kesalahan pengecualian?

112

Di konsol pengembang saya, orang-orang terus melaporkan kesalahan yang tidak dapat saya buat ulang di ponsel mana pun yang saya miliki. Satu orang meninggalkan pesan yang mengatakan dia mengerti ketika mereka mencoba membuka layar pengaturan layanan baterai saya. Seperti yang Anda lihat dari kesalahan, dikatakan bahwa penerima tidak terdaftar.

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)

Saya mendaftar di onCreate saya

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

Batalkan pendaftaran di onDestroy dan juga dengan pendengar preferensi

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

}

dan ini adalah penerima saya dalam layanan ini

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

tahu mengapa mereka mendapatkan kesalahan itu?

tyczj.dll
sumber

Jawaban:

207

Akar masalah Anda terletak di sini:

 unregisterReceiver(batteryNotifyReceiver);

Jika penerima sudah tidak terdaftar (mungkin dalam kode yang tidak Anda sertakan dalam posting ini) atau tidak terdaftar, maka panggil untuk unregisterReceivermelempar IllegalArgumentException. Dalam kasus Anda, Anda hanya perlu melakukan coba / tangkap khusus untuk pengecualian ini dan mengabaikannya (dengan asumsi Anda tidak dapat atau tidak ingin mengontrol berapa kali Anda menelepon unregisterReceiverpada penerima yang sama).

inazaruk
sumber
31
Mungkinkah platform Android itu sendiri melakukan ini? Saya memiliki kode yang mirip dengan yang di atas, tetapi tanpa kode lain sama sekali yang akan membatalkan pendaftaran layanan, dan saya mendapatkan pengecualian yang sama.
electrichead
2
Saya memiliki masalah yang sama @electrichead, saya tidak dapat melihat di mana penerima akan dibatalkan pendaftarannya sebelum onDestroy () kecuali Android melakukannya untuk saya di suatu tempat ....
user1088166
@ user1088166, coba ganti metode onStop () untuk aktivitas Anda. Di sana tambahkan coba tangkap (IllegalArgumentException e) dan dengan sengaja batalkan pendaftaran siaran Anda - lihat apakah itu membantu (perhatikan saja ini adalah komentar berusia 3 tahun :))
Nactus
Dalam kasus saya, pelakunya adalah inisialisasi malas - Saya melewatkan pendaftaran karena objek tidak diinisialisasi, jadi diinisialisasi kemudian dan saya lupa pendaftaran penerima.
Boris Treukhov
@electrichead tidak, itu tidak melakukannya untuk Anda, Anda hanya perlu memilih metode yang benar: LocalBroadcastManager.getInstance(context).unregisterReceiver()ataucontext.unregisterReceiver()
user924
25

Hati-hati, saat Anda mendaftar pada

LocalBroadcastManager.getInstance(this).registerReceiver()

Anda tidak dapat membatalkan pendaftaran pada

 unregisterReceiver()

Anda harus menggunakan

LocalBroadcastManager.getInstance(this).unregisterReceiver()

atau aplikasi akan macet, log sebagai berikut:

09-30 14: 00: 55.458 19064-19064 / com.jialan.guangdian.view E / AndroidRuntime: FATAL EXCEPTION: main Proses: com.jialan.guangdian.view, PID: 19064 java.lang.RuntimeException: Tidak dapat menghentikan layanan com.google.android.exoplayer.demo.player.PlayService@141ba331: java.lang.IllegalArgumentException: Penerima tidak terdaftar: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 di android.app.ActivityThread. handleStopService (ActivityThread.java:2941) di android.app.ActivityThread.access $ 2200 (ActivityThread.java:148) di android.app.ActivityThread $ H. handleMessage (ActivityThread.java:1395) di android.os.Handler.dispatchMessage (Handler.java:102) di android.os.Looper.loop (Looper.java:135) di android.app.ActivityThread.main (ActivityThread.java:5310) di java.lang.reflect.Method.invoke (Metode Asli) di java.lang.reflect.Method.invoke (Method.java:372) di com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:901) di com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696) Disebabkan oleh: java.lang.IllegalArgumentException : Penerima tidak terdaftar: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 di android.app.LoadedApk.forgetReceiverDispatcher (LoadedApk.java:769) di android.app.ContextImpl.unregisterReceiver (ContextImpl.java:1794) di android.content.ContextWrapper.unregisterReceiver (ContextWrapper.java:510) di com.google.android.exoplayer.demo.player.PlayService.onDestroy (PlayService.java:542) di android.app.ActivityThread.handleStopService (ActivityThread .java: 2924) di android.app.ActivityThread.access $ 2200 (ActivityThread.java:148) di android.app.ActivityThread $ H. handleMessage (ActivityThread.java:1395) di android.os.Handler.dispatchMessage (Handler.java:102) di android.os.Looper.loop (Looper.java:135) di android.app.ActivityThread.main (ActivityThread.java:5310) di java. lang.reflect.Method.invoke (Metode Asli) di java.lang.reflect.Method.invoke (Method.java:372) di com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:901) di com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696) 

Chuanhang.gu
sumber
Ini adalah jawaban nyata untuk masalah ini! Jangan lupa jika Anda telah mendaftarkan penerima global atau lokal sebelumnya
pengguna924
23

Gunakan kode ini di mana saja untuk unregisterReceiver:

if (batteryNotifyReceiver != null) {
    unregisterReceiver(batteryNotifyReceiver);
    batteryNotifyReceiver = null;
}
xnagyg.dll
sumber
6
Masih terjadi padaku. Lebih baik gunakan coba-tangkap.
palindrom
2
Coba pernyataan menangkap lebih baik
Rowland Mtetezi
16

Seperti yang disebutkan dalam jawaban lain, pengecualian diberikan karena setiap panggilan ke registerReceivertidak dicocokkan dengan satu panggilan ke persis unregisterReceiver. Kenapa tidak?

Sebuah Activitytidak selalu memiliki pencocokan onDestroypanggilan untuk setiap onCreatepanggilan. Jika sistem kehabisan memori, aplikasi Anda akan dikeluarkan tanpa panggilan onDestroy.

Tempat yang benar untuk melakukan registerReceiverpanggilan adalah di dalam onResumedan unregisterReceiverdi dalam onPause. Pasangan panggilan ini selalu cocok. Lihat diagram siklus hidup Aktivitas untuk lebih jelasnya. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle

Kode Anda akan berubah menjadi:

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);
}
Curmudgeonlybumbly
sumber
Tapi ini akan menyebabkan overhead pendaftaran dan pembatalan pendaftaran lebih banyak lagi. Saya tidak yakin dengan jumlah overhead, tapi pasti ada.
Aman Deep Gautam
2
Apakah Anda benar-benar menyarankan untuk meninggalkan pengecualian dengan melempar handler yang tidak valid karena akan memakan biaya beberapa siklus CPU untuk menghapusnya?
Curmudgeonlybumbly
11

EDIT: Ini adalah jawaban untuk inazaruk dan electrichead ... Saya telah mengalami masalah serupa dengan mereka dan menemukan yang berikut ...

Ada bug lama untuk masalah ini di sini: http://code.google.com/p/android/issues/detail?id=6191

Sepertinya ini dimulai sekitar Android 2.1 dan telah hadir di semua rilis Android 2.x. Saya tidak yakin apakah itu masih menjadi masalah di Android 3.x atau 4.x.

Bagaimanapun, posting StackOverflow ini menjelaskan cara mengatasi masalah dengan benar (ini tidak terlihat relevan dengan URL tetapi saya berjanji itu)

Mengapa keyboard-slide merusak aplikasi saya?

Justin
sumber
8

Saya menggunakan blok coba-tangkap untuk menyelesaikan masalah sementara.

// 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();
                }
            }
        }
Rowland Mtetezi
sumber
3

Deklarasikan penerima sebagai null lalu Masukkan metode register dan unregister di onResume () dan onPause () aktivitas masing-masing.

@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;
    }
}
Sagar D
sumber
0

Ketika komponen UI yang mendaftarkan BR dimusnahkan, BR juga. Oleh karena itu, saat kode tersebut dibatalkan pendaftarannya, BR mungkin telah dihancurkan.

ousanmaz.dll
sumber
0

Bagi siapa saja yang akan menemukan masalah ini dan mereka mencoba semua yang disarankan dan tidak ada yang masih berfungsi, ini adalah cara saya mengurutkan masalah saya, daripada melakukan LocalBroadcastManager.getInstance(this).registerReceiver(...) saya pertama kali membuat variabel lokal tipe LocalBroadcastManager,

private LocalBroadcastManager lbman;

Dan menggunakan variabel ini untuk melakukan registering dan unregistering pada broadcastreceiver

lbman.registerReceiver(bReceiver);

dan

lbman.unregisterReceiver(bReceiver);
nada
sumber
0

Mari kita asumsikan Anda broadcastReceiverdidefinisikan seperti ini:

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

        // your code

    }
};

Jika Anda menggunakan LocalBroadcastdalam suatu Aktivitas, berikut cara Anda membatalkan pendaftaran:

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

Jika Anda menggunakan LocalBroadcastdi Fragment, berikut cara Anda membatalkan pendaftaran:

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

Jika Anda menggunakan siaran normal dalam suatu Aktivitas, berikut cara Anda membatalkan pendaftaran:

unregisterReceiver(broadcastReceiver);

Jika Anda menggunakan siaran normal dalam Fragmen, berikut cara Anda membatalkan pendaftaran:

getActivity().unregisterReceiver(broadcastReceiver);
zeeshan
sumber