web-dev-qa-db-fra.com

Android: "BadTokenException: impossible d'ajouter une fenêtre; votre activité est en cours d'exécution?" lors de l’affichage du dialogue dans PréférenceActivité

J'aimerais demander de l'aide: Dans mon application, je n'ai qu'une seule activité, une PreferenceActivity (pas besoin d'autre, c'est juste une application de synchronisation d'arrière-plan simple, donc la PrefsActivity est la fenêtre principale/lanceur. Une fois les préférences de configuration définies par l'utilisateur, vérifie une checkBoxPreference et le démarrage (ou l'arrêt) d'un service. Au démarrage, une boîte de dialogue apparaît. Mais voici le problème: si l'utilisateur appuie en arrière (quitte l'activité), redémarrez-le et tente de vérifier la checkBoxPref., La prefsactivity plante. Le dialogue ne montre pas. Je ne sais pas pourquoi ni comment y remédier.

Ce code est exactement pareil avec cette partie, ce qui me pose le problème:

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>

et le manifeste:

<?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>

Erreur LogCat:

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 Android.os.BinderProxy@43756de8 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} 

Après avoir beaucoup cherché sur Google, je pense que la mauvaise partie est le ProgressDialog dialog = new ProgressDialog(this);. Cause this changements. Mais le changer en getApplicationContext(), ou PrefsActivity.this ne résout pas le problème, le problème est toujours là… .. S'il vous plaît, dites-moi pourquoi cela se produit et quelle pourrait être la solution! Je vous remercie! Je suis coincé, et maintenant je n'ai aucune idée ...

54
Lama

J'ai eu un problème très similaire (qui m'a atterri ici) et a trouvé une solution très simple pour cela. Bien que mon code soit différent, il devrait être facile à adapter. Voici ma solution:

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

Ainsi, dans l'exemple de code de la question, le correctif aurait été (à deviner):

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

Peut-être que vous n'avez pas fermé ou annulé quelque chose dans votre activité. Dans ce cas, essayez de désenregistrer le broadcastcastreceiver de onDestroy. 

3
yoryo

Pour moi, cela a résolu le problème .. vérifier si le dialogue est nul ou ne s'affiche pas et si oui, créer à nouveau.

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

Après avoir introduit le suivi des incidents dans un projet, j’ai remarqué que ce problème se posait assez souvent et que le même correctif fonctionnait tout au long du projet pour éliminer le blocage: 

  • Ne jamais déclarer/instancier des dialogues en tant que variables locales.
  • Définissez toutes les variables d'instance Dialogs de l'activité.
  • Remplacez onDestroy et appelez if (dialog! = Null) dialog.dismiss ();

Exemple:

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

Il est trompeur que le message d'erreur indique "impossible d'ajouter une fenêtre" car j'ai constaté que l'erreur se produit lorsque vous quittez une activité et que le contexte transmis à votre boîte de dialogue est mort.

1
Brendan Weinstein

La solution supérieure empêche uniquement le crash. Pour moi, le problème était que j'avais renvoyé une context erronée pour afficher le dialogue d'alerte. Après avoir passé la context correcte, le problème a été résolu.

0
TharakaNirmana

Cela est généralement dû au fait que votre application tente d'afficher une boîte de dialogue en utilisant une activité déjà terminée comme contexte. Ensuite, vérifiez que l'activité n'est pas fermée par d'autres applications ou d'autres déclencheurs avant d'afficher la boîte de dialogue.

if (!isFinishing()) {
    //showdialog here
    }
0
Las Lemieux