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.

Dan Monego
quelle

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 :(

Torp
quelle
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
2
Dies wurde behoben in ( developer.android.com/guide/topics/ui/dialogs.html )
Martin Marconcini
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

Samuh
quelle
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.

Kenyee
quelle
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);
Pradeep
quelle
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
17

getApplicationContext()Verwenden Sie stattdessen einfachActivityName.this

mahbub_siddique
quelle
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 ...

T. Hawk
quelle
12

Ändern Sie es einfach in

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

Anstatt

AlertDialog.Builder alert_Categoryitem = 
    new AlertDialog.Builder(getApplicationContext());
Satheesh
quelle
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.

Anubian Noob
quelle
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

Jinu
quelle
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.

mifthi
quelle
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
Suyog Gunjal
quelle
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 !!

Metalhead1247
quelle
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

Hugo
quelle
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

Hopetribe
quelle
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());
Faisal Ashraf
quelle
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);
    }
Sankar Behera
quelle