एंड्रॉइड 1.6: "android.view.WindowManager $ BadTokenException: विंडो जोड़ने में असमर्थ-टोकन नल एक एप्लिकेशन के लिए नहीं है"




android-dialog runtimeexception (13)

मैं एक संवाद विंडो खोलने की कोशिश कर रहा हूं, लेकिन हर बार जब मैं इसे खोलने की कोशिश करता हूं तो यह अपवाद फेंकता है:

Uncaught handler: thread main exiting due to uncaught exception
android.view.WindowManager$BadTokenException: 
     Unable to add window -- token null is not for an application
  at android.view.ViewRoot.setView(ViewRoot.java:460)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
  at android.app.Dialog.show(Dialog.java:238)
  at android.app.Activity.showDialog(Activity.java:2413)

मैं प्रदर्शन आईडी के साथ showDialog को कॉल करके इसे बना रहा हूं। onCreateDialog हैंडलर ठीक से लॉग करता है और मैं बिना किसी समस्या के इसे चला सकता हूं, लेकिन मैंने इसे संलग्न कर लिया है क्योंकि ऐसा लगता है कि मुझे कुछ याद आ रहा है:

@Override
public Dialog onCreateDialog(int id)
{
    Dialog dialog;
    Context appContext = this.getApplicationContext();
    switch(id)
    {
        case RENAME_DIALOG_ID:
            Log.i("Edit", "Creating rename dialog...");
            dialog = new Dialog(appContext);
            dialog.setContentView(R.layout.rename);
            dialog.setTitle("Rename " + noteName);
            break;
        default:
            dialog = null;
            break;
    }
    return dialog;      
}

क्या इससे कुछ याद आ रही है? कुछ प्रश्नों ने onCreate से एक संवाद बनाते समय इस समस्या के बारे में बात की है, जो ऐसा होता है क्योंकि गतिविधि अभी तक नहीं बनाई गई है, लेकिन यह मेनू ऑब्जेक्ट से कॉल से आ रही है, और appContext चर appContext लगता है जैसे यह सही ढंग से पॉप्युलेट किया गया है डिबगर।


नेस्टेड संवादों के लिए यह मुद्दा बहुत आम है, यह तब काम करता है

AlertDialog.Builder mDialogBuilder = new AlertDialog.Builder(MyActivity.this);

के बजाय प्रयोग किया जाता है

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

यह विकल्प


एक AsyncTask में 'प्रोग्रेसडिअलॉग' दिखाने का सबसे अच्छा और सुरक्षित तरीका, स्मृति रिसाव समस्या से परहेज करना Looper.main () के साथ 'हैंडलर' का उपयोग करना है।

    private ProgressDialog tProgressDialog;

फिर 'ऑनक्रेट' में

    tProgressDialog = new ProgressDialog(this);
    tProgressDialog.setMessage(getString(R.string.loading));
    tProgressDialog.setIndeterminate(true);

अब आप सेटअप भाग के साथ किया है। अब AsyncTask में 'showProgress ()' और 'hideProgress ()' को कॉल करें।

    private void showProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.show();
            }
        }.sendEmptyMessage(1);
    }

    private void hideProgress(){
        new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                tProgressDialog.dismiss();
            }
        }.sendEmptyMessage(1);
    }

जैसा कि कहा गया है, आपको संवाद के संदर्भ के रूप में एक गतिविधि की आवश्यकता है, एक स्थिर संदर्भ के लिए "YourActivity.this" का उपयोग करें या एक सुरक्षित मोड में गतिशील एक का उपयोग करने के लिए here


आप उस संदर्भ के माध्यम से एक एप्लिकेशन विंडो / संवाद प्रदर्शित नहीं कर सकते जो गतिविधि नहीं है। वैध गतिविधि संदर्भ पारित करने का प्रयास करें


getApplicationContext() करने के बजाय, ActivityName.this उपयोग करें


dialog विंडो के प्रकार को रीसेट करने का प्रयास करें

WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

अनुमति का उपयोग करना न भूलें android.permission.SYSTEM_ALERT_WINDOW


आप यह भी कर सकते हैं

public class Example extends Activity {
    final Context context = this;
    final Dialog dialog = new Dialog(context);
}

यह मेरे लिए काम किया !!


मेरे पास एक समान मुद्दा था जहां मेरे पास एक और वर्ग था:

public class Something {
  MyActivity myActivity;

  public Something(MyActivity myActivity) {
    this.myActivity=myActivity;
  }

  public void someMethod() {
   .
   .
   AlertDialog.Builder builder = new AlertDialog.Builder(myActivity);
   .
   AlertDialog alert = builder.create();
   alert.show();
  }
}

अधिकांश समय ठीक काम किया, लेकिन कभी-कभी यह एक ही त्रुटि से दुर्घटनाग्रस्त हो गया। तब मुझे एहसास हुआ कि MyActivity मैंने ...

public class MyActivity extends Activity {
  public static Something something;

  public void someMethod() {
    if (something==null) {
      something=new Something(this);
    }
  }
}

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

बेवकूफ बेवकूफ गलती, विशेष रूप से मुझे वास्तव में वस्तु को पहले स्थान पर static रखने की आवश्यकता नहीं थी ...


getApplicationContext() घोषित करने पर getApplicationContext() उपयोग न करें

हमेशा this या अपनी activity.this उपयोग करें। this


एक अन्य समाधान विंडो प्रकार को सिस्टम संवाद में सेट करना है:

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

इसके लिए SYSTEM_ALERT_WINDOW अनुमति की आवश्यकता है:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

जैसा कि दस्तावेज़ कहते हैं:

बहुत कम अनुप्रयोगों को इस अनुमति का उपयोग करना चाहिए; ये खिड़कियां उपयोगकर्ता के साथ सिस्टम-स्तरीय बातचीत के लिए हैं।

यह एक समाधान है जिसका उपयोग केवल तभी करना चाहिए जब आपको किसी ऐसे संवाद की आवश्यकता होती है जो किसी गतिविधि से जुड़ी न हो।


यह मेरे लिए काम किया -

new AlertDialog.Builder(MainActivity.this)
        .setMessage(Html.fromHtml("<b><i><u>Spread Knowledge Unto The Last</u></i></b>"))
        .setCancelable(false)
        .setPositiveButton("Dismiss",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    }
                }).show();

उपयोग

ActivityName.this

public class Splash extends Activity {

    Location location;
    LocationManager locationManager;
    LocationListener locationlistener;
    ImageView image_view;
    ublic static ProgressDialog progressdialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash);
        progressdialog = new ProgressDialog(Splash.this);
           image_view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                        locationManager.requestLocationUpdates("gps", 100000, 1, locationlistener);
                        Toast.makeText(getApplicationContext(), "Getting Location plz wait...", Toast.LENGTH_SHORT).show();

                            progressdialog.setMessage("getting Location");
                            progressdialog.show();
                            Intent intent = new Intent(Splash.this,Show_LatLng.class);
//                          }
        });
    }

टेक्स्ट यहां:-
progressdialog लिए activity संदर्भ प्राप्त करने के लिए इसका उपयोग करें

 progressdialog = new ProgressDialog(Splash.this);

या progressdialog = new ProgressDialog(this);

BroadcastListener लिए progressdialog लिए आवेदन संदर्भ प्राप्त करने के लिए इसका उपयोग करें।

progressdialog = new ProgressDialog(getApplicationContext());
progressdialog = new ProgressDialog(getBaseContext());

GetAplicationContext चीज़ पर ditto।

एंड्रॉइड साइट पर दस्तावेज़ इसका उपयोग करने के लिए कहते हैं, लेकिन यह काम नहीं करता है ... grrrrr: -P

बस करो:

dialog = new Dialog(this); 

"यह" आमतौर पर आपकी गतिविधि है जिससे आप संवाद शुरू करते हैं।





android-windowmanager