如果强制关闭目标应用程序,PendingIntent 会发生什么情况?

What happens to a PendingIntent if the target app was force-closed?

我实际上正在开发一个应该 post 5 天后通知的应用程序。

我使用 AlarmManager 向我的接收器发送一个 PendingIntent class。 一切正常,直到我强行关闭我的应用程序。在这种情况下,通知不会出现。

所以我的问题是: 已触发但未达到目标的 PendingIntent 会怎样? 当我的应用程序最终重新启动时,我可以检查未达到目标的 PendingIntents 吗?

编辑 1:

这些是我的广播接收器的基本部分:

    override fun onReceive(context: Context?, intent: Intent?) {
        if (context != null && intent?.action != null) {
            when (intent.action) {
                INTENT_ACTION_BOOT_COMPLETED -> handleDeviceBoot()
                INTENT_ACTION_REMINDER -> handleReminder(context, intent.getLongExtra(EXTRA_ITEM_ID, -1))
            }
        }
    }

    private suspend fun schedule(context: Context, itemId: Long, fireDate: LocalDateTime) = withContext(Dispatchers.IO) {
        AlarmManagerCompat.setAndAllowWhileIdle(
            getAlarmManager(context),
            AlarmManager.RTC,
            fireDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(),
            makePendingIntent(context, itemId)
        )

        with(AppDatabase.get(context).reminderDao()) {
            val oldReminder = getItemReminder(itemId)

            if (oldReminder == null) {
                insert(Reminder(itemId = itemId, fireDate = fireDate))
            } else {
                update(Reminder(id = oldReminder.id, itemId = itemId, fireDate = fireDate))
            }
        }
    }

    private suspend fun cancel(context: Context, itemId: Long) = withContext(Dispatchers.IO) {
        val reminderDao = AppDatabase.get(context).reminderDao()
        val reminder = reminderDao.getItemReminder(itemId)

        reminder?.let {
            getAlarmManager(context).cancel(makePendingIntent(context, itemId))
            reminderDao.delete(it)
        }
    }

    private fun getAlarmManager(context: Context) = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager

    private fun makePendingIntent(context: Context, itemId: Long): PendingIntent {
        val alarmIntent = Intent(context, ReminderManager::class.java).apply {
            action = INTENT_ACTION_REMINDER
            putExtra(EXTRA_ITEM_ID, itemId)
        }
        return PendingIntent.getBroadcast(context, itemId.toInt(), alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

定义见Official Android Documentation

PendingIntent 本身只是对系统维护的令牌的引用,描述了用于检索它的原始数据。这意味着,即使它拥有的应用程序的进程被终止,PendingIntent 本身仍可从已获得它的其他进程使用。如果创建应用程序稍后重新检索相同类型的 PendingIntent(相同的操作、相同的 Intent 操作、数据、类别和组件以及相同的标志),它将收到表示相同标记的 PendingIntent(如果它仍然有效),并且可以因此调用 cancel() 将其删除。

重新访问您的代码以检查是否有任何其他原因会导致此问题。

当您 "force close" 一个应用程序时,该应用程序被设置为 "stopped state"。在 "stopped state" 中,您的应用程序不会被 Android 自动启动,直到用户手动重新启动应用程序。这意味着如果您 "force close" 您的应用程序,您的应用程序将不会收到任何广播 Intent 直到用户手动重新启动它。

我希望(虽然我自己没有尝试过),如果您安排闹钟在时间 X 和时间 X 之前关闭,您 "force close" 应用程序,当时间 X 发生时,闹钟管理器将尝试发送 PendingIntent,但是 Android 将拒绝实际执行 BroadcastReceiver,因为该应用程序位于 "stopped state" 中。在这种情况下,我预计触发器会丢失。 Android 不会重试或重新安排。

基本上,当用户 "force close" 使用应用程序时,他是在告诉 Android 他不希望该应用程序再 运行,包括该应用程序运行的任何后台进程将来可能有,或者想开始。

答案很简短:活动的 PendingIntents 在应用程序强制停止时被取消。