Android后台/关闭状态下FCM通知无法显示可展开图片求助
解决FCM后台/关闭状态下可展开通知图片不显示的问题
首先,你的问题核心在于后台Service中异步加载Bitmap的可靠性不足,以及Glide在Service上下文下的配置问题。当应用处于后台或关闭状态时,MyFirebaseMessagingService的生命周期很短,你用的AsyncTask可能还没完成图片加载,Service就被系统回收了,导致onPostExecute根本没机会执行,自然无法显示带图片的通知。另外,Glide在Service中直接使用当前上下文也可能存在上下文回收的风险。
下面是具体的修复方案:
方案1:优化Glide加载逻辑,替换AsyncTask为回调方式
放弃AsyncTask,改用Glide的listener回调来获取Bitmap,同时使用Application Context确保上下文稳定:
public void backGroundNotification() { Intent intent = new Intent(this, MainActivity.class); intent.putExtra("title", title); intent.putExtra("text", body); intent.putExtra("imageUrl", imageUrl); intent.putExtra("type", type); intent.putExtra("id", id); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); pendingIntentPromo = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); // 用Application Context初始化Glide,避免Service上下文被回收 Glide.with(getApplicationContext()) .asBitmap() .load(imageUrl) .override(100, 100) .listener(new RequestListener<Bitmap>() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) { e.printStackTrace(); Log.e("noti exp", "图片加载失败: " + e.getMessage()); // 加载失败时显示普通通知兜底 showBasicNotification(); return false; } @Override public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) { // 图片加载完成后构建带大图的通知 showBigPictureNotification(resource); return false; } }) .submit(); } // 显示普通通知(图片加载失败时使用) private void showBasicNotification() { NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.app_icon) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setTicker("DealDio") .setSound(sound) .setVibrate(vibration) .setContentIntent(pendingIntentPromo); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build()); } // 显示带大图的通知 private void showBigPictureNotification(Bitmap bitmap) { NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle() .bigPicture(bitmap) .bigLargeIcon(null) .setSummaryText(body); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.app_icon) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setTicker("DealDio") .setSound(sound) .setVibrate(vibration) .setContentIntent(pendingIntentPromo) .setStyle(bigPictureStyle); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build()); }
方案2:使用WorkManager确保任务稳定执行
如果后台Service被系统回收的概率很高,推荐用WorkManager来处理图片加载和通知构建,它是Android官方推荐的后台任务组件,能在系统限制下保证任务完成:
1. 添加WorkManager依赖
在build.gradle中添加:
implementation "androidx.work:work-runtime:2.8.1"
2. 创建WorkManager任务类
public class NotificationWorker extends Worker { private static final String KEY_TITLE = "title"; private static final String KEY_BODY = "body"; private static final String KEY_IMAGE_URL = "imageUrl"; private static final String KEY_TYPE = "type"; private static final String KEY_ID = "id"; public NotificationWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @NonNull @Override public Result doWork() { // 获取传递的参数 String title = getInputData().getString(KEY_TITLE); String body = getInputData().getString(KEY_BODY); String imageUrl = getInputData().getString(KEY_IMAGE_URL); String type = getInputData().getString(KEY_TYPE); String id = getInputData().getString(KEY_ID); // 同步加载Bitmap(doWork本身在后台线程,可安全使用同步方法) Bitmap bitmap = null; try { bitmap = Glide.with(getApplicationContext()) .asBitmap() .load(imageUrl) .override(100, 100) .submit() .get(); } catch (Exception e) { e.printStackTrace(); Log.e("noti exp", "图片加载失败: " + e.getMessage()); } // 构建跳转Intent Intent intent = new Intent(getApplicationContext(), MainActivity.class); intent.putExtra("title", title); intent.putExtra("text", body); intent.putExtra("imageUrl", imageUrl); intent.putExtra("type", type); intent.putExtra("id", id); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT); // 构建通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()) .setSmallIcon(R.drawable.app_icon) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setTicker("DealDio") .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .setVibrate(new long[]{1000, 1000}) .setContentIntent(pendingIntent); // 如果图片加载成功,添加大图样式 if (bitmap != null) { NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle() .bigPicture(bitmap) .bigLargeIcon(null) .setSummaryText(body); builder.setStyle(style); } NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, builder.build()); return Result.success(); } // 对外提供启动任务的方法 public static void startNotificationWork(Context context, String title, String body, String imageUrl, String type, String id) { Data inputData = new Data.Builder() .putString(KEY_TITLE, title) .putString(KEY_BODY, body) .putString(KEY_IMAGE_URL, imageUrl) .putString(KEY_TYPE, type) .putString(KEY_ID, id) .build(); OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(NotificationWorker.class) .setInputData(inputData) .build(); WorkManager.getInstance(context).enqueue(workRequest); } }
3. 在MyFirebaseMessagingService中调用WorkManager
public void backGroundNotification() { // 直接启动WorkManager任务,无需自己处理线程和生命周期 NotificationWorker.startNotificationWork(this, title, body, imageUrl, type, id); }
关键原因解释
- AsyncTask的不可靠性:后台Service的生命周期不受开发者完全控制,AsyncTask依赖Service存活,一旦Service被系统回收,AsyncTask会被终止,
onPostExecute无法执行。 - Glide上下文问题:使用Service的
this作为Glide上下文,当Service销毁时,Glide的加载任务会被取消;改用Application Context能避免这个风险。 - WorkManager的优势:它会根据系统状态自动调度任务,即使应用被关闭,也能在合适的时机完成任务,是处理后台通知这类需求的最优解。
内容的提问来源于stack exchange,提问作者Rahul Sharma
相关产品推荐
相关产品推荐

