升级到WorkManager 2.7.0:如何为RxWorker实现getForegroundInfoAsync?

aku*_*ubi 6 android android-workmanager

我的应用程序面向 API 31/Android 12,根据Google 的说法,需要 WorkManager 2.7.0 版本,因此为了做到这一点,我已添加setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)到我的OneTimeWorkRequestBuilderAndroidManifest 中并添加了必要的更改(请参阅此链接了解详情)。然而,当我运行我的应用程序时,我遇到了这个错误:

java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Expedited WorkRequests require a ListenableWorker to provide an implementation for `getForegroundInfoAsync()`
Run Code Online (Sandbox Code Playgroud)

Google 没有提供关于如何为 RxWorker 执行此操作的示例或文档,但我在 Stackoverflow 中找到了这个答案,但它是针对协程的。

getForegroundInfoAsync我的问题是你如何实现何时必须返回的RxWorker说法——阅读文档似乎我必须将 Guava 添加到我的应用程序中才能做到这一点?由于文档说getForegroundInfoAsyncListenableFuture<ForegroundInfo>ListenableFutureAvoid implementing ListenableFuture from scratch. If you can't get by with the standard implementations, prefer to derive a new Future instance with the methods in Futures or, if necessary, to extend AbstractFuture.

mik*_*guy 7

另一种不需要受限 API 或导入 futures 库的方法是使用以下Futures.immediateFuture()方法:

override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
    val notificationId = // some int id for your notification
    val notification = // build your notification in the normal way
    return Futures.immediateFuture(ForegroundInfo(notificationId, notification))
}
Run Code Online (Sandbox Code Playgroud)


aku*_*ubi 5

编辑:目前,有两种方法可以解决此问题:

1. 使用受限API

查看 的源代码ListenableWorker,我们发现getForegroundInfoAsync

    @NonNull
    public ListenableFuture<ForegroundInfo> getForegroundInfoAsync() {
        SettableFuture<ForegroundInfo> future = SettableFuture.create();
        String message =
                "Expedited WorkRequests require a ListenableWorker to provide an implementation for"
                        + " `getForegroundInfoAsync()`";
        future.setException(new IllegalStateException(message));
        return future;
    }
Run Code Online (Sandbox Code Playgroud)

因此,在我自己的 RxWorker 的 getForegroundInfoAsync 实现中,我尝试创建一个 ,SettableFuture但我看到了一个 lint 警告,告诉我 的使用SettableFuture在其库内受到限制。但这可以通过仅用注释实现getForegroundInfoAsync来绕过@SuppressLint("RestrictedApi")。我的代码大致如下:

    @SuppressLint("RestrictedApi")
    override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
        val future = SettableFuture.create<ForegroundInfo>()

        val notificationId = id.hashCode()
        val fileName = inputData.getString(KEY_OUTPUT_FILE_NAME)

        if (fileName == null) {
            future.setException(IllegalStateException("Filename is null"))
            return future
        }

        val notificationBuilder = getNotificationBuilder(fileName)

        future.set(ForegroundInfo(notificationId, notificationBuilder.build()))
        return future
    }
Run Code Online (Sandbox Code Playgroud)

2.使用CallbackToFutureAdapter

您可以使用 ,而不是依赖受限制的 API CallbackToFutureAdapter,但此解决方案需要 Futures AndroidX 库,请参阅此处的链接。将上述库添加到您的项目后,您可以使用CallbackToFutureAdapter以下方式返回 ListenableFuture:

override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
    val fileName = inputData.getString(KEY_OUTPUT_FILE_NAME)

    return CallbackToFutureAdapter.getFuture {
        if (fileName == null) {
            it.setException(IllegalStateException("Filename is null"))
        } else {
            notificationBuilder = getNotificationBuilder(fileName)

            it.set(ForegroundInfo(notificationId, notificationBuilder.build()))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

不过,有一个警告,在为您的通知创建通知时PendingIntent,不要忘记PendingIntent.FLAG_MUTABLE设置标志(有关详细信息,请参阅此答案