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ł?
Odpowiedzi:
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
źródło
dialog.show()
rozwiązuje problem, ale jakie jest obejście tego problemu, aby nadal móc wyświetlać moje okno dialogowe?Fragment.getContext()
, co działa dla interfejsów API powyżej 21. Ale na Lollipop zawiesza sięWidziałem ten błąd zgłaszany od czasu do czasu z niektórych moich aplikacji, a oto, co go rozwiązało:
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ę.
źródło
context instanceof Activity
bo możesz dostaćException
!jednym prostym obejściem jest wychwycenie wyjątku:
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.
źródło
W moim przypadku problem wystąpił z powodu próby otwarcia / wyświetlenia okna dialogowego w
onPostExecute
AsyncTaskJednak jest to zła metoda
showing dialog
lub zmiany interfejsu użytkownika wonPostExecute
.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.źródło
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:
źródło
Po wykonaniu wątku dodaj te dwie linie kodu, a to rozwiąże problem.
źródło
Innym zastosowaniem deweloper sprawa: Jeśli
WindowManager
lubgetWindow()
jest nazywany naonCreate()
lubonStart()
lubonResume()
, ABadTokenException
jest 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().screenBrightness
wonResume()
wyniku spowodowała wyjątek. Przeniesienie kodu doonAttachedToWindow()
pracy.źródło
U mnie zostało to naprawione po prostu przez usunięcie
static
właściwości w metodach DialogHelper.class (odpowiedzialnych za tworzenie i ukrywanie okna dialogowego), ponieważ mam właściwości związane zWindow
tymi metodamiźródło
W zależności od usług nic z powyższych nie pomogło mi, skończyło się na tym, jak poniżej:
Muszę używać „podwójnej klasy”, ponieważ interfejs nie może być statyczny. L-
źródło
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?
źródło
Rozwiązałem to, umieszczając to:
źródło