0

Hello I have some trouble while trying to run an alert in my AsyncTask. Whenever something with context is run, the app crashes, like trying to let alert appear.

I am following this tutorial: http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/

I am sure, that the error is because of a wrong "context" or something like that.

I am calling my AsyncTask class from the GCM class like this:

GCM.java:

@Override
protected void onMessage(Context context, Intent intent) {
    Log.i(TAG, "Received message");
    String message = intent.getExtras().getString("price");

//    displayMessage(context, message);
    // notifies user
    generateNotification(context, message);
   runAsync(context);
    // update database
}

// here I want to run my asyncTask
private void runAsync(Context context){
    TestActivity = new TestActivity(context);
    task.execute();
}

TestActivity.java:

Context mContext;

public TestActivity(Context context) {
    this.mContext = context;
} 
// Progress Dialog
private ProgressDialog pDialog;

@Override
    protected void onPreExecute() {
        super.onPreExecute();
        productsList = new ArrayList<HashMap<String, String>>();

        pDialog = new ProgressDialog(mContext);
        pDialog.setMessage("Loading products. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
    // here when It shall show the alert it crashes... with the following error
      pDialog.show();

    }

  F/AndroidRuntime(19976): FATAL EXCEPTION: IntentService[GCM-980252920256-1]
  F/AndroidRuntime(19976): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
  F/AndroidRuntime(19976):  at android.view.ViewRootImpl.setView(ViewRootImpl.java:792)
  F/AndroidRuntime(19976):  at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:265)
  F/AndroidRuntime(19976):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
  F/AndroidRuntime(19976):  at android.app.Dialog.show(Dialog.java:282)
  F/AndroidRuntime(19976):  at com.test.app.TestActivity.onPreExecute(TestActivity.java:72)
  F/AndroidRuntime(19976):  at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
  F/AndroidRuntime(19976):  at android.os.AsyncTask.execute(AsyncTask.java:534)
  F/AndroidRuntime(19976):  at com.test.app.GCM.asyncTaskRun(GCM.java:63)
  F/AndroidRuntime(19976):  at com.test.app.GCM.onMessage(GCM.java:55)
  F/AndroidRuntime(19976):  at com.google.android.gcm.GCMBaseIntentService.onHandleIntent(GCMBaseIntentService.java:223)
  F/AndroidRuntime(19976):  at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
  F/AndroidRuntime(19976):  at android.os.Handler.dispatchMessage(Handler.java:99)
  F/AndroidRuntime(19976):  at android.os.Looper.loop(Looper.java:176)
  F/AndroidRuntime(19976):  at android.os.HandlerThread.run(HandlerThread.java:60)

Where is my error?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Steve
  • 127
  • 1
  • 10

2 Answers2

1

ProgressDialog needs an Activity as Context (that's a bad design in Android, Context is not always the required Context).

You should open an Activity that looks like a dialog:

See Android Activity as a dialog

Community
  • 1
  • 1
brummfondel
  • 1,202
  • 1
  • 8
  • 11
0

Pass context as an Activity not as an ApplicationContext. Both classes extends Context class.

michal.z
  • 2,025
  • 1
  • 15
  • 10
  • how can I do it? can you explain? – Steve Dec 04 '14 at 17:12
  • `mContext` variable which you pass to `ProgressDialog` constructor is propably an instance of `ApplicationContext` class. Try passing instance of `Activity` class to `ProgressDialog` constructor. If `TestActivity` is really `Activity` as you wrote in one comment and so extends `Activity` class then pass `TestActivity.this` to `ProgressDialog` constructor. As I can see looking into your code `AsyncTask` is defined as nested class inside `Activity` class so this solution should work. – michal.z Dec 04 '14 at 17:19
  • hmm sorry,, I've think I missunderstood something... TestActivity does not extend Activity... this is how TestActivity.java looks like: public class TestActivity extends AsyncTask {... and thats how GCM.java looks like: public class GCM extends GCMBaseIntentService { – Steve Dec 04 '14 at 17:24
  • Ok. So first of all name TestActivity for `AsyncTask` is really misleading. You should name it TestAsyncTask or something like that. Now, you have to find a way to pass `Activity` class instance to the `ProgressDialog` constructor. You're passing context to the constructor of `AsyncTask`. But in `runAsync` method of `GCM` class pass instance of currently running `Activity` to `TestActivity` constructor not context which you have from 'onMessage' method. – michal.z Dec 04 '14 at 17:34
  • yes I renamed it... tried everything to get the right context from activity to ProgressDialog but still could not solve that... hm – Steve Dec 06 '14 at 13:47
  • tried with public TestAsyncTask(Context context) { this.mContext = context.getApplicationContext(); } still does not work... – Steve Dec 06 '14 at 14:05
  • i tried to run asyntask in mainactiviy with : TestAsyncTask task = new TestAsyncTask(MainActivity.this); task.execute();... that worked. :S but when İ try to do the same with GCMIntentService it does not work... it also do not accept TestAsyncTask task = new TestAsyncTask(MainActivity.this); task.execute(); ... when I replace MainActivity with context... there is no syntax error but there is the problem again with the wrong context... İ am really confused :D – Steve Dec 06 '14 at 15:39
  • Ok. As you see if you pass Activity instance to TestAsyncTask constructor then everything works fine. You saw that by running TestAsyncTask in your main activity. But now you want to run TestAsyncTask in Service. How to accomplish that? You need to have currently visible Activity instance accessable from service and pass that instance to TestAsyncTask constructor. You need to pass that Activity instance from main acticity to Service. How to do that? You need to bundle your service to main activity. Then communication between them will be possible and so passing activity instance either – michal.z Dec 06 '14 at 15:59
  • In last comment I meant 'bind service to main activity' not 'bundle service to main activity'. Sorry for that. – michal.z Dec 06 '14 at 16:08