web-dev-qa-db-fra.com

Impossible d'ajouter une fenêtre - Le jeton Android.os.BinderProxy n'est pas valide. Votre activité est-elle en cours?

J'essaie de me connecter à Facebook via Facebook API, je suis cet exemple: https://github.com/facebook/facebook-Android-sdk/tree/master/examples/simple

Tout va bien, mais quand j'essaye de modifier du code, je veux dire que je veux afficher le message après le dialogue après que la connexion soit réussie comme ceci:

public void onAuthSucceed() {
        mText.setText("You have logged in! ");   
        //This is the code to call the post message dialog.                     
        mFacebook.dialog(Example.this, "feed",new SampleDialogListener());   
    }

Je reçois cette erreur dans le logcat:

03-02 13:32:08.629: E/AndroidRuntime(14991): Android.view.WindowManager$BadTokenException: Unable to add window -- token Android.os.BinderProxy@405180f8 is not valid; is your activity running?
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.view.ViewRoot.setView(ViewRoot.Java:532)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:177)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.view.Window$LocalWindowManager.addView(Window.Java:424)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.app.Dialog.show(Dialog.Java:241)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.Facebook.dialog(Facebook.Java:780)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.Facebook.dialog(Facebook.Java:737)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.Example$SampleAuthListener.onAuthSucceed(Example.Java:113)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.SessionEvents.onLoginSuccess(SessionEvents.Java:78)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.Example$LoginDialogListener.onComplete(Example.Java:88)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.Facebook$1.onComplete(Facebook.Java:320)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.facebook.Android.FbDialog$FbWebViewClient.shouldOverrideUrlLoading(FbDialog.Java:144)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.Java:218)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.webkit.CallbackProxy.handleMessage(CallbackProxy.Java:337)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.os.Handler.dispatchMessage(Handler.Java:99)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.os.Looper.loop(Looper.Java:130)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Android.app.ActivityThread.main(ActivityThread.Java:3687)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Java.lang.reflect.Method.invokeNative(Native Method)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at Java.lang.reflect.Method.invoke(Method.Java:507)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:867)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:625)
03-02 13:32:08.629: E/AndroidRuntime(14991):    at dalvik.system.NativeStart.main(Native Method)

Une idée? 

84
Han Tran

Cela peut se produire lorsque vous affichez la boîte de dialogue pour un contexte qui n'existe plus. Un cas courant - si l'opération 'show dialog' se produit après une opération asynchrone et que, pendant cette opération, l'activité d'origine (qui doit être le parent de votre boîte de dialogue) est détruite. Pour une bonne description, voir ce blog et ses commentaires:

http://dimitar.me/Android-displaying-dialogs-from-background-threads/

Dans la trace de la pile ci-dessus, il apparaît que la bibliothèque facebook désactive l'opération d'authentification de manière asynchrone et que vous disposez d'un mécanisme Handler - Callback (onComplete appelé sur un écouteur) qui pourrait facilement créer ce scénario.

Quand j'ai vu cela rapporté dans mon application, il est plutôt rare et correspond à l'expérience de l'article du blog. Quelque chose a mal tourné pour l'activité/elle a été détruite pendant le travail de la AsyncTask. Je ne sais pas comment votre modification pourrait entraîner cela à chaque fois, mais vous faites peut-être référence à une activité en tant que contexte du dialogue qui est toujours détruit au moment de l'exécution de votre code?

De plus, même si je ne suis pas sûr que ce soit le meilleur moyen de savoir si votre activité est en cours d'exécution, consultez la réponse ci-dessous pour connaître l'une des méthodes permettant de le faire:

Vérifier si l'activité est active

101
Peter Pascale

Je voyais de temps en temps cette erreur signalée par certaines de mes applications, et voici ce qui l'a résolue pour moi:

if(!((Activity) context).isFinishing())
{
    //show dialog
}

Toutes les autres réponses semblent faire des choses étranges, telles que parcourir la liste des activités en cours, mais cela est beaucoup plus simple et semble faire l'affaire.

122
DiscDev

une solution simple consiste à intercepter l'exception: 

try {
        alertDialog.show()
    }
catch (WindowManager.BadTokenException e) {
        //use a log message
    }

Ce n'est pas élégant mais parfois facile lorsque vous devez gérer des opérations asynchrones et que vous ne savez pas si l'activité est active ou non lorsque vous souhaitez afficher le dialogue.

4
gerz

Ce site Web répertorie 3 méthodes différentes pour vérifier si une certaine Activity est en cours d'exécution et fournit des extraits de code pour vous aider. Cependant, gardez à l'esprit que vérifier si une activité est toujours en cours n'est recommandé que pour le débogage car son résultat est tout sauf certain et ne convient donc pas au flux de code/logique.

3
ACLima

Après avoir exécuté le thread, ajoutez ces deux lignes de code et cela résoudra le problème.

Looper.loop();
Looper.myLooper().quit();
1

J'ai fait face exactement au même problème. L'appel de '(!isFinishing())' a empêché le blocage, mais le message "alerte" n'a pas pu être affiché.

Ensuite, j'ai essayé de créer une fonction d'appel 'static' , où alert est affichée. Après cela, aucun crash ne s'est produit et le message est également affiché.

Pour ex:

public static void connect_failure() {      
        Log.i(FW_UPD_APP, "Connect failed");

        new AlertDialog.Builder(MyActivity)
        .setTitle("Title")
        .setMessage("Message")
        .setPositiveButton(Android.R.string.yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) { 
                  //do nothing
            }
         })
        .setIcon(R.drawable.the_image).show();      
    }
1
ArunJTS

Pour moi, cela a été corrigé en supprimant simplement la propriété static dans les méthodes DialogHelper.class (resposble pour la création et le masquage du dialogue), car j'ai des propriétés liées à Window dans ces méthodes

0
Dasser Basyouni
  • Dans mon cas, le problème est dû à une tentative d'ouvrir/d'afficher une boîte de dialogue dans onPostExecute AsyncTask.

  • Cependant, c’est une mauvaise méthode de showing dialog ou de modification de l’Ui dans onPostExecute.

  • Pour cela, nous devons vérifier que l'activité est active Par exemple: !isFinishing(), si l'activité n'est pas terminée, vous ne pouvez afficher que notre boîte de dialogue ou votre modification. 

    @Override
    protected void onPostExecute(String response_str) {
    
       getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (!((Activity) mContext).isFinishing()) {
                            try {
                                ShowAgilDialog();
                            } catch (WindowManager.BadTokenException e) {
                                Log.e("WindowManagerBad ", e.toString());
                            }
                        }
                    }
                });
    }
    
0
Agilanbu

Sous dependencyServices, rien de ce qui précède ne m'a aidé, j'ai fini par faire comme ci-dessous:

    class Static_Toast_Android
    {
        private static Context _context
        {
            get { return Android.App.Application.Context; }
        }
        public static void StaticDisplayToast(string message)
        {
            Toast.MakeText(_context, message, ToastLength.Long).Show();
        }
    }
    public class Toast_Android : IToast
    {

        public void DisplayToast(string message)
        {
            Static_Toast_Android.StaticDisplayToast(message);
        }
    }

Je dois utiliser la "double-classe" car une interface ne peut pas être statique. L-

0
Legion