Android: ProgressDialog.show() crashes with getApplicationContext
Asked Answered
T

18

111

I can't seem to grasp why this is happening. This code:

mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);

works just fine. However, this code:

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

throws the following exception:

W/WindowManager(  569): Attempted to add window with non-application token WindowToken{438bee58 token=null}.  Aborting.
D/AndroidRuntime( 2049): Shutting down VM
W/dalvikvm( 2049): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
E/AndroidRuntime( 2049): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 2049): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tastekid.TasteKid/com.tastekid.TasteKid.YouTube}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.access$2100(ActivityThread.java:116)
E/AndroidRuntime( 2049):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
E/AndroidRuntime( 2049):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 2049):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.main(ActivityThread.java:4203)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
E/AndroidRuntime( 2049):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2049): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.view.ViewRoot.setView(ViewRoot.java:460)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 2049):    at android.app.Dialog.show(Dialog.java:238)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:107)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:90)
E/AndroidRuntime( 2049):    at com.tastekid.TasteKid.YouTube.onCreate(YouTube.java:45)
E/AndroidRuntime( 2049):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
E/AndroidRuntime( 2049):    ... 11 more

Any ideas why this is happening? I'm calling this from the onCreate method.

Trolley answered 13/10, 2009 at 17:41 Comment(1)
If you are using Fragment, #24825614Grimbly
Z
42

Which API version are you using? If I'm right about what the problem is then this was fixed in Android 1.6 (API version 4).

It looks like the object reference that getApplicationContext() is returning just points to null. I think you're having a problem similar to one I had in that some of the code in the onCreate() is being run before the window is actually done being built. This is going to be a hack, but try launching a new Thread in a few hundred milliseconds (IIRC: 300-400 seemed to work for me, but you'll need to tinker) that opens your ProgressDialog and starts anything else you needed (eg. network IO). Something like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    // do all your other stuff here

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog = ProgressDialog.show(
               YouTube.this.getApplicationContext(), "",
               YouTube.this.getString(R.string.loading), true);

            // start time consuming background process here
        }
    }, 1000); // starting it in 1 second
}
Zanze answered 13/10, 2009 at 19:56 Comment(4)
I'm using 1.6. I'm pretty sure any UI operations should be done in the UI thread, thus calling ProgressDialog.show() in a separate thread could easily be a big problem. Still think this is weird.Trolley
In the example I gave you aren't doing UI operations in another thread, the other thread is just calling back to the UI thread telling it to open the dialog.Zanze
@KomodoDave I just realized I have the same problem. However, the bad hack is in the timer. This is a timing window waiting to intermittently fail in some situations. The key to success might be in setting a shorter timer, check to see if the application is ready, redelay the action until it is. Probably limit how many times to try as well.Cellar
It's not weird, he is using a Handler. I wouldn't have created another thread to display an alert dialog but it really depends what you're trying to do.Staciastacie
G
129

I am using Android version 2.1 with API Level 7. I faced with this (or similar) problem and solved by using this:

Dialog dialog = new Dialog(this);

instead of this:

Dialog dialog = new Dialog(getApplicationContext());
Ghibelline answered 24/5, 2010 at 19:23 Comment(3)
I had a similar issue, but was using an ActivityGroup. The only way I was able to solve this error was by using getParent() instead.Convoke
How does this answer his question? He asks WHY the second one does not work, while the first one does.Envisage
-1, 'this' is just the same as 'getApplicationContext()' for some of us.Jerid
G
64

For me worked changing

builder = new AlertDialog.Builder(getApplicationContext());

to

builder = new AlertDialog.Builder(ThisActivityClassName.this);

Weird thing is that the first one can be found in google tutorial and people get error on this..

Gametogenesis answered 24/5, 2011 at 13:17 Comment(2)
This is the correct way to do it. Never use ApplicationContext unless strictly necessary and above all, never use it to display UI elements. That's what activities (and ultimately fragments) are for.Staciastacie
This is the one. this all alone won't work if you are doing that inside a, for example, click listener.Escribe
Z
42

Which API version are you using? If I'm right about what the problem is then this was fixed in Android 1.6 (API version 4).

It looks like the object reference that getApplicationContext() is returning just points to null. I think you're having a problem similar to one I had in that some of the code in the onCreate() is being run before the window is actually done being built. This is going to be a hack, but try launching a new Thread in a few hundred milliseconds (IIRC: 300-400 seemed to work for me, but you'll need to tinker) that opens your ProgressDialog and starts anything else you needed (eg. network IO). Something like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    // do all your other stuff here

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog = ProgressDialog.show(
               YouTube.this.getApplicationContext(), "",
               YouTube.this.getString(R.string.loading), true);

            // start time consuming background process here
        }
    }, 1000); // starting it in 1 second
}
Zanze answered 13/10, 2009 at 19:56 Comment(4)
I'm using 1.6. I'm pretty sure any UI operations should be done in the UI thread, thus calling ProgressDialog.show() in a separate thread could easily be a big problem. Still think this is weird.Trolley
In the example I gave you aren't doing UI operations in another thread, the other thread is just calling back to the UI thread telling it to open the dialog.Zanze
@KomodoDave I just realized I have the same problem. However, the bad hack is in the timer. This is a timing window waiting to intermittently fail in some situations. The key to success might be in setting a shorter timer, check to see if the application is ready, redelay the action until it is. Probably limit how many times to try as well.Cellar
It's not weird, he is using a Handler. I wouldn't have created another thread to display an alert dialog but it really depends what you're trying to do.Staciastacie
E
23

I don't think this is a timing issue around a null application context

Try extending Application within your app (or just use it if you already have)

public class MyApp extends Application

Make the instance available as a private singleton. This is never null

private static MyApp appInstance;

Make a static helper in MyApp (which will use the singleton)

    public static void showProgressDialog( CharSequence title, CharSequence message )
{
    prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This!
}

BOOM!!

Also, check out android engineer's answer here: WindowManager$BadTokenException

One cause of this error may be trying to display an application window/dialog through a Context that is not an Activity.

Now, i agree, it does not make sense that the method takes a Context param, instead of Activity..

Ednaedny answered 5/5, 2010 at 22:32 Comment(0)
P
10

Having read the above answers i found that for my situation the following fixed the issue.

This threw the error

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

Based on the previous answers that suggested the context was the wrong one, i changed the getApplicationContext() to retrieve the context from the View passed in to the buttons onClick method.

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

I don't fully understand the workings of Java so i could be wrong, but I'm guessing that for my specific situation the cause could have been related to the fact that the above snippet was defined in an Abstract Activity class; inherited and used by many Activities, perhaps that contributed to the fact that getApplicationContext() doesn't return a valid context?? (Just a guess).

Propitious answered 12/11, 2010 at 12:30 Comment(0)
A
6

I am creating a map view with itemized overlays. I was creating my itemizedoverlay like this from my mapActivity:

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

I found that I would get the "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application" exception when my itemizedoverlay's onTap method was triggered(when the location is tapped on the mapview).

I found that if I simply passed, 'this' instead of 'getApplicationContext()' to my constructor, the problem went away. This seems to support alienjazzcat's conclusion. weird.

Arthralgia answered 6/8, 2010 at 19:32 Comment(0)
G
4

For Activities shown within TabActivities use getParent()

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

instead of

final AlertDialog.Builder builder = new AlertDialog.Builder(this);
Gameto answered 9/1, 2012 at 11:53 Comment(0)
I
3

For Android 2.2
Use this code:

//activity is an instance of a class which extends android.app.Activity
Dialog dialog = new Dialog(activity);

instead of this code:

// this code produces an ERROR:
//android.view.WindowManager$BadTokenException: 
//Unable to add window -- token null is not for an application
Context mContext = activity.getApplicationContext();
Dialog dialog = new Dialog(mContext);

Remark: My custom dialog is created outside activity.onCreateDialog(int dialogId) method.

Incinerator answered 26/5, 2011 at 10:7 Comment(0)
A
3

Try -

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
Armin answered 11/7, 2011 at 13:6 Comment(1)
Needed when the current activity is inside an activitygroupFingerbreadth
B
2

Had a similar problem with (compatibility) Fragments in which using a getActivity() within ProgressDialog.show() crashes it. I'd agree that it is because of timing.

A possible fix:

mContext = getApplicationContext();

if (mContext != null) {
    mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true);
}

instead of using

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

Place the mContext as early as possible to give it more time to grab the context. There's still no guarantee that this will work, it just reduces the likelihood of a crash. If it still doesn't work, you'd have to resort to the timer hack (which can cause other timing problems like dismissing the dialog later).

Of course, if you can use this or ActivityName.this, it's more stable because this already points to something. But in some cases, like with certain Fragment architectures, it's not an option.

Burlie answered 14/2, 2013 at 3:50 Comment(0)
S
2

(For future references)

I think it's because there's differences in Application Context and Activity Context, as explained here: http://www.doubleencore.com/2013/06/context/

Which means that we can't show dialog using Application Context. That's it.

Selfreliant answered 2/3, 2014 at 15:12 Comment(0)
T
2

For using dialogs inside activities, do it this way:

private Context mContext;
private AlertDialog.Builder mBuilder;

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

     //using mContext here refering to activity context
     mBuilder = new AlertDialog.Builder(mContext);
     //...
     //rest of the code
     //...
}

For using dialogs inside fragments, do it this way:

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View mRootView = inflater.inflate(R.layout.fragment_layout, container, false);
      mContext = getActivity();

      //using mContext here refering to fragment's hosting activity context
      mBuilder = new AlertDialog.Builder(mContext);
      //...
      //rest of the code
      //...
      return mRootView;
}

That's it ^_^

Timaru answered 19/9, 2016 at 13:31 Comment(0)
B
1

What I did to get around this was to create a base class for all my activities where I store global data. In the first activity, I saved the context in a variable in my base class like so:

Base Class

public static Context myucontext; 

First Activity derived from the Base Class

mycontext = this

Then I use mycontext instead of getApplicationContext when creating dialogs.

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();
Boldt answered 1/8, 2010 at 8:15 Comment(0)
N
1

If you're calling ProgressDialog.show() in a fragment, casting the mContext to Activity worked for me.

     ProgressDialog pd = new ProgressDialog((Activity) mContext);
Novosibirsk answered 20/7, 2016 at 1:34 Comment(0)
J
1

This is a common problem. Use this instead of getApplicationContext() That should solve your problem

Jaques answered 25/6, 2018 at 6:18 Comment(0)
V
0

I have implemented Alert Dialog for exception throwing on to the current activitty view.Whenever I had given like this

AlertDialog.Builder builder = new AlertDialog.Builder(context);

Given same Window Exception.I write code for alert out of onCreate().So simple I used context = this; after setContentView() statement in onCreate() method.Taken context variable as global like Context context;

Code sample is

static Context context;

 public void onCreate(Bundle savedInstanceState)  { 
        super.onCreate(savedInstanceState); 


        setContentView(R.layout.network); 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        context = this;
.......

Alert Method Sample is

private void alertException(String execMsg){
        Log.i(TAG,"in alertException()..."+context);
        Log.e(TAG,"Exception :"+execMsg);
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
.......

It works fine for me.Actually I searched for this error on StackOverflow I found this query.After reading all responses of this post, I tried this way so It works .I thought this is a simple solution for overcome the exception.

Thanks, Rajendar

Venditti answered 22/6, 2010 at 6:12 Comment(0)
S
0

if you have a problem on groupActivity dont use this. PARENT is a static from the Parent ActivityGroup.

final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);

instead of

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());
Shutt answered 3/2, 2012 at 11:50 Comment(0)
I
0

A dialog is always created and displayed as a part of an Activity. You need to pass in an Activity context instead of the Application context.

http://developer.android.com/guide/topics/ui/dialogs.html#ShowingADialog

Impi answered 3/10, 2012 at 19:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.