रिसीवर अपवाद पंजीकृत त्रुटि नहीं है?


112

मेरे डेवलपर कंसोल में लोग एक त्रुटि की रिपोर्ट करते रहते हैं जो मेरे पास किसी भी फोन पर पुन: पेश नहीं कर सकता है। एक व्यक्ति ने एक संदेश यह कहते हुए छोड़ दिया कि उसे यह तब मिलता है जब वे मेरी बैटरी सेवा की सेटिंग स्क्रीन को खोलने का प्रयास करते हैं। जैसा कि आप त्रुटि से देख सकते हैं कि यह कहता है कि रिसीवर पंजीकृत नहीं है।

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 में Unregister करें और वरीयता श्रोता के साथ भी

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

किसी भी विचार क्यों वे त्रुटि हो रही होगी?

जवाबों:


207

आपकी समस्या की जड़ यहाँ स्थित है:

 unregisterReceiver(batteryNotifyReceiver);

यदि रिसीवर पहले से ही अपंजीकृत था (शायद उस कोड में जिसे आपने इस पोस्ट में शामिल नहीं किया था) या पंजीकृत नहीं था, तो unregisterReceiverथ्रो को कॉल करें IllegalArgumentException। आपके मामले में आपको इस अपवाद के लिए बस विशेष प्रयास / पकड़ने की आवश्यकता है और इसे अनदेखा करें (यह मानते हुए कि आप unregisterReceiverएक ही रिसीवर पर कॉल करने की संख्या को नियंत्रित नहीं कर सकते हैं या नहीं करना चाहते हैं )।


31
क्या ऐसा करना Android प्लेटफॉर्म के लिए ही संभव है? मेरे पास उपरोक्त कोड समान था, लेकिन इस सेवा में कोई भी अन्य कोड नहीं था, जो सेवा को अपंजीकृत कर दे, और मुझे वही अपवाद मिले।
इलेक्ट्रिसाइड

2
मेरे पास एक ही समस्या है @electrichead, मैं यह नहीं देख सकता कि रिसीवर onDestroy () से पहले अनरजिस्टर्ड कहां होगा जब तक कि एंड्रॉइड मेरे लिए कहीं ऐसा नहीं कर रहा है ....
user1088166

@ user1088166, अपनी गतिविधि के लिए onStop () विधि को ओवरराइड करने का प्रयास करें। इसमें एक ट्राई कैच (IllegalArgumentException e) जोड़ें और जानबूझकर आपके प्रसारण को
अनरजिस्टर्ड

मेरे मामले में अपराधी आलसी आरंभीकरण था - मैंने पंजीकरण को छोड़ दिया क्योंकि ऑब्जेक्ट को आरंभीकृत नहीं किया गया था, इसलिए इसे बाद में आरंभीकृत किया गया और मैंने रिसीवर पंजीकरण भूल गया।
बोरिस ट्रेखोव

@electrichead नहीं, यह आपके लिए नहीं है, आपको बस सही विधि चुनने की आवश्यकता है: LocalBroadcastManager.getInstance(context).unregisterReceiver()याcontext.unregisterReceiver()
user924

25

जब आप पंजीकरण करें तो सावधान रहें

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: प्राप्तकर्ता पंजीकृत नहीं: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 पर Android पर टैप करें। handleStopService (ActivThread.java:2941) Android.app.ActivityThread.access पर $ 2200 (ActivThread.java:148) android.app.ActivityThread $ H.handleMessage (ActivThread.java:1395) पर android.os.Handler.dispatchMessage (Handler.java:102) Android पर .os.ooper.loop (Looper.java:135) पर android.app.ActivityThread.main (ActivThread.java:5310) java.lang.reflect.Method.invoke (मूल विधि) पर 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): Java: Java: : प्राप्तकर्ता पंजीकृत नहीं: com.google.android.exoplayer.demo.player.PlayService$PlayStatusReceiver@19538584 android.app.LoadedApk.forgetRecepDeatch (LoadedApk.java:769) पर android.app.Context.pl.mx पर क्लिक करें।1794) android.content.ContextWrapper.unregisterReceiver (ContextWrapper.java) पर com.google.android.exoplayer.demo.player.PlayService.onDestroy (PlayService.java) 42.app.ActivityThreadShreadShand/ पर क्लिक करें। .java: 2924) android.app.ActivityThread.access पर $ 2200 (ActivThread.java:148) पर android.app.ActivityThread $ H.handleMessage (ActivThread.java:1395) पर android.os.Handler.dispatchMessage (Handler.java:102) android.os.Looper.loop (Looper.java:135) पर android.app.ActivityThread.main (ActivThread.java:5310) जावा में। lang.reflect.Method.invoke (नेटिव मेथड) at java.lang.reflect.Method.invoke (Method.java:372) पर com.android.internal.os.ZygoteInit मेथडAndArgsCaller.run (ZygoteInit.it.java:901) पर com.android.internal.os.ZygoteInit.main (ZygoteInit.java:696) 


यह इस समस्या का एक वास्तविक जवाब है! बस यह न भूलें कि आपने पहले वैश्विक या स्थानीय रिसीवर पंजीकृत किया है
user924

23

इस कोड का उपयोग हर जगह unregisterReceiver के लिए करें:

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

6
अब भी मेरे साथ होता है। बेहतर है कोशिश-कैच का इस्तेमाल करें।
पलिंड्रोम

2
कैच स्टेटमेंट को बेहतर बनाने की कोशिश करें
रॉलैंड मैटेस्टी

16

जैसा कि अन्य उत्तरों में उल्लेख किया गया है, अपवाद को फेंक दिया जा रहा है क्योंकि प्रत्येक कॉल को registerReceiverएक कॉल से बिल्कुल मिलान नहीं किया जा रहा है unregisterReceiver। क्यों नहीं?

ए में Activityहमेशा onDestroyहर onCreateकॉल के लिए एक मेल नहीं होता है । यदि सिस्टम मेमोरी से बाहर चला जाता है, तो आपका ऐप बिना कॉल किए बाहर निकल जाता है onDestroy

registerReceiverकॉल लगाने के लिए सही जगह onResumeकॉल में और unregisterReceiverअंदर है onPause। कॉल की यह जोड़ी हमेशा मेल खाती है। अधिक विवरण के लिए गतिविधि जीवनचक्र आरेख देखें। 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);
}

लेकिन यह कई बार अधिक संख्या में पंजीकरण और अपंजीकृत करने के ओवरहेड का कारण होगा। मैं ओवरहेड की मात्रा के बारे में निश्चित नहीं हूं, लेकिन निश्चित रूप से कुछ होगा।
अमन दीप गौतम

2
क्या आप वास्तव में अवैध हैंडलर फेंकने के अपवाद को छोड़ने का सुझाव दे रहे हैं क्योंकि इसे हटाने के लिए कुछ सीपीयू चक्र खर्च होंगे?
Curmudgeonlybumbly

11

EDIT: यह इनजारुक और इलेक्ट्रिचाइड का जवाब है ... मैं उनके लिए एक समान मुद्दे में चला गया था और निम्नलिखित पाया ...

इस समस्या के लिए यहां एक लंबा-चौड़ा बग है: http://code.google.com/p/android/issues/detail?id=6801

ऐसा लगता है कि यह एंड्रॉइड 2.1 के आसपास शुरू हुआ और तब से सभी एंड्रॉइड 2.x रिलीज में मौजूद है। मुझे यकीन नहीं है कि यह अभी भी एंड्रॉइड 3.x या 4.x में एक समस्या है।

वैसे भी, यह StackOverflow पोस्ट बताता है कि समस्या को सही तरीके से कैसे हल किया जाए (यह URL द्वारा प्रासंगिक नहीं दिखता है लेकिन मैं यह वादा करता हूं)

कीबोर्ड-स्लाइड मेरे ऐप को क्रैश क्यों करता है?


8

मैंने कोशिश की - अस्थायी रूप से समस्या को हल करने के लिए ब्लॉक को पकड़ना।

// 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

रिसीवर को अशक्त घोषित करें और फिर रजिस्टर और अपंजीकृत विधियों को क्रमशः गतिविधि के 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;
    }
}

0

जब यूआर घटक जो बीआर को पंजीकृत करता है नष्ट हो जाता है, तो बीआर है। इसलिए जब कोड अपंजीकृत हो जाता है, तो BR पहले ही नष्ट हो सकता है।


0

किसी के लिए भी जो इस समस्या पर आएगा और उन्होंने वह सब करने की कोशिश की जो सुझाया गया था और अभी भी कुछ भी काम नहीं करता है, यह है कि मैंने अपनी समस्या को कैसे हल किया, इसके बजाय LocalBroadcastManager.getInstance(this).registerReceiver(...) मैंने पहली बार स्थानीय प्रकार के स्थानीय चर का निर्माण किया,

private LocalBroadcastManager lbman;

और इस वैरिएबल का उपयोग प्रसारणकर्ता पर रजिस्टरिंग और अपंजीकृत करने के लिए किया जाता है, अर्थात

lbman.registerReceiver(bReceiver);

तथा

lbman.unregisterReceiver(bReceiver);

0

मान लें कि आपकी broadcastReceiverपरिभाषा इस प्रकार है:

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

        // your code

    }
};

यदि आप LocalBroadcastकिसी गतिविधि में उपयोग कर रहे हैं , तो यह है कि आप अपंजीकृत कैसे होंगे:

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

यदि आप LocalBroadcastएक टुकड़े में उपयोग कर रहे हैं , तो यह है कि आप अपंजीकृत कैसे होंगे:

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

यदि आप किसी गतिविधि में सामान्य प्रसारण का उपयोग कर रहे हैं, तो यह है कि आप अपंजीकृत कैसे होंगे:

unregisterReceiver(broadcastReceiver);

यदि आप एक फ़्रैगमेंट में सामान्य प्रसारण का उपयोग कर रहे हैं, तो यह है कि आप अपंजीकृत कैसे होंगे:

getActivity().unregisterReceiver(broadcastReceiver);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.