[android] "android.view.WindowManager$BadTokenException: Unable to add window" on buider.show()

From my main activity, I need to call an inner class and in a method within the class, I need to show AlertDialog. After dismissing it, when the OK button is pressed, forward to Google Play for purchase.

Things work perfectly for most of the times, but for few users it is crashing on builder.show() and I can see "android.view.WindowManager$BadTokenException: Unable to add window" from crash log. Please suggest.

My code is pretty much like this:

public class classname1 extends Activity{

  public void onCreate(Bundle savedInstanceState) {
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);
    setContentView(R.layout.<view>); 

    //call the <className1> class to execute
  }

  private class classNamename2 extends AsyncTask<String, Void, String>{

    protected String doInBackground(String... params) {}

    protected void onPostExecute(String result){
      if(page.contains("error")) 
      {
        AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
        builder.setCancelable(true);
        builder.setMessage("");
        builder.setInverseBackgroundForced(true);
        builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface dialog, int whichButton){
            dialog.dismiss();
            if(!<condition>)
            {
              try
              {
                String pl = ""; 

                mHelper.<flow>(<class>.this, SKU, RC_REQUEST, 
                  <listener>, pl);
              }

              catch(Exception e)
              {
                e.printStackTrace();
              }
            }  
          }
        });

        builder.show();
      }
    }
  }
}

I have also seen the error in another alert where I am not forwarding to any other activity. It's simple like this:

AlertDialog.Builder builder = new AlertDialog.Builder(classname1.this);
    builder.setCancelable(true);

    //if successful
    builder.setMessage(" ");
    builder.setInverseBackgroundForced(true);
    builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton){
            // dialog.dismiss();
                   }
    });
    builder.show();
}

This question is related to android android-alertdialog

The answer is


I had dialog showing function:

void showDialog(){
    new AlertDialog.Builder(MyActivity.this)
    ...
    .show();
}

I was getting this error and i just had to check isFinishing() before calling this dialog showing function.

if(!isFinishing())
    showDialog();

The possible reason is the context of the alert dialog. You may be finished that activity so its trying to open in that context but which is already closed. Try changing the context of that dialog to you first activity beacause it won't be finished till the end.

e.g

rather than this.

AlertDialog alertDialog = new AlertDialog.Builder(this).create();

try to use

AlertDialog alertDialog = new AlertDialog.Builder(FirstActivity.getInstance()).create();

Try this :

    public class <class> extends Activity{

    private AlertDialog.Builder builder;

    public void onCreate(Bundle savedInstanceState) {
                    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
                    super.onCreate(savedInstanceState);

                setContentView(R.layout.<view>); 

                builder = new AlertDialog.Builder(<class>.this);
                builder.setCancelable(true);
                builder.setMessage(<message>);
                builder.setInverseBackgroundForced(true);

        //call the <className> class to execute
}

    private class <className> extends AsyncTask<String, Void, String>{

    protected String doInBackground(String... params) {

    }
    protected void onPostExecute(String result){
        if(page.contains("error")) //when not subscribed
        {   
           if(builder!=null){
                builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton){
                    dialog.dismiss();
                        if(!<condition>)
                        {
                        try
                        {
                        String pl = ""; 

                        mHelper.<flow>(<class>.this, SKU, RC_REQUEST, 
                        <listener>, pl);
                        }

                        catch(Exception e)
                        {
                        e.printStackTrace();
                        }
                    }  
                }
            });

            builder.show();
        }
    }

}
}

I am creating Dialog in onCreate and using it with show and hide. For me the root cause was not dismissing onBackPressed, which was finishing the Home activity.

@Override
public void onBackPressed() {
new AlertDialog.Builder(this)
                .setTitle("Really Exit?")
                .setMessage("Are you sure you want to exit?")
                .setNegativeButton(android.R.string.no, null)
                .setPositiveButton(android.R.string.yes,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                Home.this.finish();
                                return;
                            }
                        }).create().show();

I was finishing the Home Activity onBackPressed without closing / dismissing my dialogs.

When I dismissed my dialogs the crash disappeared.

new AlertDialog.Builder(this)
                .setTitle("Really Exit?")
                .setMessage("Are you sure you want to exit?")
                .setNegativeButton(android.R.string.no, null)
                .setPositiveButton(android.R.string.yes,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                networkErrorDialog.dismiss() ;
                                homeLocationErrorDialog.dismiss() ;
                                currentLocationErrorDialog.dismiss() ;
                                Home.this.finish();
                                return;
                            }
                        }).create().show();

I got this error, but mine was coming from the Toasts, not a Dialog.

I have Activity and Fragments in my layout. Code for the Toast was in the Activity class. Fragments gets loaded before the Activity.

I think the Toast code was hit before the Context/Activity finished initializing. I think it was the getApplicationContext() in the command Toast.makeText(getApplicationContext(), "onMenutItemActionCollapse called", Toast.LENGTH_SHORT).show();


I try this it solved.

 AlertDialog.Builder builder = new AlertDialog.Builder(
                   this);
            builder.setCancelable(true);
            builder.setTitle("Opss!!");

            builder.setMessage("You Don't have anough coins to withdraw. ");
            builder.setMessage("Please read the Withdraw rules.");
            builder.setInverseBackgroundForced(true);
            builder.setPositiveButton("OK",
                    (dialog, which) -> dialog.dismiss());
            builder.create().show();

In my case I refactored code and put the creation of the Dialog in a separate class. I only handed over the clicked View because a View contains a context object already. This led to the same error message although all ran on the MainThread.

I then switched to handing over the Activity as well and used its context in the dialog creation -> Everything works now.

    fun showDialogToDeletePhoto(baseActivity: BaseActivity, clickedParent: View, deletePhotoClickedListener: DeletePhotoClickedListener) {
        val dialog = AlertDialog.Builder(baseActivity) // <-- here
   .setTitle(baseActivity.getString(R.string.alert_delete_picture_dialog_title))
...
}

I , can't format the code snippet properly, sorry :(


  • first you cannot extend AsyncTask without override doInBackground
  • second try to create AlterDailog from the builder then call show().

    private boolean visible = false;
    class chkSubscription extends AsyncTask<String, Void, String>
    {
    
        protected void onPostExecute(String result)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setCancelable(true);
            builder.setMessage(sucObject);
            builder.setInverseBackgroundForced(true);
            builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton)
                {
                    dialog.dismiss();
                }
            });
    
            AlertDialog myAlertDialog = builder.create();
            if(visible) myAlertDialog.show();
        }
    
        @Override
        protected String doInBackground(String... arg0)
        {
            // TODO Auto-generated method stub
            return null;
        }
    }
    
    
    @Override
    protected void onResume()
    {
        // TODO Auto-generated method stub
        super.onResume();
        visible = true;
    }
    
    @Override
    protected void onStop()
    {
        visible = false; 
        super.onStop();
    }
    

with this globals variables idea, I saved MainActivity instance in onCreate(); Android global variable

public class ApplicationController extends Application {

    public static MainActivity this_MainActivity;
}

and Open dialog like this. it worked.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Global Var
    globals = (ApplicationController) this.getApplication();
    globals.this_MainActivity = this;
}

and in a thread, I open dialog like this.

AlertDialog.Builder alert = new AlertDialog.Builder(globals.this_MainActivity);
  1. Open MainActivity
  2. Start a thread.
  3. Open dialog from thread -> work.
  4. Click "Back button" ( onCreate will be called and remove first MainActivity)
  5. New MainActivity will start. ( and save it's instance to globals )
  6. Open dialog from first thread --> it will open and work.

: )