Не удалось добавить оконный токен android.os.BinderProxy недействителен; работает ли ваша деятельность?

Я пытаюсь подключиться к Facebook через API Facebook, я следую этому примеру: https://github.com/facebook/facebook-android-sdk/tree/master/examples/simple

Все в порядке, но когда я пытаюсь отредактировать какой-либо код, я имею в виду, что хочу отобразить сообщение с диалоговым сообщением после успешного входа в систему:

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

Я получаю эту ошибку в logcat:

03-02 13:32:08.629: E/AndroidRuntime(14991): android.view.WindowManager$BadTokenException: Unable to add window -- token [email protected] 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)

Любая идея?

Ответ 1

Это может произойти, когда вы показываете диалог для контекста, который больше не существует. Обычный случай - если операция "показать диалог" после асинхронной операции, и во время этой операции исходное действие (то есть должно быть родителем вашего диалога) уничтожено. Для хорошего описания см. Это сообщение в блоге и комментарии:

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

Из вышеприведенной трассировки стека кажется, что библиотека facebook асинхронно отключает аут-операцию, и у вас есть механизм Handler-Callback (onComplete, вызываемый слушателем), который может легко создать этот сценарий.

Когда я видел это в своем приложении, его довольно редко и соответствует опыту в блоге. Что-то пошло не так для деятельности/оно было разрушено во время работы AsyncTask. Я не знаю, как ваша модификация может привести к этому каждый раз, но, возможно, вы ссылаетесь на Activity как на контекст для диалога, который всегда уничтожается ко времени выполнения вашего кода?

Кроме того, хотя я не уверен, что это лучший способ узнать, работает ли ваша активность, см. этот ответ для одного метода:

Проверьте, активна ли активность

Ответ 2

Я видел, что эта ошибка сообщалась раз в то время из некоторых моих приложений, и вот что решило это для меня:

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

Все остальные ответы там, кажется, делают странные вещи, такие как повторение списка запущенных действий, но это намного проще и, похоже, делает трюк.

Ответ 3

Один простой обходной путь - поймать исключение:

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

Это не элегантно, но иногда легко, когда вам нужно управлять асинхронными операциями, и вы не уверены, активна ли активность или нет, когда вы хотите показать диалоговое окно.

Ответ 4

На этом веб-сайте перечислены 3 различных метода проверки, если определенный Activity работает, и предоставляет фрагменты кода для помочь тебе. Однако имейте в виду, что проверка того, что активность еще выполняется, предназначена только для отладки, поскольку ее результат не является чем-то конкретным и, следовательно, не подходит для потока кода/логики.

Ответ 5

  • В моем случае проблема возникает из-за того, что я пытаюсь открыть/показать диалоговое окно в onPostExecute AsyncTask

  • Однако это неправильный метод showing dialog или изменений пользовательского onPostExecute в onPostExecute.

  • Для этого нам нужно проверить, что активность активна. Например !isFinishing(), если операция не завершена, то мы можем показать только наше диалоговое окно или изменение пользовательского интерфейса.

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

Ответ 6

Я столкнулся с такой же проблемой. Вызов '(!isFinishing())' предотвратил сбой, но не смог отобразить сообщение "alert".

Затем я попытался сделать функцию вызова 'static', где отображается предупреждение. После этого не произошло сбоя, и сообщение также отображается.

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

Ответ 7

После выполнения потока добавьте эти две строки кода, и это решит проблему.

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

Ответ 8

Для меня это было исправлено простым удалением static свойства в методах DialogHelper.class(resposble для создания и скрытия диалога), так как у меня есть свойства, связанные с Window в этих методах

Ответ 9

В зависимости от услуг ничего из вышеперечисленного не помогло мне, в итоге я сделал следующее:

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

Я должен использовать "двойной класс", потому что интерфейс не может быть статическим. L-