繁体   English   中英

即使在用户从最近的应用程序中删除应用程序后,如何安排和发送通知?

[英]How To schedule and a send Notification even after user removes app from recent apps?

我的应用很简单

  1. 从用户那里花时间(我知道怎么做)

  2. 安排通知(我知道如何发送通知)

  3. 现在我只想知道即使用户从最近的应用程序中删除它,我如何发送此通知。

尝试过的解决方案——AlarmManager、BroudcastReceiver、Service、Intent Service、

但只有当应用程序存在于 RAM 中时,所有这些都有效(最近的移动应用程序列表)。

我该怎么做就告诉我主题。 我不需要代码。 我会研究那个。

您可以使用 WorkManger 来安排任务。

WorkManager API 可以轻松安排可延迟的异步任务,即使应用程序退出或设备重新启动,这些任务也会运行。

在此处查看 Google 文档。

对于通知,您可以在工作管理器 class 中发送通知。 在这里了解更多。

这些提示应该足够了。 如果您需要更多说明,请告诉我。

正如您提到的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM