WorkManager 2.7.0加急任务在Android 11报错:需实现ListenableWorker的getForegroundInfoAsync()方法
解决WorkManager 2.7.0加急任务在Android 11上的崩溃问题
嘿,这个问题我之前在项目里踩过坑!原因很明确:Android 12(API 31)以下的系统对加急WorkRequest有额外要求——你必须在你的Worker类里实现前台服务信息的获取方法,否则就会抛出你看到的IllegalStateException。
为什么会出现这个差异?
在Android 12及以上,系统会自动为加急WorkRequest创建前台通知,不需要开发者手动处理;但在Android 11及以下,WorkManager要求开发者提供ForegroundInfo(包含通知ID和具体的通知实例),因为加急任务会以前台服务的形式运行,而前台服务必须显示通知。
具体解决方案
你需要修改你的MyWorker类,实现对应的前台信息获取方法:
1. 如果你使用Kotlin的CoroutineWorker(推荐)
直接重写suspend fun getForegroundInfo(): ForegroundInfo方法,返回一个合法的ForegroundInfo对象:
import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.os.Build import androidx.core.app.NotificationCompat import androidx.work.CoroutineWorker import androidx.work.ForegroundInfo import androidx.work.WorkerParameters import android.content.Context class MyWorker( context: Context, params: WorkerParameters ) : CoroutineWorker(context, params) { private val NOTIFICATION_CHANNEL_ID = "expedited_work_channel" private val NOTIFICATION_ID = 1001 override suspend fun doWork(): Result { // 这里执行你的加急任务逻辑 return Result.success() } override suspend fun getForegroundInfo(): ForegroundInfo { // 创建通知渠道(Android 8及以上必须) createNotificationChannel() // 构建通知 val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID) .setContentTitle("加急任务处理中") .setContentText("正在执行你的紧急请求") .setSmallIcon(R.drawable.ic_notification) // 替换成你的通知图标 .setPriority(NotificationCompat.PRIORITY_LOW) .build() return ForegroundInfo(NOTIFICATION_ID, notification) } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( NOTIFICATION_CHANNEL_ID, "加急任务通知", NotificationManager.IMPORTANCE_LOW ) val notificationManager = applicationContext.getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } } }
2. 如果你使用Java的ListenableWorker
需要重写getForegroundInfoAsync()方法,返回ListenableFuture<ForegroundInfo>:
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.os.Build; import androidx.core.app.NotificationCompat; import androidx.work.ForegroundInfo; import androidx.work.ListenableWorker; import androidx.work.WorkerParameters; import com.google.common.util.concurrent.SettableFuture; import android.content.Context; public class MyWorker extends ListenableWorker { private static final String NOTIFICATION_CHANNEL_ID = "expedited_work_channel"; private static final int NOTIFICATION_ID = 1001; public MyWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @NonNull @Override public ListenableFuture<Result> startWork() { SettableFuture<Result> future = SettableFuture.create(); // 执行你的任务逻辑 future.set(Result.success()); return future; } @NonNull @Override public ListenableFuture<ForegroundInfo> getForegroundInfoAsync() { SettableFuture<ForegroundInfo> future = SettableFuture.create(); createNotificationChannel(); Notification notification = new NotificationCompat.Builder(getApplicationContext(), NOTIFICATION_CHANNEL_ID) .setContentTitle("加急任务处理中") .setContentText("正在执行你的紧急请求") .setSmallIcon(R.drawable.ic_notification) .setPriority(NotificationCompat.PRIORITY_LOW) .build(); future.set(new ForegroundInfo(NOTIFICATION_ID, notification)); return future; } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( NOTIFICATION_CHANNEL_ID, "加急任务通知", NotificationManager.IMPORTANCE_LOW ); NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } }
额外注意事项
- 你原来代码中的
setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)可以保留,当系统加急任务配额不足时,任务会自动降级为普通任务,避免失败。 - 确保通知图标是合法的,避免因图标问题导致通知无法显示,进而影响任务执行。
内容的提问来源于stack exchange,提问作者Roy Solberg




