59 votes

Android : "BadTokenException : Unable to add window ; is your activity running ?" lors de l'affichage de la boîte de dialogue dans PreferenceActivity.

J'aimerais demander de l'aide : Dans mon application, je n'ai qu'une seule activité, une PreferenceActivity (il n'en faut pas d'autres, il s'agit juste d'une simple application de synchronisation en arrière-plan, donc la fonction PrefsActivity est le Main/Launcher). Après que l'utilisateur ait configuré ses préférences, il vérifie un checkBoxPreference et qui démarre (ou arrête) un service. Au démarrage, un dialogue s'affiche. Mais voici le problème : si l'utilisateur appuie sur la touche retour (quitter l'activité), la relance, et essaie ensuite de vérifier la valeur de l'activité. checkBoxPref ., le prefsactivity plantages. Le dialogue ne s'affiche pas. Je n'ai aucune idée de la raison et de la façon de la réparer.

Ce code est exactement le même que celui de cette partie, ce qui me pose 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 des changements. Mais le changer en getApplicationContext() o PrefsActivity.this n'aide pas, le problème est toujours là. S'il vous plaît, dites-moi pourquoi cela se produit, et quelle pourrait être la solution ! Merci ! Je suis coincé, et maintenant je n'ai aucune idée...

4 votes

Utiliser getParent() à la place de ceci et essayer

4 votes

Vérifiez ce lien [BadTokenException ]( vinnysoft.blogspot.com/2010/11/ ). Cela vous aidera. Merci Venky.

1 votes

En utilisant getParent(), je reçois une NullpointerException. :(

84voto

Tigger Points 1904

J'ai eu un problème très similaire (qui m'a conduit ici) et j'ai trouvé une solution très simple. 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, la correction aurait été (à vue de nez) :

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

2 votes

Vous ne devez pas comparer un booléen avec un autre booléen, mais utiliser le booléen ! (ou rien) à la place.

0 votes

Selon le [Docs Android](http://developer.android.com/reference/android/app/Activity.html#isFinishing()) - isFinishing() renvoie soit true o false . Après avoir effectué quelques recherches pour savoir quand il est correct d'utiliser if (! boolean) o if (boolean == false) je n'ai pas réussi à trouver quelque chose de précis. Avez-vous un lien ou quelque chose que je puisse vérifier pour étayer votre affirmation ?

9 votes

C'est une question de style, pas de fonctionnalité. Les deux sont techniquement les mêmes, mais : stackoverflow.com/questions/2661110/ programmateurs.stackexchange.com/questions/136908/ Ce dernier a une réponse qui me plaît : C'est plus facile à lire, comme dans ! se lit comme suit no et les identifiants Java sont généralement lisibles en anglais.

4voto

yoryo Points 31

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

3voto

MJames Montes Points 1

Ce problème est généralement dû au fait que votre application tente d'afficher une boîte de dialogue en utilisant un processus précédemment terminé. Activity como context . Vérifiez ensuite 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
    }

1voto

Amit Tumkur Points 1016

Pour moi, cela a résolu le problème : vérifier si la boîte de dialogue est nulle ou ne s'affiche pas et si oui, la créer à nouveau.

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

1voto

Brendan Weinstein Points 705

Après avoir introduit le suivi des pannes dans un projet, j'ai remarqué que ce problème apparaissait assez fréquemment et j'ai constaté que la même solution fonctionnait dans tout le projet pour éliminer les pannes :

  • Ne jamais déclarer/instancier les dialogues en tant que variables locales.
  • Faire de toutes les boîtes de dialogue des variables d'instance de l'activité.
  • Remplacer onDestroy et appeler if(dialog != null) dialog.dismiss() ;

Ejemplo:

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 dise "impossible d'ajouter une fenêtre" car j'ai constaté que l'erreur se produit lorsque vous quittez une activité et que le contexte qui a été transmis à votre dialogue est mort.

0 votes

Etes-vous sûr d'avoir besoin de fermer les boîtes de dialogue vous-même ? Le code d'Android pour l'activité semble déjà les fermer pour vous : grepcode.com/file_/repository.grepcode.com/java/ext/

0 votes

Oui, cela semble correct. Je travaille généralement sur des bases de code composées de fragments, donc je suppose que j'ai destiné cet article aux fragments lorsque je l'ai écrit en août. Je vais examiner la question et mettre à jour l'article.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X