Android: „BadTokenException: Fenster konnte nicht hinzugefügt werden; läuft Ihre Aktivität?“ beim Anzeigen des Dialogs in PreferenceActivity

Lesezeit: 8 Minuten

Benutzer-Avatar
Lama

Ich möchte um Hilfe bitten: In meiner App habe ich nur eine Aktivität, a PreferenceActivity (brauche nichts anderes, es ist nur eine einfache Hintergrund-Sync-App, also die PrefsActivity ist der Main/Launcher). Überprüfen Sie nach den Benutzer-Setup-Einstellungen a checkBoxPreference, und das startet (oder stoppt) einen Dienst. Beim Start erscheint ein Dialog. Aber hier ist das Problem: Wenn der Benutzer zurück drückt (die Aktivität verlässt), startet sie erneut und versucht dann, das zu überprüfen checkBoxPref., das prefsactivity stürzt ab. Dialog wird nicht angezeigt. Ich habe keine Ahnung warum und wie ich das beheben kann.

Dieser Code ist genau gleich mit diesem Teil, was mir das Problem gibt:

PrefsActivity.java:

   package is.it.works;

   // imports .....

   public class PrefsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
SharedPreferences prefs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);
    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    prefs.registerOnSharedPreferenceChangeListener(this);
}// onCreate

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        showDialog(1);
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC

@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case 1: {
        ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMessage("press back twice, start the app again, and click checkbox...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                prefs.edit().putBoolean("cancel", false).commit();
            }
        });
        return dialog;
    }// case
    }// switch
    return null;
}// onCreateDialog
}// PrefsActivity

prefs.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference android:key="checkTest" android:title="test" />

</PreferenceScreen>

und das Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="is.it.works" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".PrefsActivity" android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>
</manifest>

LogCat-Fehler:

09-14 10:34:34.472: ERROR/AndroidRuntime(281): Uncaught handler: thread main exiting due to uncaught exception
09-14 10:34:34.502: ERROR/AndroidRuntime(281): android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] is not valid; is your activity running?
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.ViewRoot.setView(ViewRoot.java:456)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.view.Window$LocalWindowManager.addView(Window.java:409)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.Dialog.show(Dialog.java:238)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.Activity.showDialog(Activity.java:2413)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at is.it.works.PrefsActivity.onSharedPreferenceChanged(PrefsActivity.java:27)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.ApplicationContext$SharedPreferencesImpl$EditorImpl.commit(ApplicationContext.java:2727)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.tryCommit(Preference.java:1199)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.persistBoolean(Preference.java:1404)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.CheckBoxPreference.setChecked(CheckBoxPreference.java:155)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.CheckBoxPreference.onClick(CheckBoxPreference.java:143)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.Preference.performClick(Preference.java:811)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.preference.PreferenceScreen.onItemClick(PreferenceScreen.java:190)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.ListView.performItemClick(ListView.java:3246)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1635)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Handler.handleCallback(Handler.java:587)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Handler.dispatchMessage(Handler.java:92)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.os.Looper.loop(Looper.java:123)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at android.app.ActivityThread.main(ActivityThread.java:4203)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at java.lang.reflect.Method.invokeNative(Native Method)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at java.lang.reflect.Method.invoke(Method.java:521)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
09-14 10:34:34.502: ERROR/AndroidRuntime(281):     at dalvik.system.NativeStart.main(Native Method)
09-14 10:34:34.522: INFO/Process(52): Sending signal. PID: 281 SIG: 3
09-14 10:34:34.532: INFO/dalvikvm(281): threadid=7: reacting to signal 3
09-14 10:34:34.592: INFO/dalvikvm(281): Wrote stack trace to '/data/anr/traces.txt'
09-14 10:34:38.533: DEBUG/dalvikvm(107): GC freed 437 objects / 21560 bytes in 136ms
09-14 10:34:39.183: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:44.632: INFO/global(175): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required.
09-14 10:34:47.412: INFO/Process(281): Sending signal. PID: 281 SIG: 9
09-14 10:34:47.472: INFO/ActivityManager(52): Process is.it.works (pid 281) has died.
09-14 10:34:47.492: INFO/WindowManager(52): WIN DEATH: Window{4394f638 is.it.works/is.it.works.PrefsActivity paused=false} 

Nach viel googeln denke ich, das ist der falsche Teil ProgressDialog dialog = new ProgressDialog(this);. Weil this Änderungen. Aber ändern Sie es zu getApplicationContext()oder PrefsActivity.this hilft nichts, das Problem ist immer noch da. Bitte sagen Sie mir, warum das passiert und was die Lösung sein könnte! Danke! Ich stecke fest, und jetzt habe ich keine Ahnung …

  • Verwenden Sie stattdessen getParent() und versuchen Sie es

    – Abhi

    14. September 2011 um 10:47 Uhr

  • Überprüfen Sie diesen Link [BadTokenException ](vinnysoft.blogspot.com/2010/11/…). Das wird dir helfen. Danke Venky.

    – Venki

    14. September 2011 um 11:00 Uhr

  • Die Verwendung von getParent () gibt mir NullpointerException. 🙁

    – Lamas

    14. September 2011 um 11:04 Uhr

  • Danke für die Antwort, diese Seite habe ich auch gefunden. Aber das Zeigen eines Dialogs, nur wenn die Aktivität nicht beendet wird, ist nicht die Lösung. Die Aktivität befindet sich im laufenden Zustand, nachdem Sie zurück gedrückt und erneut gestartet haben. Das Problem sollte sein, dass sich (glaube ich) die Aktivität “ändert” (veränderte “diese” Referenz), nicht dass sie beendet wird.

    – Lamas

    14. September 2011 um 11:11 Uhr


  • @Lama Funktioniert es jetzt, nachdem Sie von dieser Referenz geändert haben?

    – Venki

    14. September 2011 um 11:16 Uhr

Benutzer-Avatar
Tiger

Ich hatte ein sehr ähnliches Problem (das mich hierher gebracht hat) und fand eine sehr einfache Lösung dafür. Obwohl mein Code anders ist, sollte er einfach anzupassen sein. Hier ist meine Lösung:

public void showBox() {
    mActive = true;
    if (! ((Activity) mContext).isFinishing()) {
        mDialogBox.show();
    }
} 

Im Beispielcode in der Frage wäre die Lösung also (geschätzt) gewesen:

@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    if (key.equals("checkTest")) {
        if (! this.isFinishing()) {
            showDialog(1);
        }
    }
    if (key.equals("cancel")) {
        dismissDialog(1);
    }
}// onSPC

  • Sie sollten einen booleschen Wert nicht mit einem anderen booleschen Wert vergleichen, sondern den booleschen Wert verwenden ! Operator (oder nichts) statt.

    – Darkhogg

    12. Februar 2013 um 11:37 Uhr


  • Ist eine Frage des Stils, nicht der Funktionalität. Beide sind technisch gleich, aber: stackoverflow.com/questions/2661110/… programers.stackexchange.com/questions/136908/… Letztere hat eine Antwort, die mir gefällt: Es ist einfacher zu lesen, wie in ! liest sich wie nicht und Java-Bezeichner sind normalerweise englisch lesbar.

    – Darkhogg

    13. Februar 2013 um 10:00 Uhr


  • Danke für die Links Darkhogg. Einige gute Punkte werden angesprochen. Das obige Antwortbeispiel wurde geändert und ich werde jetzt auch meinen Codestil ändern.

    – Tiger

    13. Februar 2013 um 22:56 Uhr

  • Diese Besetzung zu Activity ist überflüssig.

    – Androiderson

    16. September 2013 um 13:37 Uhr

  • @Exception-al Für den ersten Beispielcode ist die Activity Besetzung wurde als erforderlich mContext wurde als übergeben Context Objekt. Ich denke jedoch, dass Sie für das zweite Codebeispiel richtig sind, also habe ich es entfernt.

    – Tiger

    17. September 2013 um 0:55 Uhr

Benutzer-Avatar
yoryo

Vielleicht haben Sie etwas in Ihrer Aktivität nicht geschlossen oder die Registrierung aufgehoben. Versuchen Sie in diesem Fall, den Broadcastreceiver auf onDestroy abzumelden.

Benutzer-Avatar
MJ Montes

Dies wird normalerweise dadurch verursacht, dass Ihre App versucht, einen Dialog mit einer zuvor abgeschlossenen Datei anzuzeigen Activity Als ein context. Überprüfen Sie dann, dass die Aktivität nicht von einigen anderen Apps oder anderen Auslösern geschlossen wird, bevor Sie den Dialog anzeigen

if (!isFinishing()) {
    //showdialog here
    }

Nachdem ich die Absturzverfolgung in einem Projekt eingeführt hatte, bemerkte ich, dass dieses Problem ziemlich häufig auftauchte, und stellte fest, dass derselbe Fix während des gesamten Projekts funktionierte, um den Absturz zu beseitigen:

  • Dialoge niemals als lokale Variablen deklarieren/instanziieren.
  • Machen Sie alle Dialoge zu Instanzvariablen der Aktivität.
  • OnDestroy überschreiben und aufrufen if(dialog != null) dialog.dismiss();

Beispiel:

MyActivity extends Activity {
  ProgressDialog mProgressDialog;
  AlertDialog mAlertDialog;


  @Override
  public void onCreate(Bundle savedInstanceState) {
    mProgressDialog = new ProgressDialog(MyActivity.this);
    mAlertDialog = new AlertDialog.Builder(MyActivity.this).show();
  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    if(mProgressDialog != null) {
      mProgressDialog.dismiss();
    }
    if(mAlertDialog != null) {
      mAlertDialog.dismiss();
    }
  }

Es ist irreführend, dass die Fehlermeldung “Fenster kann nicht hinzugefügt werden” lautet, da ich festgestellt habe, dass der Fehler auftritt, wenn Sie eine Aktivität verlassen und der Kontext, der an Ihren Dialog übergeben wurde, tot ist.

Für mich hat dies das Problem gelöst. Überprüfen, ob der Dialog null ist oder nicht angezeigt wird, und wenn ja, dann erneut erstellen.

    // create alert dialog
    if (enableNetworkDialog == null || !enableNetworkDialog.isShowing())
        enableNetworkDialog = alertDialogBuilder.create();
    if (context instanceof AppCompatActivity && !((AppCompatActivity) context).isFinishing())
        enableNetworkDialog.show(); 

Benutzer-Avatar
Tharaka Nirmana

Die Top-Lösung verhindert nur den Absturz. Für mich war das Problem, dass ich einen falschen weitergeleitet hatte context um den Warndialog anzuzeigen. Nach dem Passieren der richtigen contextdas Problem wurde gelöst.

1179510cookie-checkAndroid: „BadTokenException: Fenster konnte nicht hinzugefügt werden; läuft Ihre Aktivität?“ beim Anzeigen des Dialogs in PreferenceActivity

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy