エラー:BinderProxy @ 45d459c0は無効です。あなたの活動は実行されていますか?


143

このエラーとは...私はこのエラーに関する議論を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)

このリンクを確認してください:Android – [バックグラウンドスレッドからダイアログを表示する](dimitar.me/android-displaying-dialogs-from-background-threads
Naveen

あなたのリンクは受け入れられた答えに似ていますが、はるかによく調べられています。それをありがとう
LuckyMalaka 2013


回答:


343

これは、アクティビティが破棄されているときに、バックグラウンドスレッドの実行後にダイアログを表示しようとしているために発生する可能性があります。

このエラーは、ダイアログを呼び出すアクティビティが何らかの理由で終了したとき、またはダイアログを表示しようとしたときに、アプリの一部から時々報告されるのを見ていました。これが私のためにそれを解決したものです:

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

私はこれを数年前のAndroidの古いバージョンの問題を回避するために使用しており、その後のクラッシュは見ていません。


1
これは実際にはトリックです!しかし、それが発生した場合でもダイアログを開く方法はありますか?これが発生したときにダイアログを管理する方法が本当にわかりません。助言がありますか?前もって感謝します!
Carla Urrea Stabile

@CarlaStabileこんにちは!これが発生したときにダイアログを表示すると考えることができる唯一の方法は、完了していないアクティビティの有効なコンテキストを取得できるかどうかです。これは、このコードを呼び出している場所と、取得する方法があるかどうかによって異なります別の非仕上げアクティビティからのコンテキスト。
DiscDev 2015年

8
どうもありがとう!私にとって、ダイアログボックスが表示される前に戻るボタンを押すと、クラッシュ(上記のエラーメッセージが表示される)が発生しました。そのため、別のアクティビティを行っていても、コードは継続して表示しようとします。しかし、これはクラッシュを止め、私は簡単に新しいアクティビティに行きました!
Azurespot 2015年

1
多くの同様の質問がありますが、それらのどれにもこれが示唆されていません。個人的には、これが私のシナリオに対する唯一の正しい解決策でした。
fillobotto 2016

これのkotlinバージョンは何ですか?isFinishing()で十分でしょうか?
Alok Rajasukumaran、2018年

12

私は同じ問題に直面し、上記のDiscDevによって提案されたコードを次のように少し変更して使用しました。

if (!MainActivity.this.isFinishing()){
    alertDialog.show();
}

(アクティビティ)コンテキストの平均がMainActivity.thisだったので変更しました。また、ユーザープロフィールのリンクについては正しいですが、上記で見つけることができると思いました。
Hamza Polat 2017

4

スレッドのためにダイアログがこの問題を解決している場合は、そのようなUIスレッドでこれを実行する必要があります。

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

            }
        });

2

このエラーは、存在しないコンテキストのダイアログを表示しているときに発生します。

呼び出す前に.show()、アクティビティ/コンテキストが終了していないことを確認してください

if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
    alert.show();
}

1

countDownTimerアプリでを使用しているときにこのエラーが発生しました。それは私のアプリでGameOverを呼び出すメソッドを持っていました

public void onFinish() {
     GameOver();
}

しかし実際には、ユーザーの誤ったクリック(クリックゲーム)が原因で、時間切れになる前にゲームが終了した可能性があります。たとえば、20秒後に[ゲームオーバー]ダイアログを見ていると、キャンセルするのを忘れていたcountDownTimerので、時間が経過するとダイアログが再び表示されました。または、何らかの理由で上記のエラーでクラッシュしました。


1

これに対する修正は非常に簡単です。ダイアログを表示する前に、アクティビティが終了フェーズにあるかどうかをテストします。

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

もっと見るこちら


1

私の場合、問題はContext、拡張するクラスの弱い参照として保持されていたことでしたHandler。次にMessenger、ハンドラをラップするを介してをに渡していIntentましたServiceonResume()メソッドの画面にアクティビティが表示されるたびにこれを行っていました。

ご存知のように、Messengerはフィールド(コンテキストを含む)と共にIntentシリアル化されました。それは、オブジェクトをシリアル化するために-を使用してオブジェクトを渡す唯一の方法だからです。メッセンジャーがサービスに渡された瞬間、別の状態(onResume()と呼ばれているため、アクティビティがすでに画面上にあるときとはまったく異なります)であるため、アクティビティ自体はまだダイアログを表示する準備ができていませんでした。そのため、メッセンジャーが逆シリアル化されたとき、コンテキストはまだ再開状態でしたが、実際にはアクティビティが画面上にありました。さらに、デシリアライゼーションは、元のオブジェクトとは完全に異なる新しいオブジェクトにメモリを割り当てます。

解決策は、必要になるたびにサービスにバインドし、「setMessenger(Messenger messenger)」のようなメソッドを持つバインダーを返し、サービスにバインドされているときにそれを呼び出すことです。


1

この問題をWeakReference<Activity>コンテキストとして使用することで解決します。クラッシュは二度と現れませんでした。Kotlinのサンプルコードを次に示します。

ダイアログマネージャークラス:

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

0

呼び出したいダイアログの新しいインスタンスを作成してみませんか?私は実際に同じ問題に遭遇したばかりで、それが私がやっていることです。そうではなく:

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

これはどう?

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

ダイアログを表示するほうが安全かどうかをチェックするだけではなく、新しいインスタンスを作成してダイアログを表示する方がはるかに安全だと思います。

私と同じように、私の場合、(フラグメント onCreateから)1つのインスタンスを作成し、adapterListの別のコンテンツでそれらのダイアログのインスタンスを呼び出そうとすると、「is your activity running」エラーが発生します。(onCreateから)1つのインスタンスを作成すると、それが破棄されるためだと思ったので、別のadapterListからそれを呼び出そうとしたときに、古いインスタンスからダイアログを呼び出しました。

私のソリューションがメモリフレンドリかどうかはわかりません。プロファイリングを試みていないためですが、機能します (確かに、インスタンスをあまり作成しないのであれば安全です)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.