Nie można dodać okna - token android.os.BinderProxy jest nieprawidłowy; czy Twoja aktywność biegnie?

116

Próbuję połączyć się z Facebookiem przez Facebook API, podążam za tym przykładem: https://github.com/facebook/facebook-android-sdk/tree/master/examples/simple

Wszystko jest w porządku, ale kiedy próbuję edytować jakiś kod, mam na myśli, że chcę wyświetlić komunikat w oknie dialogowym po pomyślnym zalogowaniu się w następujący sposób:

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

W logcacie pojawia się ten błąd:

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)

Dowolny pomysł?

Han Tran
źródło
1
Sprawdź odpowiedź poniżej. Zaznaczam, że to poprawne :)
Han Tran,
To, że zaznaczyłeś odpowiedź, nie zmienia faktu, że jest to zduplikowane pytanie. Drugi został zapytany jako pierwszy i jest to identyczny problem z zasadniczo identyczną odpowiedzią.
bsara
1
Widziałeś, że moje pytanie jest 2 lata temu?
Han Tran,
1
Więc wyglądaj jak inni Moderator ma błąd, ale Ty :)) Anw, dzięki!
Han Tran,

Odpowiedzi:

127

Może się to zdarzyć, gdy wyświetlasz okno dialogowe kontekstu, który już nie istnieje. Typowy przypadek - jeśli operacja „show dialog” jest wykonywana po operacji asynchronicznej, a podczas tej operacji pierwotna aktywność (która ma być elementem nadrzędnym twojego okna dialogowego) jest niszczona. Aby uzyskać dobry opis, zobacz ten post na blogu i komentarze:

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

Z powyższego śladu stosu wynika, że ​​biblioteka Facebooka odwraca operację auth asynchronicznie, a masz mechanizm Handler - Callback (wywoływany onComplete na odbiorniku), który może łatwo stworzyć taki scenariusz.

Kiedy widziałem to zgłoszone w mojej aplikacji, jest to dość rzadkie i pasuje do doświadczenia z postu na blogu. Coś poszło nie tak w działaniu / zostało zniszczone podczas pracy AsyncTask. Nie wiem, w jaki sposób Twoja modyfikacja może spowodować to za każdym razem, ale być może odwołujesz się do działania jako kontekstu okna dialogowego, które jest zawsze niszczone do czasu wykonania kodu?

Ponadto, chociaż nie jestem pewien, czy jest to najlepszy sposób na stwierdzenie, czy Twoja aktywność jest uruchomiona, zapoznaj się z tą odpowiedzią, aby poznać jedną z metod:

Sprawdź, czy aktywność jest aktywna

Peter Pascale
źródło
3
Brak połączenia dialog.show()rozwiązuje problem, ale jakie jest obejście tego problemu, aby nadal móc wyświetlać moje okno dialogowe?
natsumiyu
Dla mnie dzwonię Fragment.getContext(), co działa dla interfejsów API powyżej 21. Ale na Lollipop zawiesza się
TheRealChx101
158

Widziałem ten błąd zgłaszany od czasu do czasu z niektórych moich aplikacji, a oto, co go rozwiązało:

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

Wszystkie inne odpowiedzi wydają się robić dziwne rzeczy, takie jak iterowanie listy uruchomionych działań, ale jest to znacznie prostsze i wydaje się, że załatwia sprawę.

DiscDev
źródło
6
nie rozwiązuje problemu, zapobiega zawieszaniu się i wyświetlaniu okna dialogowego
YTerle,
6
Pamiętaj tylko, że powinieneś sprawdzić, context instanceof Activitybo możesz dostać Exception!
FtheBuilder
3
lub możesz użyć getActivity (). isFinishing () zamiast kontekstu
Nikita Axyonov
Używam API-23. Kiedy próbuję użyć tego w mojej MainActivity, która rozszerza AppCompatActivity. Pokazuje mi błąd typu Spowodowane przez: java.lang.ClassCastException: com.creativeapp.hindihdvideosongs.AppController nie można przesłać do android.app.Activity pod adresem com.creativeapp.hindihdvideosongs.MainActivity.onCreate (MainActivity.java:145) AppController jest dodane do mojego AndroidMenifest
pavel
Nie używam żadnego dialogu i otrzymuję ten błąd.
Abdul Waheed
11

jednym prostym obejściem jest wychwycenie wyjątku:

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

Nie jest to eleganckie, ale czasami łatwe, gdy musisz zarządzać operacjami asynchronicznymi i nie masz pewności, czy aktywność jest aktywna, czy nie, kiedy chcesz wyświetlić okno dialogowe.

gerz
źródło
1
tak brzydkie, ale tak piękne!
Rahul Tiwari
8
  • W moim przypadku problem wystąpił z powodu próby otwarcia / wyświetlenia okna dialogowego w onPostExecuteAsyncTask

  • Jednak jest to zła metoda showing dialoglub zmiany interfejsu użytkownika w onPostExecute.

  • W tym celu musimy sprawdzić, czy aktywność jest aktywna Np .: !isFinishing() jeśli czynność nie została zakończona , możemy tylko wyświetlić nasze okno dialogowe lub zmianę interfejsu użytkownika.

    @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());
                            }
                        }
                    }
                });
    }
Agilanbu
źródło
1

Miałem dokładnie ten sam problem. Dzwonienie '(!isFinishing())'zapobiegło awarii, ale nie mogło wyświetlić komunikatu „alert”.

Następnie spróbowałem ustawić funkcję wywołującą jako „statyczną” , w której wyświetlany jest alert. Po tym nie nastąpiła żadna awaria, a komunikat jest również wyświetlany.

Na przykład:

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();      
    }
ArunJTS
źródło
1

Po wykonaniu wątku dodaj te dwie linie kodu, a to rozwiąże problem.

Looper.loop();
Looper.myLooper().quit();
Balachandran Muthuraj
źródło
1

Innym zastosowaniem deweloper sprawa: Jeśli WindowManagerlub getWindow()jest nazywany na onCreate()lub onStart()lub onResume(), A BadTokenExceptionjest wyrzucane. Będziesz musiał poczekać, aż widok zostanie przygotowany i dołączony.

Przeniesienie kodu, aby onAttachedToWindow()go rozwiązać. Może nie jest to trwałe rozwiązanie, ale o ile mogłem przetestować, zawsze działało.

W moim przypadku zaistniała potrzeba zwiększenia jasności ekranu, gdy aktywność stała się widoczna. Linia getWindow().getAttributes().screenBrightnessw onResume()wyniku spowodowała wyjątek. Przeniesienie kodu do onAttachedToWindow()pracy.

Ram Iyer
źródło
0

U mnie zostało to naprawione po prostu przez usunięcie staticwłaściwości w metodach DialogHelper.class (odpowiedzialnych za tworzenie i ukrywanie okna dialogowego), ponieważ mam właściwości związane z Windowtymi metodami

Dasser Basyouni
źródło
0

W zależności od usług nic z powyższych nie pomogło mi, skończyło się na tym, jak poniżej:

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

Muszę używać „podwójnej klasy”, ponieważ interfejs nie może być statyczny. L-

Legion
źródło
0

Nie można dodać okna - token jest nieprawidłowy; czy Twoja aktywność biegnie?

Ta awaria jest zwykle spowodowana przez aplikację, która próbuje wyświetlić okno dialogowe, używając jako kontekstu wcześniej ukończonego działania. Na przykład może się to zdarzyć, jeśli działanie wyzwala AsyncTask, które próbuje wyświetlić okno dialogowe po jego zakończeniu, ale użytkownik przechodzi z powrotem z działania przed ukończeniem zadania.

Zasoby zewnętrzne

Android - wyświetlanie okien dialogowych z wątków w tle

Błąd: BinderProxy @ 45d459c0 jest nieprawidłowy; czy Twoja aktywność biegnie?

Bholendra Singh
źródło
0

Rozwiązałem to, umieszczając to:

@Override
protected void onDestroy() {
    accessTokenTracker.stopTracking();
    super.onDestroy();
}
Juan L. Antón Santamaria
źródło
Przy wysyłaniu proszę wybrać język angielski
Pedro Coelho