使用 AsyncTask 在后台服务中添加 android 进度对话框,获取致命异常

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

  1. 我正在从计划服务中调用一个 Asynctask 每 10 分钟它将 运行.

  2. 而 运行 服务,进度对话框OnpreExecute.[=15= 获取异常]

错误

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)

编辑 1: 每 5 分钟调用一次服务的警报管理器

/*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);

}

从 Service Onstart 调用 AsyncTask

 @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 方法

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


        }


    }

帮我解决这个问题。

初始化你的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();

异常 Exception:android.vi‌​ew.WindowManager$BadT‌​okenException: Unable to add window -- token null is not for an application 当上下文不存在时出现。此异常可能还有其他原因,但上下文是主要原因。此外,如果之前显示的对话框没有关闭,可能会出现异常。

请尝试此代码:

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");
               }
            }
        });

可以添加额外的检查:http://dimitar.me/android-displaying-dialogs-from-background-threads/

您的上下文似乎没有正确的资源集。 确保您使用的是正确的上下文。

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

其中 "this" - AppCompatActivity 或 Activity 上下文

您不需要在onPreExecute 的线程中初始化对话框。因为这个方法总是在UI线程中被调用。通过调用线程,您正在延迟它。所以 doInbackground 可能发生在对话框创建之前。

此外,您不应在 doItBackground 方法中调用任何修改 UI 的内容。因为这个方法运行在一个工作线程中。任何 UI 调用都必须在主线程中。 onPostExecute 由主线程调用。所以把你的对话框相关的调用放在那里,而不是在 doInBackground 中。

doInbackground 中的这些行需要删除。

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

实际上您无法从服务启动进度对话框,因为它需要 activity 上下文而不是在您的情况下变为空的应用程序上下文。

更多信息在这里: link1 , link2 and link3

如果你想根据服务动作触发进度对话框,你可以使用观察者设计模式,看here

更新: 如果您的应用 运行ning,您可以每 5 分钟使用一次 Handler 和 运行。

这是一个完整的例子:

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


    }


}

}

1) 您不需要在 Runnable 中设置 ProgressDialogonPreExecute()onPostExecute() 中的任何内容都已在 UI 线程上运行.只有 doInBackground() 从 UI 线程运行。

2) 将 AsyncTask class 放入 MainActivity,从 MainActivity 调用它,而不是从您的 Service 调用它。像这样从 MainActivity 调用你的 AsyncTask

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

3) 最后,将此构造函数放入您的 AsyncTask class:

public MyAsyncTask(Context context) {
        appContext = context;
    }