Adding android progress dialog inside Background service with AsyncTask,Getting FATAL Exception
Asked Answered
B

6

7
  1. Iam calling a Asynctask from Scheduled Service Every 10 mins it will Run.

  2. while running the Service, Progress dialog getting Exception from OnpreExecute.

ERROR :

FATAL EXCEPTION: main                                                                                    
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:594)

at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)

at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)

at android.app.Dialog.show(Dialog.java:286)

EDIT 1: Alarm Manager for calling the service for every 5 mins

/*Alarm manager Service for From Server*/
private void setServerFetch() {
    // for  to Server to GPS PING
    Intent myIntent1 = new Intent(LoginPage.this, AlarmService.class);
    pendingintent1 = PendingIntent.getService(LoginPage.this, 1111, myIntent1, 0);
    AlarmManager alarmManager5 = (AlarmManager) getSystemService(ALARM_SERVICE);
    Calendar calendar1 = Calendar.getInstance();
    calendar1.setTimeInMillis(System.currentTimeMillis());
    calendar1.add(Calendar.SECOND, 1);
    alarmManager5.set(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), pendingintent1);
    alarmManager5.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), 300 * 1000, pendingintent1);

}

Calling the AsyncTask from Service Onstart

 @Override
    public void onStart(Intent intent, int startId)
    {
        super.onStart(intent, startId);


        try
        {

                Asynctask_Incident task=new Asynctask_Incident();
                task=new();

        }
        catch (Exception e)
        {
            e.printStackTrace();
            Log.i("PING", "EXCEPTION in reading Data from Web Async task ONstart.!");

        }

    }

Asynctask Class onStart Method

public class Asynctask_Incident extends AsyncTask<String, Void, Void>
    {


        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();

            runOnUiThread(new Runnable() {

                @Override
                public void run() {

                    if (!pDialog.isShowing())
                    {
                        pDialog = new ProgressDialog(appContext);
                        pDialog.setCanceledOnTouchOutside(false);
                        pDialog.setCancelable(false);
                        pDialog.setMessage("Please Wait Updating Data From...");
                        pDialog.show();
                    }
                }
            });


        }

        @Override
        protected Void doInBackground(String... params)
        {
            try {
                getAPICall();

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

                if (pDialog.isShowing()) {
                    pDialog.dismiss();
                }

            }

            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid)
        {

            super.onPostExecute(aVoid);

            if (pDialog.isShowing()) {
                pDialog.dismiss();
            }


        }


    }

Help me to Solve this Issue.

Barozzi answered 16/8, 2016 at 12:11 Comment(7)
Are you starting the service from Activity or from other class?Hid
@AbdulhamidDhaiban -Using Alarm Manager starting the Service Inside activity .Barozzi
github.com/nickfox/Update-Android-UI-from-a-Service Link i triedBarozzi
so no possibility to add Progress bar, if Background service is running by Alarm manager Every 5 mins?Barozzi
There are two scenarios: 1) if you want to run periodic task from background service, even if the app is closed, you shouldn't show progress dialog. It is bad ux and againest android policies to show dialog outside your app. 2) if you want to run progress dialog, then your app should be opened. Then you can start a periodic handler that starts the AsyncTask. Let me know which scinario works for you to give you detailed code.Hid
@AbdulhamidDhaiban 2nd Scenario -i want Progress dialog Only when App is Open. my background Service will Run every 5 mins once using Pending intent with alarm Manger. When My method is going to execute inside Onstart Progresss dialog should start(it should be like pDialog.setCanceledOnTouchOutside(false) not Clickable anything on the app), after finishing execution it will be dismissed.Barozzi
Check scenario2 in my updated answer.Hid
H
3

Actually you can't start a progress dialog from a service, because it needs the activity context not application context which come to be null in your case.

More info here: link1 , link2 and link3

If you want to trigger progress dialog based on service action, you may use Observer design patter, look here.

Update: If your app is running, you can use Handler and run it each 5 minutes.

Here is a complete example:

public class TestActivity extends AppCompatActivity {

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            //
            new Asynctask_Incident(TestActivity.this).execute("url");
            handler.postDelayed(this, 5 * DateUtils.MINUTE_IN_MILLIS);
        }
    }, 0);
}

public class Asynctask_Incident extends AsyncTask<String, Void, Void> {


    ProgressDialog pDialog;
    Context appContext;

    public Asynctask_Incident(Context ctx) {
        appContext = ctx;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

            pDialog = new ProgressDialog(appContext);
            pDialog.setCanceledOnTouchOutside(false);
            pDialog.setCancelable(false);
            pDialog.setMessage("Please Wait Updating Data From...");
            pDialog.show();


    }

    @Override
    protected Void doInBackground(String... params) {
        try {
            getAPICall();

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

            if (pDialog.isShowing()) {
                pDialog.dismiss();
            }

        }

        return null;
    }

    private void getAPICall() {

        //5 seconds delay for test, you can put your code here
        try {
            Thread.sleep(5 * DateUtils.SECOND_IN_MILLIS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPostExecute(Void aVoid) {

        super.onPostExecute(aVoid);

        if (pDialog.isShowing()) {
            pDialog.dismiss();
        }


    }


}

}
Hid answered 21/8, 2016 at 13:46 Comment(6)
Please Check my updated Question. using Observer add any code snippet along with my question.Barozzi
Thanks for your Reply,where is my service ?. my webservice method is placed inside service Onstart.Barozzi
@Kumer, this code replaces a service. You don't need to use Service and AlarmManager. Because the Service main purpose is when your app is closed. But while your app is running you can use the handler to repeat your AsyncTask.Hid
Thank you Very Much Friend :), its achieved What i expectedBarozzi
also one more Doubt if another Activity page is Opened top this page it will Run the Every 5 mins Handler?Barozzi
Also, you can get the handler in other activities: check this url: linkHid
E
3

Intialize your ProgressDialog.

OnPreExecute();

runOnUiThread(new Runnable() {

                @Override
                public void run() {

                    if (pDialog == null)
                    {
                       pDialog = new ProgressDialog(appContext);
                        pDialog.setCanceledOnTouchOutside(false);
                        pDialog.setCancelable(false);
                        pDialog.setMessage("Please Wait Updating Data From...");

                    }

                   pDialog.show();
                }
            });

OnPostExecute();

 pDialog.dismiss();
Emissary answered 17/8, 2016 at 5:12 Comment(3)
wait i am trying, already Prgressdialog i intialized inside Oncreate.Barozzi
still iam getting same Error :( Please help me.Barozzi
i tried in this Line pDialog.show(); is getting the Exception:android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an applicationBarozzi
H
3

Actually you can't start a progress dialog from a service, because it needs the activity context not application context which come to be null in your case.

More info here: link1 , link2 and link3

If you want to trigger progress dialog based on service action, you may use Observer design patter, look here.

Update: If your app is running, you can use Handler and run it each 5 minutes.

Here is a complete example:

public class TestActivity extends AppCompatActivity {

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            //
            new Asynctask_Incident(TestActivity.this).execute("url");
            handler.postDelayed(this, 5 * DateUtils.MINUTE_IN_MILLIS);
        }
    }, 0);
}

public class Asynctask_Incident extends AsyncTask<String, Void, Void> {


    ProgressDialog pDialog;
    Context appContext;

    public Asynctask_Incident(Context ctx) {
        appContext = ctx;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

            pDialog = new ProgressDialog(appContext);
            pDialog.setCanceledOnTouchOutside(false);
            pDialog.setCancelable(false);
            pDialog.setMessage("Please Wait Updating Data From...");
            pDialog.show();


    }

    @Override
    protected Void doInBackground(String... params) {
        try {
            getAPICall();

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

            if (pDialog.isShowing()) {
                pDialog.dismiss();
            }

        }

        return null;
    }

    private void getAPICall() {

        //5 seconds delay for test, you can put your code here
        try {
            Thread.sleep(5 * DateUtils.SECOND_IN_MILLIS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPostExecute(Void aVoid) {

        super.onPostExecute(aVoid);

        if (pDialog.isShowing()) {
            pDialog.dismiss();
        }


    }


}

}
Hid answered 21/8, 2016 at 13:46 Comment(6)
Please Check my updated Question. using Observer add any code snippet along with my question.Barozzi
Thanks for your Reply,where is my service ?. my webservice method is placed inside service Onstart.Barozzi
@Kumer, this code replaces a service. You don't need to use Service and AlarmManager. Because the Service main purpose is when your app is closed. But while your app is running you can use the handler to repeat your AsyncTask.Hid
Thank you Very Much Friend :), its achieved What i expectedBarozzi
also one more Doubt if another Activity page is Opened top this page it will Run the Every 5 mins Handler?Barozzi
Also, you can get the handler in other activities: check this url: linkHid
B
1

The exception Exception:android.vi‌​ew.WindowManager$BadT‌​okenException: Unable to add window -- token null is not for an application comes when the context is not alive. There may be other reason for this exception but context is major reason. Moreover, if previously shown Dialog is not dismissed, exception may occur.

Please try this code :

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(appContext != null) {

                    // if dialog is already showing, hide it
                    if(pDialog != null && pDialog.isShowing()) {
                        pDialog.dismiss();
                    }

                    if (pDialog == null) {
                        pDialog = new ProgressDialog(appContext);
                        pDialog.setCanceledOnTouchOutside(false);
                        pDialog.setCancelable(false);
                        pDialog.setMessage("Please Wait Updating Data From...");
                    }
                    pDialog.show();

                } else {
                    Log.e("Error","Context is Null");
               }
            }
        });

An additional check can be added : http://dimitar.me/android-displaying-dialogs-from-background-threads/

Businesslike answered 17/8, 2016 at 8:56 Comment(2)
Still Getting Same Exception... :( not fixedBarozzi
possibility to Show the progressbar, when Background service is Running along with the Asynctask or not?Barozzi
T
1

You do not need to initialize the dialog in a thread in the onPreExecute. Because this method is always called in the UI thread. By calling a thread you are delaying it. So the doInbackground perhaps happened before the dialog was created.

Also you should not call anything that modifies the UI in the doItBackground method. Because this method runs in a worker thread. Any UI call must be in the main thread. The onPostExecute is called by the main thread. So put your dialog related calls there, but not in the doInBackground.

These lines in the doInbackground need to be removed.

if (pDialog.isShowing()) {
                        pDialog.dismiss();
                    }
Tillotson answered 18/8, 2016 at 14:35 Comment(2)
hi Friend, i removed PDialog from DoinBackground, also i removed async task before Method Calling i added Progressdialog before Retrofit called but Error came- android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application. Please help me to fix else give me some code snippet along With my code.Barozzi
Check the answer by Abdulhamid Dhaiban. You can not show dialog in a service. You must have an activity on screen. In your service, you need to start an activity first when you want to show a dialog, and then show the dialog in the activity.Tillotson
S
1

1) You don't need your ProgressDialog setup inside a Runnable, anything in onPreExecute() and onPostExecute() already runs on the UI thread. Only doInBackground() runs off the UI thread.

2) Put AsyncTask class in MainActivity, call it from MainActivity, not from your Service. Call your AsyncTask from the MainActivity like this:

new MyAsyncTask(MainActivity.this).execute("");

3) Finally, put this constructor in your AsyncTask class:

public MyAsyncTask(Context context) {
        appContext = context;
    }
Stylographic answered 22/8, 2016 at 5:55 Comment(3)
How to connect my Service(Its Started By alarm Manger Every 5mins this will run) to Main activity async task.? Please add any code snippet.Barozzi
I'm not sure I understand? It looks like you want the AsyncTask task to start when the Service starts? I'm not too familiar with Alarm Manager .. but I believe there is a way to set the AsyncTask to start on a schedule with AlarmManager and then you'd start your Service in onPostExecute. Search "AsyncTask AlarmManager Service" brings up some solutions if this is what you want to achieve.Stylographic
Ok Iam trying, i let you know if any doubt.Barozzi
I
0

It seems like your context does not have the right set of resources. Make sure that your are using the right context.

Context context = this;
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.show();

where "this" - AppCompatActivity or Activity context

Infusible answered 18/8, 2016 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.