首页 > 解决方案 > 如果目标应用程序被强制关闭,PendingIntent 会发生什么?

问题描述

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

使用 AlarmManager,我将 PendingIntent 发送到我的 Receiver 类。一切正常,直到我强制关闭我的应用程序。在这种情况下,通知不会出现。

所以我的问题是:这个 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)
    }

标签: androidandroid-intentalarmmanagerandroid-pendingintent

解决方案


如官方 Android 文档中所定义

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

重新访问您的代码以检查是否有其他任何可能导致此问题的内容。


推荐阅读