gpt4 book ai didi

当应用程序被杀死时,Android AlarmManager 不会触发

转载 作者:行者123 更新时间:2023-12-04 09:13:59 26 4
gpt4 key购买 nike

我要求每 5 分钟执行一次任务。我已经考虑了多个选项,并尝试使用 AlarmManager 来实现它。类来触发任务。但是,当应用程序被杀死时,我无法触发警报。
当应用程序打开或在后台运行时,警报似乎可以正常工作,但一旦我退出应用程序,它似乎就完全停止了。
我的实现是使用 setExactAndAllowWhileIdle()功能并自己处理重复。初始警报在 5 秒后触发,之后每 5 分钟触发一次。
我已经以 5 分钟和 10 分钟的增量对其进行了测试,但是当应用程序关闭时,它再次运行。
请看一下我的实现:
我的 Activity .kt:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_landing)
initAlarm()
}

private fun initAlarm() {
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager

val intent = Intent(this, AlarmReceiver::class.java).apply { action = "MY_ALARM" }
val sender = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

val ALARM_DELAY_IN_SECOND = 5
val alarmTimeAtUTC = System.currentTimeMillis() + ALARM_DELAY_IN_SECOND * 1_000

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.(TAG, "initAlarm() 23+ - $alarmTimeAtUTC")
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, sender)
} else {
alarm.setExact(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, sender)
}
}
警报接收器.kt:
class AlarmReceiver : BroadcastReceiver() {

companion object {
private val TAG = AlarmReceiver::class.java.simpleName
}

override fun onReceive(context: Context?, intent: Intent?) {
Log.d(TAG, "onReceive()")
if (intent?.action == "MY_ALARM") {
Log.d(TAG, "onReceive() - starting service")
context?.startService(Intent(context, MyService::class.java))
initAlarm(context)
}
}

private fun initAlarm(context: Context?) {
val alarm = context?.applicationContext?.getSystemService(Context.ALARM_SERVICE) as AlarmManager

val intent = Intent(context, AlarmReceiver::class.java).apply { action = "MY_ALARM" }
val sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

val ALARM_DELAY_IN_SECOND = 600
val alarmTimeAtUTC = System.currentTimeMillis() + ALARM_DELAY_IN_SECOND * 1_000

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.d(TAG, "initAlarm() 23+ - $alarmTimeAtUTC")
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, sender)
} else {
alarm.setExact(AlarmManager.RTC_WAKEUP, alarmTimeAtUTC, sender)
}
}
}
我的服务.kt:
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate()")
doMyTask()
}

private fun doMyTask() {
job = CoroutineScope(Dispatchers.IO).launch {
// Perform task here and once complete stop service
stopSelf()
}
}
}

override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy()")
job?.cancel()
job = null
}

最佳答案

问题是代码正在调用 startService()当应用程序在后台时。
这在 Android 8 之前是允许的,但现在受到以下限制:

While an app is in the foreground, it can create and run bothforeground and background services freely. When an app goes into thebackground, it has a window of several minutes in which it is stillallowed to create and use services. At the end of that window, the appis considered to be idle. At this time, the system stops the app'sbackground services, just as if the app had called the services'Service.stopSelf() methods.


Background Execution Restrictions
上面示例中创建的服务是 Android 文档语言中的“后台服务”,因为它不调用 startForeground。发布 Notification让用户知道它正在运行。
要在应用程序处于后台时从警报启动“前台服务”, ContextCompat.startForegroundSerivce必须使用。它将调用 startForegroundService在 Android 8 及更高版本和 startService 上在旧设备上。
在服务中,您需要调用 startForeground发布正在进行的服务 Notification让用户知道服务正在运行。如果没有发布通知,则服务将在 5 秒后被终止。
是否可以通过 WorkManager 完成任务也值得考虑。或与 Firebase Cloud Messaging .
最后,您可能需要通知您的客户,在现代 Android 设备上“恰好每 5 分钟”运行一次任务是不可能的。我没看过 Doze最近实现,但过去在使用 setExactAndAllowWhileIdle 时观察到在维护窗口期间的常规延迟最多 10 分钟.但在某些情况下,延迟可能会更长。
关于未在 BroadcastReceiver 中调用 onReceive:
Disable Battery Optimisations
Do not kill my app
最后,您可以尝试在 getBroadcast 中传入唯一的 requestCode。而不是每次都传递 0。

关于当应用程序被杀死时,Android AlarmManager 不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63304673/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com