在 IntentService 中创建 AlertDialog 时无法添加 window
Unable to add window when creating AlertDialog inside an IntentService
我想在 IntentService 中创建一个 AlertDialog,但是当在 AlertDialog.Builder 构造函数中传递上下文时,它显示以下错误:
06-30 00:01:31.265 11994-11994/com.alwa7y W/System.err: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
06-30 00:01:31.267 11994-11994/com.alwa7y W/System.err: at android.view.ViewRootImpl.setView(ViewRootImpl.java:572)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.app.Dialog.show(Dialog.java:319)
at com.go.mushaf.mushafapplication.services.DownloadService$override.showAlert(DownloadService.java:176)
at com.go.mushaf.mushafapplication.services.DownloadService$override.access$dispatch(DownloadService.java)
at com.go.mushaf.mushafapplication.services.DownloadService.showAlert(DownloadService.java:0)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:88)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:61)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access0(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
06-30 00:01:31.268 11994-11994/com.alwa7y W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是创建 AlertDialog 的方法:
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
这是 IntentService class:
package com.go.mushaf.mushafapplication.services;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.go.mushaf.mushafapplication.DownloadActivity;
import com.go.mushaf.mushafapplication.MainActivity;
import java.util.ArrayList;
import static com.go.mushaf.mushafapplication.DownloadActivity.BUNDLE;
import static com.go.mushaf.mushafapplication.DownloadActivity.CONTEXT;
import static com.go.mushaf.mushafapplication.DownloadActivity.TEXT_ID;
import static com.go.mushaf.mushafapplication.DownloadActivity.getLoadingText;
import static com.go.mushaf.mushafapplication.DownloadActivity.mTxtProgress;
import static com.go.mushaf.mushafapplication.DownloadActivity.showEndLoadingNotification;
import static com.go.mushaf.mushafapplication.Utility.getPages;
public class DownloadService extends IntentService {
public int viewId;
Context context;
public static final String TAG = "servicee";
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent.hasExtra(BUNDLE)) {
viewId = intent.getBundleExtra(BUNDLE).getInt(TEXT_ID);
Log.d(TAG, "onHandleIntent: ");
}
new BackGroundTask().execute();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
context = getApplicationContext();
return super.onStartCommand(intent, flags, startId);
}
public class BackGroundTask extends AsyncTask<Void, Integer, Void> {
private final String ASYNC_ERROR = this.getClass().getName();
private RequestBuilder<Drawable> x;
private ArrayList<String> pagesList = getPages();
@Override
protected Void doInBackground(Void... arg0) {
// FIXME: 6/27/2018
doAllCache(mTxtProgress);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// if(x!=null) {
// x.preload();
//// if (!cancelFlag || count < MainActivity.mushafTotal)
//// new BackGroundTask().execute(++count);
// }
showAlert("تم اكتمال التحميل بنجاح", "تم التحميل");
// getApplicationContext(), unable to add window
// DownladService.this, unable to add window
// getBaseContext(), unable to add window
}
private void doAllCache(final TextView mTxtProgress) {
Log.d(TAG, "doAllCache: " + mTxtProgress.getText().toString());
Log.d(TAG, "doAllCache: " + pagesList.size());
for (int i=0; i<pagesList.size(); i++) {
String pageNumber = pagesList.get(i); //get string for page number
Log.d(TAG, "doAllCache: " + pageNumber);
String url = MainActivity.mainUril + pageNumber + ".gif"; // get page url
final int finalI = i;
x = Glide.with(DownloadService.this)
.load(url)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// Log.i("Image Loading End", String.valueOf(i));
mTxtProgress.setText(getLoadingText(getApplicationContext(), finalI));
Log.d(TAG, "onResourceReady: " + resource +"\n"+model.toString()+"\n"+target+"\n"+dataSource);
//// //check cancel
//// if (cancelFlag) {
//// finish();
//// } else {
//
// if (finalI < MainActivity.mushafTotal) {
// final int ii = finalI + 1;
// new BackGroundTask().execute();
//
//// new Handler().postDelayed(new Runnable() {
//// @Override
//// public void run() {//Use your "bitmap" here
//// doAllCache(ii);
//// }
//// }, 100);
// }
//// else{
//// cancelFlag = true;
//// }
//// }
return true;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
Log.d(ASYNC_ERROR, String.valueOf(finalI));
Log.d(ASYNC_ERROR, "onLoadFailed: " + e);
return false;
}
});
}
}
}
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
}
这就是我启动服务的方式:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.download_btn:
startLoadingNotification();
Bundle bundle = new Bundle();
bundle.putInt(TEXT_ID, R.id.txt_load);
// bundle.putSerializable(CONTEXT, (Serializable) DownloadActivity.this);
startService(new Intent(DownloadActivity.this, DownloadService.class).putExtra(BUNDLE, bundle));
mViewDownload.setVisibility(View.GONE);
mViewCancel.setVisibility(View.VISIBLE);
break;
case R.id.cancel_btn:
createLogoutDialog().show();
break;
}
}
我想在 onPostExecute 方法中显示对话框。
我试过:
getApplicationContext(), DownloadService.this, this, getBaseContext()
以上都是同样的错误。
提前致谢。
您不能从 Service
显示 AlertDialog
。您只能显示 Activity
中的 AlertDialog
。在这种情况下,显示来自 activity 的正在启动此服务的对话框。或者,不使用对话框,而是使用 Notification
.
除此之外:
不要在 IntentService
内执行异步操作,因为服务会在 onHandleIntent()
returns 后立即消失。一旦服务消失,您的进程可能会终止,在工作完成之前杀死您的后台线程。删除 BackGroundTask
并将其所有要执行的逻辑移至 onHandleIntent()
。另外,摆脱 Glide 或弄清楚如何让它同步下载图像(据我所知,它做不到)。
IntentService
将无法在 Android 8.0+ 上正常运行,除非您将其设为前台服务并使用 startForegroundService()
。考虑使用 JobIntentService
或在 2019 年及以后使用 WorkManager
.
我想在 IntentService 中创建一个 AlertDialog,但是当在 AlertDialog.Builder 构造函数中传递上下文时,它显示以下错误:
06-30 00:01:31.265 11994-11994/com.alwa7y W/System.err: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
06-30 00:01:31.267 11994-11994/com.alwa7y W/System.err: at android.view.ViewRootImpl.setView(ViewRootImpl.java:572)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.app.Dialog.show(Dialog.java:319)
at com.go.mushaf.mushafapplication.services.DownloadService$override.showAlert(DownloadService.java:176)
at com.go.mushaf.mushafapplication.services.DownloadService$override.access$dispatch(DownloadService.java)
at com.go.mushaf.mushafapplication.services.DownloadService.showAlert(DownloadService.java:0)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:88)
at com.go.mushaf.mushafapplication.services.DownloadService$BackGroundTask.onPostExecute(DownloadService.java:61)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.access0(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
06-30 00:01:31.268 11994-11994/com.alwa7y W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
这是创建 AlertDialog 的方法:
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
这是 IntentService class:
package com.go.mushaf.mushafapplication.services;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.go.mushaf.mushafapplication.DownloadActivity;
import com.go.mushaf.mushafapplication.MainActivity;
import java.util.ArrayList;
import static com.go.mushaf.mushafapplication.DownloadActivity.BUNDLE;
import static com.go.mushaf.mushafapplication.DownloadActivity.CONTEXT;
import static com.go.mushaf.mushafapplication.DownloadActivity.TEXT_ID;
import static com.go.mushaf.mushafapplication.DownloadActivity.getLoadingText;
import static com.go.mushaf.mushafapplication.DownloadActivity.mTxtProgress;
import static com.go.mushaf.mushafapplication.DownloadActivity.showEndLoadingNotification;
import static com.go.mushaf.mushafapplication.Utility.getPages;
public class DownloadService extends IntentService {
public int viewId;
Context context;
public static final String TAG = "servicee";
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent.hasExtra(BUNDLE)) {
viewId = intent.getBundleExtra(BUNDLE).getInt(TEXT_ID);
Log.d(TAG, "onHandleIntent: ");
}
new BackGroundTask().execute();
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
context = getApplicationContext();
return super.onStartCommand(intent, flags, startId);
}
public class BackGroundTask extends AsyncTask<Void, Integer, Void> {
private final String ASYNC_ERROR = this.getClass().getName();
private RequestBuilder<Drawable> x;
private ArrayList<String> pagesList = getPages();
@Override
protected Void doInBackground(Void... arg0) {
// FIXME: 6/27/2018
doAllCache(mTxtProgress);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// if(x!=null) {
// x.preload();
//// if (!cancelFlag || count < MainActivity.mushafTotal)
//// new BackGroundTask().execute(++count);
// }
showAlert("تم اكتمال التحميل بنجاح", "تم التحميل");
// getApplicationContext(), unable to add window
// DownladService.this, unable to add window
// getBaseContext(), unable to add window
}
private void doAllCache(final TextView mTxtProgress) {
Log.d(TAG, "doAllCache: " + mTxtProgress.getText().toString());
Log.d(TAG, "doAllCache: " + pagesList.size());
for (int i=0; i<pagesList.size(); i++) {
String pageNumber = pagesList.get(i); //get string for page number
Log.d(TAG, "doAllCache: " + pageNumber);
String url = MainActivity.mainUril + pageNumber + ".gif"; // get page url
final int finalI = i;
x = Glide.with(DownloadService.this)
.load(url)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// Log.i("Image Loading End", String.valueOf(i));
mTxtProgress.setText(getLoadingText(getApplicationContext(), finalI));
Log.d(TAG, "onResourceReady: " + resource +"\n"+model.toString()+"\n"+target+"\n"+dataSource);
//// //check cancel
//// if (cancelFlag) {
//// finish();
//// } else {
//
// if (finalI < MainActivity.mushafTotal) {
// final int ii = finalI + 1;
// new BackGroundTask().execute();
//
//// new Handler().postDelayed(new Runnable() {
//// @Override
//// public void run() {//Use your "bitmap" here
//// doAllCache(ii);
//// }
//// }, 100);
// }
//// else{
//// cancelFlag = true;
//// }
//// }
return true;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
Log.d(ASYNC_ERROR, String.valueOf(finalI));
Log.d(ASYNC_ERROR, "onLoadFailed: " + e);
return false;
}
});
}
}
}
public void showAlert(String message, String header) {
if (header.equals(""))
header = "Alert!";
try {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getApplicationContext());
// Log.d(TAG, "show: " + alertDialog.getOwnerActivity());
alertDialogBuilder.setTitle(header);
alertDialogBuilder.setMessage(message);
alertDialogBuilder.setPositiveButton("موافق",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Activity) context).finish();
dialog.dismiss();
showEndLoadingNotification(context);
}
});
// alertDialogBuilder.show();
alertDialogBuilder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
((Activity) context).finish();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} catch (Exception ignored) {
ignored.printStackTrace();
}//when app trying to display a dialog using a previously finished activity as a context
}
}
这就是我启动服务的方式:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.download_btn:
startLoadingNotification();
Bundle bundle = new Bundle();
bundle.putInt(TEXT_ID, R.id.txt_load);
// bundle.putSerializable(CONTEXT, (Serializable) DownloadActivity.this);
startService(new Intent(DownloadActivity.this, DownloadService.class).putExtra(BUNDLE, bundle));
mViewDownload.setVisibility(View.GONE);
mViewCancel.setVisibility(View.VISIBLE);
break;
case R.id.cancel_btn:
createLogoutDialog().show();
break;
}
}
我想在 onPostExecute 方法中显示对话框。 我试过:
getApplicationContext(), DownloadService.this, this, getBaseContext()
以上都是同样的错误。
提前致谢。
您不能从 Service
显示 AlertDialog
。您只能显示 Activity
中的 AlertDialog
。在这种情况下,显示来自 activity 的正在启动此服务的对话框。或者,不使用对话框,而是使用 Notification
.
除此之外:
不要在
IntentService
内执行异步操作,因为服务会在onHandleIntent()
returns 后立即消失。一旦服务消失,您的进程可能会终止,在工作完成之前杀死您的后台线程。删除BackGroundTask
并将其所有要执行的逻辑移至onHandleIntent()
。另外,摆脱 Glide 或弄清楚如何让它同步下载图像(据我所知,它做不到)。IntentService
将无法在 Android 8.0+ 上正常运行,除非您将其设为前台服务并使用startForegroundService()
。考虑使用JobIntentService
或在 2019 年及以后使用WorkManager
.