首页 > 解决方案 > WorkManager - 定期运行作业的问题

问题描述

过去我使用AlarmManagerand aForegroundService来定期运行作业。在我最近的应用程序中,我尝试改用 JetPack WorkManager,但我无法让它可靠地工作。

我需要每天在预定义的时间运行一项工作(大约,电池优化很好),但在我的情况下,似乎一段时间后我的工作停止工作并且不再自动执行。

问题

如果我使用AlarmManagerand aForegroundService我没有问题,我的工作会定期且可靠地执行。但是,如果我在WorkManager下面尝试使用,该作业会执行几次,然后它会跳过或停止(例如,它不会在大多数时候在上午 8 点运行,而是在晚上 8 点运行;几天后它会完全停止)。

任何想法是什么问题?我正在我的 android 9 设备上对此进行测试...

附加信息

代码

  1. 使作业入队的功能:

// 1) enqueue the periodic job
fun enqueuePeriodic(
  context: Context,
  keepNotification: Boolean
) {
  val firstDelay = Util.getPeriodicImportFirstDelay()
  val repeatInterval = Util.getPeriodicRepeatInterval()

  val workManager = WorkManager.getInstance(context)
  val data = workDataOf(
    "keepNotification" to keepNotification
  )
  val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .build()
  val workRequest = PeriodicWorkRequest.Builder(
    PaypalImportWorker::class.java,
    repeatInterval.first,
    repeatInterval.second
  )
    .setInitialDelay(firstDelay.first, firstDelay.second)
    .setInputData(data)
    .setConstraints(constraints)
    .build()

  workManager.enqueueUniquePeriodicWork(
    "ImportWorker-PERIODIC",
    ExistingPeriodicWorkPolicy.REPLACE,
    workRequest
  )
  L.tag(TAG).d { "periodic work enqueued" }
}
  1. CoroutineWorker 类:
class PaypalImportWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) {

  private val notificationManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

  override suspend fun doWork(): Result {
    L.tag(TAG).d { "Job started..." }

    val keepNotification = inputData.getBoolean( "keepNotification", false)

    // 1) create notification
    val notification =
      AppNotificationManager.createImportNotification(applicationContext, "Import started...")

    // 2) make this a foreground job
    val foregroundInfo = ForegroundInfo(AppNotificationManager.NOT_ID_IMPORTER, notification)
    setForeground(foregroundInfo)

    // 3) do work
    val res = ...

    // 4) notification
    if (keepNotification) {
      val not = ...
      notificationManager.notify(AppNotificationManager.NOT_ID_IMPORTER_FINISHED, not)
    }

    L.tag(TAG).d { "Job finished (keepNotification: $keepNotification)" }

    // 5) return result
    return Result.success(
      workDataOf(
        "result" to res
      )
    )
  }

  private fun updateNotification(info: String) {
    val notification = AppNotificationManager.createImportNotification(applicationContext, info)
    notificationManager.notify(AppNotificationManager.NOT_ID_IMPORTER, notification)
  }
}

  1. 定义和辅助函数

// DEFINITIONS - run checks, beginning at 20 o'clock every 12 hours
const val PERIODIC_CHECK_HOUR = 20
const val PERIODIC_CHECK_INTERVAL_HOUR = 12L

// HELPER functions
fun getPeriodicImportFirstDelay(): Pair<Long, TimeUnit> {
  val currentDate = Calendar.getInstance()
  val dueDate = Calendar.getInstance().apply {
    set(Calendar.HOUR_OF_DAY, Setup.PERIODIC_CHECK_HOUR)
    set(Calendar.MINUTE, 0)
    set(Calendar.SECOND, 0)
    set(Calendar.MILLISECOND, 0)
    if (before(currentDate)) {
      add(Calendar.HOUR_OF_DAY, 24)
    }
  }
  val timeDiffInMillis = dueDate.timeInMillis - currentDate.timeInMillis
  return Pair(timeDiffInMillis, TimeUnit.MILLISECONDS)
}

fun getPeriodicRepeatInterval(): Pair<Long, TimeUnit> = Pair(Setup.PERIODIC_CHECK_INTERVAL_HOUR, TimeUnit.HOURS)

标签: androidandroid-workmanager

解决方案


推荐阅读