You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动