![](/img/trans.png)
[英]How to cancel alarm manager alarms when user removes the app from recent apps list?
[英]How To schedule and a send Notification even after user removes app from recent apps?
我的应用很简单
从用户那里花时间(我知道怎么做)
安排通知(我知道如何发送通知)
现在我只想知道即使用户从最近的应用程序中删除它,我如何发送此通知。
尝试过的解决方案——AlarmManager、BroudcastReceiver、Service、Intent Service、
但只有当应用程序存在于 RAM 中时,所有这些都有效(最近的移动应用程序列表)。
我该怎么做就告诉我主题。 我不需要代码。 我会研究那个。
正如您提到的 AlarmManager 和其他人对您不起作用,我测试了您尝试使用 JobScheduler 实现的目标。
它对我有用,即使从最近的应用程序列表中删除该应用程序后它也有效。 我在 Android 10 模拟器上试过。
您已要求提供要研究的主题/参考作为答案。 所以首先我会提到我使用的参考资料。
这是 JobScheduler 的代码实验室,它真的很有帮助: https://codelabs.developers.google.com/codelabs/android-training-job-scheduler/
这是有关创建多个计划作业的一个很好的参考: https://android-developers.googleblog.com/2017/10/working-with-multiple-jobservices.html
这是我尝试过的。
NotificationJobService.kt
private const val NOTIF_CHANNEL_ID = "primary_notification_channel"
private const val NOTIF_CHANNEL_NAME = "Job Service notification"
class NotificationJobService : JobService() {
override fun onStartJob(params: JobParameters?): Boolean {
// Get Notification Manager
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Create Notification Channel if device OS >= Android O
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel(NOTIF_CHANNEL_ID, NOTIF_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT).let {
notificationManager.createNotificationChannel(it)
}
}
// Create PendingIntent with empty Intent
// So this pending intent does nothing
val pendingIntent = PendingIntent.getActivity(this, 0, Intent(), PendingIntent.FLAG_ONE_SHOT)
// Configure NotificationBuilder
val builder = NotificationCompat.Builder(this, NOTIF_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Title")
.setContentText("Message")
.setAutoCancel(true)
.setContentIntent(pendingIntent)
// Make the Notification
notificationManager.notify(0, builder.build())
// False to let system know that the job is completed by the end of onStartJob(),
// and the system calls jobFinished() to end the job.
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
// True because if the job fails, you want the job to be rescheduled instead of dropped.
return true
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Job ID must be unique if you have multiple jobs scheduled
var jobID = 0
// Get fake user set time (a future time 1 min from current time)
val ( userSetHourOfDay, userSetMinute ) = getMockUserSetTime()
val timeToWaitBeforeExecuteJob = calculateTimeDifferenceMs(userSetHourOfDay, userSetMinute)
(getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler).run {
schedule(
JobInfo.Builder(
jobID,
ComponentName(baseContext, NotificationJobService::class.java)
)
// job execution will be delayed by this amount of time
.setMinimumLatency(timeToWaitBeforeExecuteJob)
// job will be run by this deadline
.setOverrideDeadline(timeToWaitBeforeExecuteJob)
.build()
)
}
}
// Returns a pair ( hourOfDay, minute ) that represents a future time,
// 1 minute after the current time
private fun getMockUserSetTime() : Pair<Int, Int> {
val calendar = Calendar.getInstance().apply {
// add just 1 min from current time
add(Calendar.MINUTE, 1)
}
return Pair(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE))
}
// Calculate time difference relative to current time in ms
private fun calculateTimeDifferenceMs(hourOfDay: Int, minute: Int) : Long {
val now = Calendar.getInstance()
val then = (now.clone() as Calendar).apply {
set(Calendar.HOUR_OF_DAY, hourOfDay)
set(Calendar.MINUTE, minute)
}
return then.timeInMillis - now.timeInMillis
}
}
我在调度作业时使用了setMinimumLatency(timeToWaitBeforeExecuteJob)
和setOverrideDeadline(timeToWaitBeforeExecuteJob)
约束,以便作业将在我们希望它运行的准确时间执行。
我运行了一次应用程序 go 并从最近的应用程序列表中删除了该应用程序。 然后我暂停了设备,1分钟后,我听到了提示音。 当我恢复设备并检查时,预期的通知就在那里。
您也应该考虑 Remon Shehatta 的回答。 因为 WorkManager 似乎位于 JobScheduler 和 AlarmManager 之上,并根据设备的 API 级别选择正确的。 因此,如果您的目标是 21 岁以上的 API 级别,使用 WorkManager 可能会更好。但是正如您提到的,AlarmManager 不适合您,您应该尝试并选择正确的。
请向我们更新您的发现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.