我正在尝试开发一个简单的 Android 应用程序(jetpack compose + kotlin)用于日常治疗监控。用户设置在一天中的某个时间要做的一些事情(吃药、测量血压......),这些事情保存在 Room 数据库中。我希望该应用程序每 30 分钟检查一次,是否有在接下来的 30 分钟内进行的治疗,并在这种情况下显示通知。我认为 WorkManager 是执行此操作的最佳方法,因为我希望该应用程序即使不活动也可以发送通知。这是我关于workmanager的代码:
//MainActivity
private lateinit var workManager: WorkManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
workManager = WorkManager.getInstance(applicationContext)
val workRequest = PeriodicWorkRequestBuilder<IncomingTherapyWorker>(30,TimeUnit.MINUTES)
.setInitialDelay(1, TimeUnit.MINUTES)
.build()
workManager.enqueueUniquePeriodicWork(IncomingTherapyWorker.WORKER_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, workRequest)
//Notifictaion channel creation
val therapyNotificationService = TherapyNotificationService(this)
therapyNotificationService.createNotificationChannel()
//
setContent {...
@HiltWorker
class IncomingTherapyWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted parameters: WorkerParameters,
private val repository: TherapyRepository
) : CoroutineWorker(context, parameters) {
val terapyNotificationService = TherapyNotificationService(context = context)
override suspend fun doWork(): Result {
return try {
//let's log on a file
val dataNow = LocalDateTime.now()
val folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
val file = File(folder,"RegistroWorker.txt")
val outputStream = withContext(Dispatchers.IO) {
FileOutputStream(file, true)
}
withContext(Dispatchers.IO) {
outputStream.write(
String.format(
"%4d_%02d_%02d_%02d_%02d_%02d \n",
dataNow.year,
dataNow.monthValue,
dataNow.dayOfMonth,
dataNow.hour,
dataNow.minute,
dataNow.second
).toByteArray()
)
outputStream.close()
}
//
var messaggio: String = ""
val listaTerapie = repository.getTherapylist()
val iterator = listaTerapie.listIterator()
iterator.forEach { terapia ->
val incomingOutput = isTherapyIncoming(terapia)
if(incomingOutput.esito) {
messaggio = messaggio + terapia.etichetta + " " + incomingOutput.messaggio + "\r\n"
}
}
if(!messaggio.isEmpty())
terapyNotificationService.sendTherapyNotification(messaggio)
return Result.success()
} catch (throwable: Throwable) {
throwable.message?.let { Log.d(WORKER_TAG, it) }
throwable.cause?.let { Log.d(WORKER_TAG, it.cause.toString()) }
Result.failure()
}
}
companion object {
const val WORKER_TAG = "TherapySeeker"
}
}
这项工作有效,但只能持续一段时间。特别是当设备关闭或应用程序最小化时,Worker 会停止工作。
我理解,或者我认为我理解,这涉及打瞌睡模式和省电模式。
我的代码有什么问题吗?
是否有可能在所有条件下都有坚持不懈的工人?
PeriodicWorkRequest
的文档:
定期工作适用于您希望连续运行之间具有相当一致的延迟,并且您愿意接受由于电池优化和打瞌睡模式而导致的不精确性的用例。
如果您需要安排在特定时间或仅在特定时间窗口内发生的工作,您应该考虑使用
s。OneTimeWorkRequest
我对这个主题不太熟悉,但在我看来,您的用例的一般路线图可能是:
OneTimeWorkRequest
,因为它们不受打瞌睡模式或电池优化的限制。OneTimeWorkRequest
之内,
setExact
安排闹钟,以确保闹钟准确地在指定时间发出,与打瞌睡模式或电池优化无关。OneTimeWorkRequest
。如果仅通过应用程序将疗法单独添加到房间数据库中,那么只要将新条目添加到数据库中,实际上只需调用
AlarmManager.setExact()
就足够了。