[更新] 这已在alpha09中解决
我有两件作品被WorkManager alpha04 beginWith和thenapi 链接起来.
fun updateData() {
createWorkRequests()
runDataDownloadWork()
}
private fun createWorkRequests() {
dwElementsWork = OneTimeWorkRequestBuilder<DWElementsWork>()
.addTag(TAG_ELEMENTS_WORK)
.build()
dwElementTypesWork = OneTimeWorkRequestBuilder<DWElementTypesWork>()
.addTag(TAG_ELEMENTS_TYPE_WORK)
.build()
}
private fun runDataDownloadWorkNoStatus() {
WorkManager.getInstance()!!
.beginWith(dwElementTypesWork)
.then(dwElementsWork)
.enqueue()
}
Run Code Online (Sandbox Code Playgroud)
它们会在我的MainActivity.kt文件中被调用dwElementTypesWork,而在某些情况下,第一个会被执行,而在少数情况下,它们都没有.我错过了一些配置吗?文档很简单.
这是基于WorkManager日志的logcat输出:
06-28 09:28:20.519 28480-28501/com.myapp.app D/SystemJobScheduler: Scheduling work ID 3e5f8531-aa92-4e28-8533-d180612dab02 Job ID 28
06-28 09:28:20.537 28480-28501/com.myapp.app D/GreedyScheduler: Starting tracking for 3e5f8531-aa92-4e28-8533-d180612dab02
06-28 09:28:20.542 28480-28501/com.myapp.app D/ConstraintTracker: NetworkStateTracker: initial state = [ Connected=true Validated=true Metered=false NotRoaming=true …Run Code Online (Sandbox Code Playgroud) I'm trying to load some URL in the background, but in the same way WebView loads it in an Activity.
There are multiple reasons developers would want it (and requested about it here) , such as running JavaScript without Activity, caching, monitor websites changes, scrapping ...
It seems that on some devices and Android versions (Pixel 2 with Android P, for example), this works fine on Worker , but on some others (probably on older versions …
我有一个服务侦听传入的FCM通知.收到此类通知后,我使用WorkManager运行作业.
当同时收到多个通知时,如何确保当时只执行一个作业?作业应按顺序执行.在这种情况下,我想发送短信,这些不能同时发送.(请注意,在发送短信之前和之后,我会在此作业中执行其他类似的http请求,这就是为什么我决定为它创建一个作业,而不是直接从服务发送短信.)
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
//...
OneTimeWorkRequest sendSmsWorker = new OneTimeWorkRequest.Builder(SendSmsWorker.class).build();
WorkManager.getInstance().enqueue(sendSmsWorker);
//...
}
}
Run Code Online (Sandbox Code Playgroud)
我已经检查了WorkManager文档中的高级部分; 它提到了链式序列,但是这些必须明确地链接到彼此(beginWith/then/then/...).
如何对WorkManager Worker进行单元测试?
这是示例工作者:
public class SampleWorker extends Worker {
private static final String TAG = "SampleWorker";
private static final String WORKER_TAG = "SAMPLE";
static final String KEY_DATA_1 = "KEY_DATA_1";
static final String KEY_DATA_2 = "KEY_DATA_2";
public SampleWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
public static WorkRequest createWorkRequest(String data1, String data2) {
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
Data inputData = createData(data1, data2);
return new OneTimeWorkRequest.Builder(SampleWorker.class)
.setConstraints(constraints)
.setInputData(inputData)
.addTag(WORKER_TAG)
.build();
}
static Data createData(String data1, String data2) …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用WorkManager进行服务器调用。所以,我写了下面的Worker类:
class ServerCallWorker extends Worker {
public ServerCallWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
Log.d("Testing", "ServerCallWorker constructor method" );
}
@NonNull
@Override
public Worker.Result doWork() {
Log.d("Testing", "doWork() method" );
return Worker.Result.SUCCESS;
}
}Run Code Online (Sandbox Code Playgroud)
我正在从活动的onCreate()方法调用此工作者类。代码段在这里:
private void getLocationUpdate() {
Log.d("Testing", "inside Location Update");
WorkManager workManager = WorkManager.getInstance();
Log.d("Testing", "inside Location Update 222");
Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType
.CONNECTED).build();
// PeriodicWorkRequest recurringWork = new PeriodicWorkRequest.Builder(FilterWorker.class, 15,
// TimeUnit.MINUTES).build();
OneTimeWorkRequest wrkReq = new OneTimeWorkRequest.Builder(ServerCallWorker.class).setConstraints(constraints)
.build();
Log.d("Testing", "inside Location Update 333"); …Run Code Online (Sandbox Code Playgroud)我在互联网上搜索了有关此主题的信息,但似乎没有人再遇到此问题。
还记得这个有趣的错误吗?
java.lang.IllegalStateException:超出 JobScheduler 100 作业限制。我们在 JobScheduler 中统计了 101 个 WorkManager 作业;我们的数据库中有 50 个跟踪的作业;我们的配置限制是 50。
和
原因:java.lang.IllegalStateException:应用程序可能无法安排超过 100 个不同的作业
好吧,尽管换了很多工作要做enqueueUniqueWork,但我的一些用户似乎仍然达到了这个限制。我的用例是供那些贫穷且没有网络连接的人离线做很多事情,从而创造大量工作来更新远程服务器上的资源。我在使用 FirebaseJobDispatcher 时从未遇到过这个问题(至少我没有意识到),有些人可能几天都没有信号,如果有人几周无法连接会发生什么?它将轻松创造数百个就业岗位。因此,出现了这个错误。
我的问题是,当达到限制时,这些工作会发生什么?它们只是被调度程序丢弃了吗?当我输入此内容时,我现在会丢失人们的数据吗?
更新
Android 版本:已确认 7.0、8.0、8.1,可能还有更多
工作管理器版本:2.3.0
协程工作线程发生以下崩溃,该崩溃仅发生在某些 Samsung、Vivo 和 Oppo 设备上,特别是 Android 10 上
Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{2dcabaa u0 `app_id_hidden`/androidx.work.impl.foreground.SystemForegroundService}
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2159)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:230)
at android.app.ActivityThread.main(ActivityThread.java:7752)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
Run Code Online (Sandbox Code Playgroud)
doWork工作人员的功能被实现为,该功能init()完成我的工作。
override suspend fun doWork(): Result {
setForeground(createForegroundInfo())
return init()
}
private fun init() {
//implementation hidden
}
private fun createForegroundInfo(): ForegroundInfo {
val notificationId = 1
return ForegroundInfo(notificationId, createNotification())
}
private fun createNotification(): Notification {
val context = applicationContext
val builder = …Run Code Online (Sandbox Code Playgroud) 仅当设备未使用时我才需要运行特定的工作。但是,我不完全理解该.setRequiresDeviceIdle()约束是如何工作的。
我正在这样安排一个工人:
\nval constraints = Constraints.Builder()\n .setRequiredNetworkType(NetworkType.CONNECTED)\n .setRequiresBatteryNotLow(true)\n .setRequiresStorageNotLow(true)\n .setRequiresDeviceIdle(true)\n .build()\n\nval networkWorkRequest = PeriodicWorkRequestBuilder<NetworkWorker>(15, TimeUnit.MINUTES)\n .addTag(NetworkWorker.TAG)\n .setInitialDelay(15, TimeUnit.SECONDS)\n .setConstraints(constraints)\n .build()\n\nWorkManager.getInstance(context)\n .enqueueUniquePeriodicWork(NetworkWorker.TAG, ExistingPeriodicWorkPolicy.REPLACE, networkWorkRequest)\nRun Code Online (Sandbox Code Playgroud)\n请注意,设备已充满电、有足够的存储空间并且始终有可用的互联网连接(意味着满足前 3 个限制)。
\n我尝试过几个小时不触摸设备,关闭所有应用程序,甚至通过 ADB(使用adb shell dumpsys deviceidle force-idle然后adb shell dumpsys deviceidle step)触发打瞌睡模式(然后是维护窗口),但似乎没有任何效果(根据文档,这个“空闲”不是与打瞌睡模式相同,但我决定尝试一下)。
正如你所看到的,我已经将这项工作安排为定期的,只是为了检查它是否会产生任何影响(事实上,我只需要一名一次性工人)。我离开设备过夜,最终工作人员运行了(这些是我正在写入 SD 卡中的文件的一些日志):
\n1620688536155,2021.05.11 00:15:36.155,DEBUG,PRETTY_LOGGER,Enqueueing worker with id 931d2b1f-85f4-445f-a889-832fdd945752\n1620712213970,2021.05.11 06:50:13.970,DEBUG,PRETTY_LOGGER,Running background work\xe2\x80\xa6 --- job started running\n1620712224898,2021.05.11 06:50:24.898,DEBUG,PRETTY_LOGGER,Response is: IT WORKS\n1620712224899,2021.05.11 06:50:24.899,DEBUG,PRETTY_LOGGER,Done! --- job finished\nRun Code Online (Sandbox Code Playgroud)\n如果我的作业至少在晚上运行一次,我就很好,因为它是为了触发更新过程,所以我确实需要设备在更新过程中处于空闲状态。无论如何,我想了解如何确保它能够运行,以及如何模仿它进行测试(例如,我们可以使用打瞌睡模式)。
\n我在我的应用程序类中启动了一个工作人员,如下所示;
@HiltAndroidApp
class KutuphanemApplication:Application(),Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.DEBUG)
.setWorkerFactory(workerFactory)
.build()
Run Code Online (Sandbox Code Playgroud)
我想将单例 dao 注入到我的工作类中以更新数据库中的某些内容。所以我像下面一样注入 dao;
@HiltWorker
class ClearImageNotInArchiveWorker @AssistedInject constructor(
@Assisted val appContext: Context,
@Assisted val workerParams: WorkerParameters,
private val kitapDao: KitapDao): CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {...}
}
Run Code Online (Sandbox Code Playgroud)
当我在 App 类中加入这个 WorkManager 类时,我得到
WorkerFactory:无法实例化 com.mesutemre.kutuphanem.job.ClearImageNotInArchiveWorker 错误。但应用程序并没有崩溃。这里注入dao有没有问题?
还有我的单例刀;
@Singleton
@Provides
fun provideKitapDao(database: KutuphanemDatabase) = database.getKitapDao();
Run Code Online (Sandbox Code Playgroud) android dependency-injection android-workmanager dagger-hilt
我只想保持蓝牙开启,为此我监听蓝牙状态,如果它被关闭,广播接收器可以启用它。我也希望它在应用程序关闭时运行。因此,即使在应用程序关闭后(当它不工作时),我也试图运行蓝牙广播接收r。为此,我了解到我需要使用工作管理器来支持所有设备。我试图结合 Broadcast Receiver 和 Work Manager。但是当应用程序关闭时我无法让它运行。
这是我的MainActivity.java在这里,我将工作请求排入队列。
package com.example.workmanagersample;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MyWorker.class).build();
WorkManager.getInstance().enqueue(workRequest);
}
}
Run Code Online (Sandbox Code Playgroud)
下面的类是我的MyWorker.java 在这里我注册了接收器。
package com.example.workmanagersample;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.IntentFilter;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
public class MyWorker extends Worker {
private …Run Code Online (Sandbox Code Playgroud) android background-service broadcastreceiver android-bluetooth android-workmanager