Ошибка: BinderProxy @ 45d459c0 недействителен; ваша деятельность работает? - PullRequest
127 голосов
/ 18 октября 2011

Что это за ошибка ... я не нашел обсуждения этой ошибки в сообществе stackoverflow Подробнее: -

10-18 23:53:11.613: ERROR/AndroidRuntime(3197): Uncaught handler: thread main exiting due to uncaught exception
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@45d459c0 is not valid; is your activity running?
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.ViewRoot.setView(ViewRoot.java:468)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.Dialog.show(Dialog.java:239)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.vishal.contacte.Locationlistener$MyLocationListener.onLocationChanged(Locationlistener.java:86)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:179)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:112)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:128)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.os.Looper.loop(Looper.java:123)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at android.app.ActivityThread.main(ActivityThread.java:4363)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invokeNative(Native Method)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at java.lang.reflect.Method.invoke(Method.java:521)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197):     at dalvik.system.NativeStart.main(Native Method)

Ответы [ 10 ]

312 голосов
/ 24 января 2013

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

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

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

Я использую это для решения этой проблемы на старых версиях Android уже несколько лет, и с тех пор не видел сбоя.

9 голосов
/ 04 июля 2017

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

if (!MainActivity.this.isFinishing()){
    alertDialog.show();
}
2 голосов
/ 24 декабря 2015

Я столкнулся с этой ошибкой, когда в моем приложении было countDownTimer.В моем приложении был метод, вызывающий GameOver:

public void onFinish() {
     GameOver();
}

, но на самом деле игра могла быть закончена до истечения времени из-за неправильного щелчка пользователя (это была игра с кликом).Поэтому, когда я смотрел на диалоговое окно Game Over, например, через 20 секунд, я забыл отменить countDownTimer, поэтому, когда время истекло, диалоговое окно появилось снова.Или по какой-то причине произошел сбой при указанной выше ошибке.

1 голос
/ 01 ноября 2018

Я решаю эту проблему, используя WeakReference<Activity> в качестве контекста. Крушение никогда не появлялось снова. Вот пример кода в Котлине:

Класс диспетчера диалогов:

class DialogManager {

        fun showAlertDialog(weakActivity: WeakReference<Activity>) {
            val wActivity = weakActivity.get()
            wActivity?.let {
                val builder = AlertDialog.Builder(wActivity, R.style.MyDialogTheme)
                val inflater = wActivity.layoutInflater
                val dialogView = inflater.inflate(R.layout.alert_dialog_info, null)
                builder.setView(dialogView)

                // Set your dialog properties here. E.g. builder.setTitle("MyTitle")

                builder.create().show()
            }
         }

}

И вы показываете диалог следующим образом:

 val dialogManager = DialogManager()
 dialogManager.showAlertDialog(WeakReference<Activity>(this@MainActivity))

Если вы хотите быть супер-защищенным от сбоев. Вместо builder.create().show() используйте:

val dialog = builder.create()
safeShow(weakActivity, dialog)

Это safeShow метод:

private fun safeShow(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (!dialog.isShowing && !(wActivity).isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.show()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }

Это аналогичный метод, который можно использовать для безопасного закрытия диалогового окна:

private fun safeDismissAlertDialog(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
        val wActivity = weakActivity.get()
        if (null != dialog && null != wActivity) {
            // Api >=17
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (dialog.isShowing && !wActivity.isFinishing && !wActivity.isDestroyed) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            } else {

                // Api < 17. Unfortunately cannot check for isDestroyed()
                if (!dialog.isShowing && !(wActivity).isFinishing) {
                    try {
                        dialog.dismiss()
                    } catch (e: Exception) {
                        //Log exception
                    }
                }
            }
        }
    }
1 голос
/ 06 июня 2018

если диалог вызывает эту проблему из-за потока, вы должны запустить его в потоке пользовательского интерфейса следующим образом: -

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                dialog.show();

            }
        });
1 голос
/ 31 октября 2017

В моем случае проблема заключалась в том, что Context хранилось как слабая ссылка в классе, который расширяет Handler. Затем я передавал Messenger, который оборачивает обработчик, через Intent в Service. Я делал это каждый раз, когда активность появлялась на экране в методе onResume().

Итак, как вы понимаете, Messenger был сериализован вместе со своими полями (включая контекст), потому что это единственный способ передать объекты, используя Intent - для их сериализации. В тот момент, когда Messenger был передан в службу, само действие все еще не было готово для отображения диалогов, поскольку оно находится в другом состоянии (как говорится на Resume (), которое абсолютно отличается от того, когда действие уже находится на экране). Поэтому, когда мессенджер был десериализован, контекст все еще находился в состоянии возобновления, в то время как действие фактически уже было на экране. Кроме того, десериализация выделяет память для нового объекта, который полностью отличается от исходного.

Решение состоит в том, чтобы просто связываться со службой каждый раз, когда вам это нужно, и возвращать связыватель, имеющий метод, такой как 'setMessenger (Messenger messenger)', и вызывать его, когда вы привязаны к службе.

1 голос
/ 05 августа 2017

Исправить это довольно просто. Просто проверьте, проходит ли Действие в завершающей фазе, прежде чем отображать диалог:

  private Handler myHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
    switch (msg.what) {
      case DISPLAY_DLG:
        if (!isFinishing()) {
        showDialog(MY_DIALOG);
        }
      break;
    }
  }
};

подробнее здесь

0 голосов
/ 30 апреля 2019

как насчет создания нового экземпляра этого диалога, который вы хотите вызвать?Я на самом деле только что встретил ту же проблему, и это то, что я делаю.так что вместо:

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

как насчет этого?

 YourDialog mDialog = new YourDialog();
 mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
                        }

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

Как и я, в моем случае я пытался создать один экземпляр (из Fragment onCreate ) и вызвать экземпляр этого диалога в другом содержимом adaptorList , и это приведет к "ваша деятельность выполняется" - ошибка .Я думал, что это потому, что я просто создаю один экземпляр (из onCreate), а затем он уничтожается, поэтому, когда я пытался вызвать его из другого adapterList , я вызываю диалог из старого экземпляра.

Я не уверен, подходит ли мое решение для памяти или нет, потому что я не пытался его профилировать, но оно работает (конечно, безопасно, если вы не создадите слишком много экземпляров)

0 голосов
/ 13 апреля 2019

В моем случае я забыл прокомментировать finish ();

0 голосов
/ 19 ноября 2018

Эта ошибка возникает, когда вы показываете диалог для контекста, который больше не существует.

Перед вызовом .show() убедитесь, что действие / контекст не заканчивается

if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
    alert.show();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...