升级到 WorkManager 2.7.0:如何为 RxWorker 实现 getForegroundInfoAsync?
Upgrading to WorkManager 2.7.0: How to implement getForegroundInfoAsync for RxWorker?
我的应用程序的目标是 API 31/Android 12,根据 Google, so in order to do that, I have added setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
to my OneTimeWorkRequestBuilder
and added the necessary changes in the AndroidManifest as well (see this link 了解详情,需要 WorkManager 2.7.0 版)。但是,当我 运行 我的应用程序遇到此错误时:
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()`
Google 没有提供关于如何为 RxWorker 执行此操作的示例或文档,但我在 Whosebug 中找到了这个 ,但它适用于协程。
我的问题是,当 getForegroundInfoAsync
必须 return ListenableFuture<ForegroundInfo>
时,您如何为 RxWorker
实现上述 getForegroundInfoAsync
——阅读文档似乎我必须将 Guava 添加到我的应用程序才能执行此操作吗?由于 ListenableFuture
的文档对 Avoid 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.
说
编辑:目前,有两种方法可以解决这个问题:
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;
}
所以在我自己的 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
}
2。使用 CallbackToFutureAdapter
您可以使用 CallbackToFutureAdapter
而不是依赖受限制的 API,但此解决方案需要 Futures AndroidX 库,请参阅 link here。将上述库添加到您的项目后,您可以使用 CallbackToFutureAdapter
到 return 一个 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()))
}
}
}
但有一个警告,在为您的通知创建 PendingIntent
时,不要忘记设置 PendingIntent.FLAG_MUTABLE
标志(有关详细信息,请参阅此 )
另一种不需要限制 API 或导入期货库的方法是使用 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))
}
我的应用程序的目标是 API 31/Android 12,根据 Google, so in order to do that, I have added setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
to my OneTimeWorkRequestBuilder
and added the necessary changes in the AndroidManifest as well (see this link 了解详情,需要 WorkManager 2.7.0 版)。但是,当我 运行 我的应用程序遇到此错误时:
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()`
Google 没有提供关于如何为 RxWorker 执行此操作的示例或文档,但我在 Whosebug 中找到了这个
我的问题是,当 getForegroundInfoAsync
必须 return ListenableFuture<ForegroundInfo>
时,您如何为 RxWorker
实现上述 getForegroundInfoAsync
——阅读文档似乎我必须将 Guava 添加到我的应用程序才能执行此操作吗?由于 ListenableFuture
的文档对 Avoid 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.
编辑:目前,有两种方法可以解决这个问题:
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;
}
所以在我自己的 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
}
2。使用 CallbackToFutureAdapter
您可以使用 CallbackToFutureAdapter
而不是依赖受限制的 API,但此解决方案需要 Futures AndroidX 库,请参阅 link here。将上述库添加到您的项目后,您可以使用 CallbackToFutureAdapter
到 return 一个 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()))
}
}
}
但有一个警告,在为您的通知创建 PendingIntent
时,不要忘记设置 PendingIntent.FLAG_MUTABLE
标志(有关详细信息,请参阅此
另一种不需要限制 API 或导入期货库的方法是使用 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))
}