1. PendingIntent认识
PendIntent其实是Intent的封装,这就带来了几个问题:
- 为什么要有PendingIntent?与Intent有什么区别?
- PendingIntent的应用场景主要有哪些?
- 它的内部是如何实现的?
1.1 与Intent的区别
-
Intent
是意图的意思。Android 中的 Intent 正是取自这个意思,它是一个消息对象,通过它,Android 系统的四大组件能够方便的通信,并且保证解耦。Intent 可以说明某种意图,携带一种行为和相应的数据,发送到目标组件。
-
PendingIntent
是对Intent的封装,但它不是立刻执行某个行为,而是满足某些条件或触发某些事件后才执行指定的行为
A组件 创建了一个 PendingIntent 的对象然后传给 B组件,B 在执行这个 PendingIntent 的 send 时候,它里面的 Intent 会被发送出去,而接受到这个 Intent 的 C 组件会认为是 A 发的。
B以A的权限和身份发送了这个Intent
我们的 Activity 如果设置了 exported = false,其他应用如果使用 Intent 就访问不到这个 Activity,但是使用 PendingIntent 是可以的。
即:PendingIntent将某个动作的触发时机交给其他应用;让那个应用代表自己去执行那个动作(权限都给他)
2.2 获取PendingIntent
关于PendingIntent的实例获取一般有以下五种方法,分别对应Activity、Broadcast、Service
getActivity()
getActivities()
getBroadcast()
getService()
getForegroundService()
它们的参数都相同,都是四个:
Context
,requestCode
,Intent
,flags
,分别对应上下文对象、请求码、请求意图用以指明启动类及数据传递、关键标志位。
前面三个参数共同标志一个行为的唯一性,而第四个参数flags:
FLAG_CANCEL_CURRENT
:如果当前系统中已经存在一个相同的PendingIntent对象,那么就将先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。FLAG_NO_CREATE
:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent对象而是直接返回null,如果之前设置过,这次就能获取到。FLAG_ONE_SHOT
:该PendingIntent只作用一次。在该PendingIntent对象通过send()方法触发过后,PendingIntent将自动调用cancel()进行销毁,那么如果你再调用send()方法的话,系统将会返回一个SendIntentException。FLAG_UPDATE_CURRENT
:如果系统中有一个和你描述的PendingIntent对等的PendingInent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如更新Intent中的Extras
备注:两个PendingIntent对等是指它们的operation一样, 且其它们的Intent的action, data, categories, components和flags都一样。但是它们的Intent的Extra可以不一样
2.3 使用场景
关于PendingIntent的使用场景主要用于闹钟、通知、桌面部件。
大体的原理是: A应用希望让B应用帮忙触发一个行为,这是跨应用的通信,需要 Android 系统作为中间人,这里的中间人就是 ActivityManager。 A应用创建建 PendingIntent,在创建 PendingIntent 的过程中,向 ActivityManager 注册了这个 PendingIntent,所以,即使A应用死了,当它再次苏醒时,只要提供相同的参数,还是可以获取到之前那个 PendingIntent 的。当 A 将 PendingIntent 调用系统 API 比如 AlarmManager.set(),实际是将权限给了B应用,这时候, B应用可以根据参数信息,来从 ActivityManager 获取到 A 设置的 PendingIntent