Android 1.6: "android.view.WindowManager $ BadTokenException: Fenster kann nicht hinzugefügt werden - Token null ist nicht für eine Anwendung"


303

Ich versuche, ein Dialogfenster zu öffnen, aber jedes Mal, wenn ich versuche, es zu öffnen, wird folgende Ausnahme ausgelöst:

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)

Ich erstelle es, indem ich showDialogmit der ID des Displays anrufe. Der onCreateDialogHandler protokolliert einwandfrei und ich kann ihn problemlos durchgehen, aber ich habe ihn angehängt, da mir anscheinend etwas fehlt:

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

Fehlt etwas daran? In einigen Fragen wurde über dieses Problem beim Erstellen eines Dialogfelds gesprochen onCreate, das auftritt, weil die Aktivität noch nicht erstellt wurde, dies jedoch aus einem Aufruf eines Menüobjekts stammt und die appContextVariable im Debugger korrekt ausgefüllt zu sein scheint.

Antworten:


609

Anstelle von: Context appContext = this.getApplicationContext(); Sie sollten einen Zeiger auf die Aktivität verwenden, in der Sie sich befinden (wahrscheinlich this).

Ich wurde auch heute davon gebissen, der nervige Teil ist der getApplicationContext()wörtliche von developer.android.com :(


2
Es wird auch als Fehler gemeldet (obwohl dies nicht der Fall
Raymond Martineau

63
Nur für den Fall, dass dies jemandem hilft - verwenden Sie myActivity.this als Ihren Kontext in einem Dialog.
Rab Ross

13
Diese Frage und Antwort wird in 2 Tagen 3 Jahre alt. Ich bekomme immer noch einen guten Ruf, also habe Google ihre Dokumente immer noch nicht repariert ...
Torp


6
Dies ist April 2016 und immer noch diese Ausnahme, die zum Absturz der Anwendung bei der Dialoginitiierung führt.
Yogesh Seralia

78

Sie können ein Anwendungsfenster / -dialogfeld nicht über einen Kontext anzeigen, der keine Aktivität ist. Versuchen Sie, eine gültige Aktivitätsreferenz zu übergeben


Wie? Ich habe es versucht activity.thisund activity.getBaseContext()aber ohne Erfolg. Irgendeine Hilfe?
Darpan

3
Verstanden. Übergeben Sie direkt Ihren Aktivitätsnamen. Ohne .this.
Darpan

45

Das Gleiche gilt für die Sache getApplicationContext.

Die Dokumente auf der Android-Site sagen, dass sie es verwenden sollen, aber es funktioniert nicht ... grrrrr :-P

Mach einfach:

dialog = new Dialog(this); 

"this" ist normalerweise Ihre Aktivität, von der aus Sie den Dialog starten.


43

In Android-Dokumenten wird empfohlen, getApplicationContext () zu verwenden.

Stattdessen funktioniert es jedoch nicht. Verwenden Sie Ihre aktuelle Aktivität, während Sie AlertDialog.Builder oder AlertDialog oder Dialog instanziieren.

Ex:

AlertDialog.Builder builder = new  AlertDialog.Builder(this);

oder

AlertDialog.Builder builder = new  AlertDialog.Builder((Your Activity).this);

Das hat mir massiv geholfen. Ich habe versucht, einen Dialog aus einem anderen Dialog heraus zu erstellen und habe nur "AlertDialog.Builder (this);" gab einen Fehler. Vielen Dank!
EHarpham

(ActivityName.this) ist besonders nützlich, wenn Sie versuchen, einen Dialog innerhalb von onClick einer Schaltfläche zu erstellen
RmK

Mein Problem ist, dass ich einen ProgressDialog in einem AlertDialog in einem Adapter erstelle ... Ich kann ihn nicht zum Laufen bringen.
Martin Erlic


13

Ich hatte ein ähnliches Problem, bei dem ich eine andere Klasse wie diese hatte:

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

Hat die meiste Zeit gut funktioniert, aber manchmal ist es mit dem gleichen Fehler abgestürzt. Dann merke ich, dass MyActivityich in ...

public class MyActivity extends Activity {
  public static Something something;

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

Da ich das Objekt als hielt static, enthielt ein zweiter Lauf des Codes immer noch die Originalversion des Objekts und bezog sich daher immer noch auf das Original Activity, das nicht mehr existierte.

Dummer dummer Fehler, zumal ich das Objekt wirklich nicht wie statican erster Stelle halten musste ...


12

Ändern Sie es einfach in

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(YourActivity.this);

Anstatt

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(getApplicationContext());

9

Eine andere Lösung besteht darin, den Fenstertyp auf einen Systemdialog festzulegen:

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

Dies erfordert die SYSTEM_ALERT_WINDOWErlaubnis:

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

Wie die Dokumente sagen:

Nur sehr wenige Anwendungen sollten diese Berechtigung verwenden. Diese Fenster sind für die Interaktion auf Systemebene mit dem Benutzer vorgesehen.

Dies ist eine Lösung, die Sie nur verwenden sollten, wenn Sie einen Dialog benötigen, der nicht an eine Aktivität angehängt ist.


Dies ist jetzt ein veraltetes Flag von API-Ebene 26. Weil es dem Entwickler ermöglicht, mit Systemfenstern zu spielen, die aus Benutzersicht nicht gut sind.
CopsOnRoad

4

Nicht getApplicationContext()zum Deklarieren von Dialouge verwenden

Verwenden thisSie immer oder Ihreactivity.this


2

Bei verschachtelten Dialogen tritt dieses Problem häufig auf. Es funktioniert, wenn

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

wird anstelle von verwendet

mDialogBuilder = new AlertDialog.Builder(getApplicationContext);

diese Alternative.


2

Das hat bei mir funktioniert ...

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

Verwenden

ActivityName.this

0

Sie können dies auch tun

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

Das hat bei mir funktioniert !!


0

Wie bereits erwähnt, benötigen Sie eine Aktivität als Kontext für den Dialog. Verwenden Sie "YourActivity.this" für einen statischen Kontext oder prüfen Sie hier, wie Sie eine dynamische Aktivität im abgesicherten Modus verwenden können


0

Versuchen Sie, den dialogFenstertyp auf zurückzusetzen

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

Vergessen Sie nicht, die Erlaubnis zu verwenden android.permission.SYSTEM_ALERT_WINDOW


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

Text hier: -
Verwenden Sie dies, um den activityKontext für zu erhaltenprogressdialog

 progressdialog = new ProgressDialog(Splash.this);

oder progressdialog = new ProgressDialog(this);

Verwenden Sie diese Option, um den Anwendungskontext für BroadcastListener nicht für abzurufen progressdialog.

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

0

Der beste und sicherste Weg, einen 'ProgressDialog' in einer AsyncTask anzuzeigen, um Speicherverlustprobleme zu vermeiden, ist die Verwendung eines 'Handlers' mit Looper.main ().

    private ProgressDialog tProgressDialog;

dann in der 'onCreate'

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

Jetzt sind Sie mit dem Setup-Teil fertig. Rufen Sie nun in asyncTask 'showProgress ()' und 'hideProgress ()' auf.

    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);
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.