专栏名称: Android_开发者
目录
相关文章推荐
51好读  ›  专栏  ›  Android_开发者

关于 PendingIntent 您需要知道的那些事

Android_开发者  · 掘金  · android  · 2021-08-05 21:32

正文

阅读 93

关于 PendingIntent 您需要知道的那些事

PendingIntent 是 Android 框架中非常重要的组成部分,但是目前大多数与该主题相关的开发者资源更关注它的实现细节,即 "PendingIntent 是由系统维护的 token 引用",而忽略了它的用途。

由于 Android 12 对 PendingIntent 进行了 重要更新 ,包括需要显式确定 PendingIntent 是否是可变的,所以我认为有必要和大家深入聊聊 PendingIntent 有什么作用,系统如何使用它,以及为什么您会需要可变类型的 PendingIntent。

PendingIntent 是什么?

PendingIntent 对象封装了 Intent 对象的功能,同时以您应用的名义指定其他应用允许哪些操作的执行,来响应用户未来会进行的操作。比如,所封装的 Intent 可能会在闹铃关闭后或者用户点击通知时被触发。

PendingIntent 的关键点是其他应用在触发 intent 时是 以您应用的名义 。换而言之,其他应用会使用您应用的身份来触发 intent。

为了让 PendingIntent 具备和普通 Intent 一样的功能,系统会使用创建 PendingIntent 时的身份来触发它。在大多数情况下,比如闹铃和通知,其中所用到的身份就是应用本身。

我们来看应用中使用 PendingIntent 的不同方式,以及我们使用这些方式的原因。

常规用法

使用 PendingIntent 最常规最基础的用法是作为关联某个通知所进行的操作。

val intent = Intent(applicationContext, MainActivity::class.java).apply {
    action = NOTIFICATION_ACTION
    data = deepLink
}
val pendingIntent = PendingIntent.getActivity(
    applicationContext,
    NOTIFICATION_REQUEST_CODE,
    intent,
    PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(
        applicationContext,
        NOTIFICATION_CHANNEL
    ).apply {
        // ...
        setContentIntent(pendingIntent)
        // ...
    }.build()
notificationManager.notify(
    NOTIFICATION_TAG,
    NOTIFICATION_ID,
    notification
)
复制代码

可以看到我们构建了一个标准类型的 Intent 来打开我们的应用,然后,在添加到通知之前简单用 PendingIntent 封装了一下。

在本例中,由于我们明确知道未来需要进行的操作,所以我们使用 FLAG_IMMUTABLE 标记构建了无法被修改的 PendingIntent

调用 NotificationManagerCompat.notify() 之后工作就完成了。当系统显示通知,且用户点击通知时,会在我们的 PendingIntent 上调用 PendingIntent.send() ,来启动我们的应用。

更新不可变的 PendingIntent

您也许会认为如果应用需要更新 PendingIntent ,那么它需要是可变类型,但其实并不是。应用所创建的 PendingIntent 可通过 FLAG_UPDATE_CURRENT 标记来更新。

val updatedIntent = Intent(applicationContext, MainActivity::class.java).apply {
   action = NOTIFICATION_ACTION
   data = differentDeepLink
}

// 由于我们使用了 FLAG_UPDATE_CURRENT 标记,所以这里可以更新我们在上面创建的 
// PendingIntent
val updatedPendingIntent = PendingIntent.getActivity(
   applicationContext,
   NOTIFICATION_REQUEST_CODE,
   updatedIntent,
   PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
// 该 PendingIntent 已被更新
复制代码

在接下来的内容中我们会解释为什么将 PendingIntent 设置为可变类型。

跨应用 API

通常的用法并不局限于与系统交互。虽然在某些操作后使用 startActivityForResult() onActivityResult() 接收回调 是非常常见的用法,但它并不是唯一用法。

想象一下一个线上订购应用提供了 API 使其他应用可以集成。当 Intent 启动了订购食物的流程后,应用可以 Intent extra 的方式访问 PendingIntent 。一旦订单完成传递,订购应用仅需启动一次 PendingIntent

在本例中,订购应用使用了 PendingIntent 而没有直接发送 activity 结果,因为订单可能需要更长时间进行提交,而让用户在这个过程中等待是不合理的。







请到「今天看啥」查看全文