使用 AsyncTask 在后台服务中添加 android 进度对话框,获取致命异常
Adding android progress dialog inside Background service with AsyncTask,Getting FATAL Exception
我正在从计划服务中调用一个 Asynctask 每 10 分钟它将 运行.
而 运行 服务,进度对话框 从 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.view.WindowManager$BadTokenException: 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
中设置 ProgressDialog
,onPreExecute()
和 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;
}
我正在从计划服务中调用一个 Asynctask 每 10 分钟它将 运行.
而 运行 服务,进度对话框 从 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.view.WindowManager$BadTokenException: 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
中设置 ProgressDialog
,onPreExecute()
和 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;
}