1.1. 广播简单介绍
Android 广播不关心接收者是否收到处理或者怎样处理广播,能够说是一种单向的通知。
Android 通过 BraodcastReceiver 来监听系统发出的广播,不同的 BraodcastReceiver 通过设置不同的 fliter 来区分监听广播的类型。
有些广播的监听须要相应的权限。
1.2. 注冊广播
1.2.1. 静态注冊
action 能够为自己定义 action,也能够是系统自带的 action。
1.2.2. 动态注冊
MyReceiver receiver = new MyReceiver(); //创建过滤器,并指定 action,使之用于接收同 action 的广播 IntentFilter filter = new IntentFilter("MyReceiver_Action"); //注冊广播接收器 registerReceiver(receiver, filter); 在 activity 中注冊广播,必须在 activity 结束时注销广播,一般在 onStart 中注冊 BroadcastReceiver,在 onStop 中取消 BroadcastReceiver,广播接收器尾随 Activity 的生命周期 //注销广播接收器 unregisterReceiver(receiver);
1.3. 生命周期
1.4. 发送广播
1.4.1. Android 中发送广播的三种形式
普通广播是全然异步的,能够在同一时刻(逻辑上)被全部广播接收者接收到,消息传递的效率比較高,但缺点是:接收者不能将处理结果传递给下一个接收者,而且无法终止广播 Intent 的传播;然而有序广播是依照接收者声明的优先级别(声明在intent-filter 元素的 android:priority 属性中,数越大优先级别越高,取值范围:-1000 到 1000(事实上最大能够为 int 最大值即:2147483647)。也能够调用 IntentFilter 对象的 setPriority()进行设置),被接收者依次接收广播。
如:A 的级别高于 B,B 的级别高于 C,那么,广播先传给 A,再传给 B,最后传给 C。A 得到广播后,能够往广播里存入数据,当广播传给 B 时,B 能够从广播中得到 A 存入的数据。Context.sendBroadcast()发送的是普通广播,全部订阅者都有机会获得并进行处理。Context.sendOrderedBroadcast()发送的是有序广播,系统会依据接收者声明的优先级别按顺序逐个运行接收者,前面的接收者有权终止广播。BroadcastReceiver.abortBroadcast()假设广播被前面的接收者终止,后面的接收者就再也无法获取到广播。
对于有序广播,前面的接收者能够将处理结果存放进广播 Intent,然后传给下一个接收者。Context.sendStickyBroadcast()是发送粘性广播,使用这个 api须要权限 android.Manifest.permission.BROADCAST_STICKY,粘性广播的特点是 Intent 会一直保留到广播事件结束,而这样的广播也没有所谓的 8 秒限制,即上文所讲,假设 onReceive 方法运行时间太长,超过 8 秒的时候系统会将这个广播置为能够干掉的 candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不运行。
1.5. 广播优先级
1.5.1. 基本原则
接收无序广播的接收器也一样能够设置优先级的
动态注冊广播优先级高于静态注冊广播
同等优先级的动态接收器,先注冊的先接收
同等优先级的静态接收器,接收广播的顺序与 String[] java.io.File.list()顺序一致
Ps:这里有一点须要注意的是,同等优先级的静态接收器的接收顺序具有不确定性,原因就是File.list()的方法返回的顺序具有不确定性,假设须要查看某接收器的接收顺序,最好是试验大量的 apk 名。
1.5.2. ordered 广播
1.动态 A(优先级=1)
2.动态 B(优先级=2)
3.动态 C(优先级=2)
4.静态 D(优先级=1)
5.静态 E(优先级=2)
而且 B 先于 C 注冊
那么实际接收顺序应为
B C E A D
也就是说,假设静态接收器的优先级高于动态接收器的优先级,那么还是静态接收器先接收到广播(比方接收 SMS 广播)
1.5.3. 非 ordered 广播
1.6. 仅仅能动态接受广播源代码分析
1. void com.android.server.PowerManagerService.initInThread() 2. Java 代码 3. void initInThread() { 4. „„ 5. mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 6. mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 7. mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 8. mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 9. „„ 10. }
Intent 中都设置了 Intent.FLAG_RECEIVER_REGISTERED_ONLY,所以,假设要接收,必须动态注冊广播接收器 ACTION_SCREEN_OFF 也是如此。
1.6.1. 关于 FLAG_RECEIVER_REGISTERED_ONLY 的说明
FLAG_RECEIVER_REGISTERED_ONLY
Added in API level 1
If set, when sending a broadcast only registered receivers will be called -- no
BroadcastReceiver components will be launched.
Constant Value: 1073741824 (0x40000000)
ACTION_BATTERY_CHANGED(电池电量发生变化的时候,系统发送此广播)该广播就是这样
Java 代码 1. private final void sendIntent() { 2. // 3. Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); 4. intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY 5. Pack up the values and broadcast them to everyone 6. 7. }
1.7. 广播注冊过程分析
1.7.1. 静态注冊 Receiver 的流程
PMS 会解析 apk 的 manifest 文件,查找这里注冊的 receiver,然后载入到内存中。
PMS 初始化扫描文件夹的顺序:
system/framework
system/app
vendor/app
data/appd
rm/app-private
我们看到了 PMS 怎样在初始化的时候怎样解析 manifest 并把当中的 element 存放到内存中的当中receiver 保存到了 owner 的成员变量 receivers 中,owner 的类型是
android.content.pm.PackageParser.Package 也就是说 scanPackageLI 返回结果就是已经包括了manifest 信息的 Package 对象。
1.7.2. 动态注冊 Receiver 的流程
静态广播是 PackageManagerService负责,保存到其成员变量 mReceivers 中,动态广播是 ActivityManagerService 负责,保存到其成员变量 mReceiverResolver 中。
1.8. 广播发送过程分析
1.8.1. 分析
void android.app.ContextImpl.sendBroadcast(Intent intent) void android.app.ContextImpl.sendBroadcast(Intent intent, String receiverPermission) void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission) void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) void android.app.ContextImpl.sendStickyBroadcast(Intent intent) void android.app.ContextImpl.sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)能够分为 3 组:1 普通广播;2 Ordered 广播;3 Sticky 广播。不论哪种,最后都会由 AMS 处理
1.8.2. 总结
先处理动接收器,然后处理静态接收器 ordered 广播同一时候处理动态接收器和静态接收器先将动态接收器与静态接收器合并,保持着与优先级同样的顺序,优先级高的在前面,否则顺序不变。静态接收器与动态接收器优先级同样的话,动态接收器在前。