154

What is this error... i haven't found any discussion on this error in the stackoverflow community Detailed :-

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)
VISHAL DAGA
  • 3,616
  • 8
  • 41
  • 50
  • Possible duplicate of [Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?](https://stackoverflow.com/questions/9529504/unable-to-add-window-token-android-os-binderproxy-is-not-valid-is-your-activ) – Pod Sep 22 '17 at 10:47
  • http://dimitar.me/android-displaying-dialogs-from-background-threads/ – niketshah09 Jan 04 '19 at 07:30
  • check this link: Android – [Displaying Dialogs From Background Threads ](http://dimitar.me/android-displaying-dialogs-from-background-threads/) – Naveen Feb 16 '12 at 09:19
  • Your link is simmilar to the accepted answer, but it is much better expained. Thanks for that – LuckyMalaka Apr 17 '13 at 13:53

10 Answers10

366

This is most likely happening because you are trying to show a dialog after execution of a background thread, while the Activity is being destroyed.

I was seeing this error reported once in a while from some of my apps when the activity calling the dialog was finishing for some reason or another when it tried to show a dialog. Here's what solved it for me:

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

I've been using this to work around the issue on older versions of Android for several years now, and haven't seen the crash since.

DiscDev
  • 36,864
  • 20
  • 113
  • 130
  • 2
    This actually does the trick! but is there a way to open the dialog even if that happens? I'm not really sure of how to manage the dialog when this happens. Any suggestions? Thanks in advance! – Carla Urrea Stabile Jun 22 '15 at 16:52
  • @CarlaStabile hi! The only way I can think to show a dialog when this happens would be if you can obtain a valid Context for an activity that isn't finishing - it would depend where you're calling this code and if you have a way to retrieve a context from another, non-finishing activity. – DiscDev Jun 23 '15 at 19:40
  • 9
    Thanks a million! For me, the crash (with error message above) would happen when I pressed the back button, before the Dialog box showed. So the code would continue and try to show it, even though I was in a different activity. But this stopped the crash and I went to the new activity with ease! – Azurespot Nov 10 '15 at 08:24
  • 1
    There are many similar questions, but in none of them was suggested this. Personally this was the only correct solution for my scenario. – fillobotto Apr 03 '16 at 22:06
  • what is the kotlin version for this? will isFinishing() be enough? – Alok Rajasukumaran Oct 12 '18 at 09:37
  • @DiscDev got once the crash "is your activity running?" even after adding this check **if(!((Activity) context).isFinishing())** – itabdullah Oct 20 '19 at 15:56
  • I don't understand why this answer was selected. Casting a Context to an Activity causes a ClassCastException. – FractalBob Dec 12 '19 at 11:38
  • @FractalBob This should only happen if the passed context is not actually an Activity. Please check what type the object is that you pass as `context`. – Benjamin Basmaci Jan 28 '20 at 14:42
  • is `isFinishing() == true` even if the finished process is completed? Or does finishing the activity actually solve that problem by destroying the dialog in the process? – Benjamin Basmaci Jan 28 '20 at 14:43
  • Short, succinct, and to the point. Thanks man for saving so much of my time. – Tajveer Singh Nijjar Jan 29 '21 at 01:49
12

I faced the same problem and used the code proposed by DiscDev above with minor changes as follows:

if (!MainActivity.this.isFinishing()){
    alertDialog.show();
}
SRack
  • 8,800
  • 5
  • 38
  • 50
Hamza Polat
  • 325
  • 3
  • 7
  • i changed because (Activity) context mean was MainActivity.this for my case. Also you are right about the user profile link, but i thought that you can find it above. – Hamza Polat Jul 06 '17 at 10:00
5

if dialog is trowing this problem because of the thread you should do run this on UI thread like that :-

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

            }
        });
Rahul Rao
  • 51
  • 1
  • 2
2

This error occurs when you are showing the dialog for a context that no longer exists.

Before calling .show() check that activity/context is not finishing

if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
    alert.show();
}
matdev
  • 3,317
  • 4
  • 26
  • 42
akhilesh0707
  • 5,244
  • 4
  • 34
  • 44
1

I encountered this error when I had a countDownTimer in my app. It had a method calling GameOver in my app as

public void onFinish() {
     GameOver();
}

but actually the game could be over before the time was up due to a wrong click of the user (it was a clicking game). So when I was looking at the Game Over dialog after e.g. 20 seconds, I forgot to cancel the countDownTimer so once the time was up, the dialog appeared again. Or crashed with the above error for some reason.

erdomester
  • 11,491
  • 31
  • 126
  • 226
1

The fix to this is pretty simple. Just test if the Activity is going through its finishing phase before displaying the Dialog:

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

see more here

Diego Venâncio
  • 4,095
  • 2
  • 31
  • 56
1

In my case, the problem was that Context was kept as a weak reference in the class that extends Handler. Then I was passing Messenger, that wraps the handler, through an Intent to a Service. I was doing this each time the activity appeared on screen in onResume() method.

So as you understand, Messenger was serialized together with its fields (including context), because it is the only way to pass objects using Intent - to serialize them. At that moment when Messenger was passed to the service, the activity itself still wasn't ready for showing dialogs as it is in another state (being said onResume(), that is absolutely different from when the activity is already on the screen). So when messenger was deserialized, the context still was at the resuming state, while the activity actually was already on the screen. Moreover, deserialization allocates memory for new object, that is completely different from the original one.

The solution is just to bind to the service each time you need it and return a binder that has a method like 'setMessenger(Messenger messenger)' and call it, when you are binded to the service.

Turkhan Badalov
  • 668
  • 1
  • 9
  • 17
1

I solve this problem by using WeakReference<Activity> as a context. The crash never appeared again. Here is a sample code in Kotlin:

Dialog manager class:

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

}

And you show the dialog like this:

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

If you want to be super-duper protected from crashes. Instead of builder.create().show() use:

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

This is the safeShow method:

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

This is a similar method that you could use for safe dismissing the dialog:

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
                    }
                }
            }
        }
    }
Ivo Stoyanov
  • 13,531
  • 5
  • 50
  • 52
0

how about makes a new Instance of that dialog you want to call? I've actually just met the same problem, and that is what I do. so rather than :

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

how about this?

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

so rather than just checking is it safe or not to show the dialog, I think it's much more safe if we just create a new instance to show the dialog.

Like me, In my case I tried to create one instance (from a Fragment onCreate) and call the instance of those dialog in another content of adapterList and this will result in "is your activity running"- error. I thought that was because I just create one instance (from onCreate) and then it is get destroyed, so when I tried to call it from another adapterList I calling the dialog from old instance.

I am not sure if my solution is memory friendly or not, because I haven't tried to profile it, but it works (well surely, it is safe if you do not create too many instance)

Dan
  • 1
  • 1
0

In Kotlin

if (!(context is Activity && context.isFinishing)) {
            pausingDialog!!.show()
        }
Sandeep Pareek
  • 300
  • 2
  • 7