त्रुटि: BinderProxy @ 45d459c0 मान्य नहीं है; क्या आपकी गतिविधि चल रही है?


144

यह त्रुटि क्या है ... मुझे स्टैकओवरफ़्लो समुदाय में इस त्रुटि पर कोई चर्चा नहीं मिली है विस्तृत: -

10-18 23:53:11.613: ERROR/AndroidRuntime(3197): Uncaught handler: thread main exiting due to uncaught exception
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@45d459c0 is not valid; is your activity running?
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.ViewRoot.setView(ViewRoot.java:468)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.Dialog.show(Dialog.java:239)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.vishal.contacte.Locationlistener$MyLocationListener.onLocationChanged(Locationlistener.java:86)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:179)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:112)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:128)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Looper.loop(Looper.java:123)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.ActivityThread.main(ActivityThread.java:4363)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invokeNative(Native Method)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invoke(Method.java:521)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at dalvik.system.NativeStart.main(Native Method)

इस लिंक की जाँच करें: Android - [बैकग्राउंड थ्रेड्स में से डायलॉग्स दिखा रहा है ] ( dimitar.me/android-displaying-dialogs-from-background-threads )
नवीन

आपका लिंक स्वीकृत उत्तर के लिए simmilar है, लेकिन यह बहुत बेहतर निष्कासित है। इसके लिए धन्यवाद
लकीमलाका


जवाबों:


343

यह सबसे अधिक होने की संभावना है क्योंकि आप पृष्ठभूमि थ्रेड के निष्पादन के बाद एक संवाद दिखाने की कोशिश कर रहे हैं, जबकि गतिविधि नष्ट हो रही है।

मैं अपने कुछ ऐप्स में से एक बार रिपोर्ट की गई इस त्रुटि को देख रहा था जब संवाद कॉल करने वाली गतिविधि किसी कारण या किसी अन्य के लिए समाप्त हो रही थी जब उसने संवाद दिखाने का प्रयास किया। यहाँ क्या यह मेरे लिए हल है:

if(!((Activity) context).isFinishing())
{
    //show dialog
}

मैं कई वर्षों से एंड्रॉइड के पुराने संस्करणों पर समस्या के आसपास काम करने के लिए इसका उपयोग कर रहा हूं, और तब से दुर्घटना नहीं देखी है।


1
यह वास्तव में चाल है! लेकिन क्या ऐसा होने पर भी संवाद खोलने का कोई तरीका है? मुझे वास्तव में यकीन नहीं है कि ऐसा होने पर संवाद कैसे प्रबंधित किया जाए। कोई सुझाव? अग्रिम में धन्यवाद!
कार्ला उर्रे स्टैबल

@CarlaStabile हाय! जिस तरह से मैं एक संवाद को दिखाने के लिए सोच सकता हूं जब ऐसा होता है यदि आप एक गतिविधि के लिए एक वैध संदर्भ प्राप्त कर सकते हैं जो खत्म नहीं हो रहा है - यह निर्भर करेगा कि आप इस कोड को कहां बुला रहे हैं और यदि आपके पास एक पुनर्प्राप्त करने का तरीका है दूसरे से संदर्भ, गैर-परिष्करण गतिविधि।
DiscDev

8
बहुत - बहुत धन्यवाद! मेरे लिए, दुर्घटना (ऊपर त्रुटि संदेश के साथ) तब होगा जब मैंने बैक बटन दबाया, डायलॉग बॉक्स दिखाए जाने से पहले। इसलिए कोड जारी रहेगा और इसे दिखाने की कोशिश की जाएगी, भले ही मैं एक अलग गतिविधि में था। लेकिन इससे दुर्घटना रुक गई और मैं नई गतिविधि में आसानी के साथ चला गया!
अज़ुरसपोट

1
इसी तरह के कई सवाल हैं, लेकिन उनमें से किसी में भी यह सुझाव नहीं दिया गया था। व्यक्तिगत रूप से यह मेरे परिदृश्य के लिए एकमात्र सही समाधान था।
भरण

इसके लिए कोटलिन संस्करण क्या है? क्या फ़िनिशिंग () पर्याप्त होगी?
आलोक राजसुकुमारन

12

मुझे उसी समस्या का सामना करना पड़ा और ऊपर दिए गए मामूली बदलावों के साथ डिस्कडेव द्वारा प्रस्तावित कोड का उपयोग किया गया :

if (!MainActivity.this.isFinishing()){
    alertDialog.show();
}

मैं बदल गया क्योंकि (गतिविधि) संदर्भ का मतलब मेरे मामले के लिए MainActivity.this था। इसके अलावा, आप उपयोगकर्ता प्रोफ़ाइल लिंक के बारे में सही हैं, लेकिन मुझे लगा कि आप इसे ऊपर पा सकते हैं।
हमजा पोलाट

4

यदि संवाद थ्रेड के कारण इस समस्या को बढ़ा रहा है, तो आपको इसे UI थ्रेड पर इस तरह चलाना चाहिए: -

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                dialog.show();

            }
        });

2

यह त्रुटि तब होती है जब आप किसी संदर्भ के लिए संवाद दिखा रहे होते हैं जो अब मौजूद नहीं है।

कॉल करने से पहले .show()जाँच लें कि गतिविधि / संदर्भ खत्म नहीं हो रहा है

if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
    alert.show();
}

1

जब मैंने countDownTimerअपने ऐप में ए । यह मेरे app में GameOver के रूप में कॉल करने का एक तरीका था

public void onFinish() {
     GameOver();
}

लेकिन वास्तव में खेल उपयोगकर्ता के गलत क्लिक के कारण समय से पहले खत्म हो सकता था (यह एक क्लिकिंग गेम था)। इसलिए जब मैं 20 सेकंड के बाद गेम ओवर डायलॉग देख रहा था, तो समय समाप्त होने पर मैं इसे रद्द करना भूल countDownTimerगया, संवाद फिर से दिखाई दिया। या किसी कारण से उपरोक्त त्रुटि के साथ दुर्घटनाग्रस्त हो गया।


1

इसे ठीक करने के लिए बहुत आसान है। डायलॉग प्रदर्शित करने से पहले यदि गतिविधि अपने अंतिम चरण से गुजर रही है तो परीक्षण करें:

  private Handler myHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    switch (msg.what) {
      case DISPLAY_DLG:
        if (!isFinishing()) {
        showDialog(MY_DIALOG);
        }
      break;
    }
  }
};

यहाँ और देखें


1

मेरे मामले में, समस्या यह थी कि Contextवर्ग में एक कमजोर संदर्भ के रूप में रखा गया था जो फैली हुई है Handler। तब मैं गुजर रहा था Messenger, कि एक के माध्यम से हैंडलर लपेटता Intentहै Service। मैं हर बार ऐसा कर रहा था जब गतिविधि onResume()विधि में स्क्रीन पर दिखाई दी ।

तो जैसा कि आप समझते हैं, मैसेंजर को अपने क्षेत्रों (संदर्भ सहित) के साथ एक साथ क्रमबद्ध किया गया था, क्योंकि इसका उपयोग करने वाली वस्तुओं को पास करने का एकमात्र तरीका है Intent- उन्हें सीरियल करना। उस समय जब मैसेंजर को सेवा में पारित किया गया था, तब भी गतिविधि स्वयं को संवाद दिखाने के लिए तैयार नहीं थी क्योंकि यह किसी अन्य राज्य में है (कहा जा रहा है Resume (), यह उस समय से बिल्कुल अलग है जब गतिविधि स्क्रीन पर पहले से ही है)। इसलिए जब मेसेंजर का डिजायराइजेशन किया गया था, तब भी संदर्भ फिर से शुरू होने की स्थिति में था, जबकि गतिविधि वास्तव में पहले से ही स्क्रीन पर थी। इसके अलावा, deserialization नई वस्तु के लिए स्मृति आवंटित करता है, जो मूल एक से पूरी तरह से अलग है।

समाधान सिर्फ यह है कि जब भी आपको जरूरत हो, सेवा में बंधे और एक ऐसी बाइंडर लौटाएं जिसमें 'setMessenger (मैसेंजर मैसेंजर)' जैसी विधि हो और जब आप सेवा में बंधे हों तो इसे कॉल करें।


1

मैं WeakReference<Activity>एक संदर्भ के रूप में उपयोग करके इस समस्या को हल करता हूं । दुर्घटना फिर कभी दिखाई नहीं दी। यहाँ कोटलिन में एक नमूना कोड है:

संवाद प्रबंधक वर्ग:

class DialogManager {

        fun showAlertDialog(weakActivity: WeakReference<Activity>) {
            val wActivity = weakActivity.get()
            wActivity?.let {
                val builder = AlertDialog.Builder(wActivity, R.style.MyDialogTheme)
                val inflater = wActivity.layoutInflater
                val dialogView = inflater.inflate(R.layout.alert_dialog_info, null)
                builder.setView(dialogView)

                // Set your dialog properties here. E.g. builder.setTitle("MyTitle")

                builder.create().show()
            }
         }

}

और आप इस तरह से संवाद दिखाएँ:

 val dialogManager = DialogManager()
 dialogManager.showAlertDialog(WeakReference<Activity>(this@MainActivity))

यदि आप सुपर-डुपर क्रैश से सुरक्षित होना चाहते हैं। builder.create().show()उपयोग के बजाय :

val dialog = builder.create()
safeShow(weakActivity, dialog)

यह safeShowविधि है:

private fun safeShow(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (!dialog.isShowing && !(wActivity).isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }

यह एक समान विधि है जिसे आप संवाद को सुरक्षित रूप से खारिज करने के लिए उपयोग कर सकते हैं:

private fun safeDismissAlertDialog(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (dialog.isShowing && !wActivity.isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }

0

उस डायलॉग का एक नया इंस्टेंस आप कैसे कॉल करना चाहते हैं? मैं वास्तव में सिर्फ एक ही समस्या से मिला हूं, और यही मैं करता हूं। इसके बजाय:

if(!((Activity) context).isFinishing())
{
    //show dialog
}

इस बारे में कैसा है?

 YourDialog mDialog = new YourDialog();
 mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
                        }

इसलिए यह जाँचने के बजाय कि क्या यह सुरक्षित है या संवाद नहीं दिखा रहा है, मुझे लगता है कि यह बहुत अधिक सुरक्षित है यदि हम केवल संवाद दिखाने के लिए एक नया उदाहरण बनाते हैं ।

मेरी तरह, मेरे मामले में मैं (एक से एक उदाहरण बनाने की कोशिश की टुकड़ा onCreate ) और का एक और सामग्री में उन लोगों के संवाद के कहने फोन adapterList और इस में परिणाम होगा "अपनी गतिविधि चल रहा है" - त्रुटि । मैंने सोचा कि ऐसा इसलिए था क्योंकि मैं सिर्फ एक उदाहरण बनाता हूं (onCreate से) और फिर यह नष्ट हो जाता है, इसलिए जब मैंने इसे किसी अन्य एडॉप्टरलिस्ट से कॉल करने की कोशिश की तो मैं पुराने उदाहरण से संवाद कॉल कर रहा हूं।

मुझे यकीन नहीं है कि मेरा समाधान मेमोरी के अनुकूल है या नहीं, क्योंकि मैंने इसे प्रोफाइल करने की कोशिश नहीं की है, लेकिन यह काम करता है (निश्चित रूप से, यह सुरक्षित है यदि आप बहुत सारे उदाहरण नहीं बनाते हैं)

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