Android broadcast 相同优先级的顺序
来源:互联网 发布:淘宝动态评分计算器 编辑:程序博客网 时间:2024/06/05 08:46
为了利于各个进程应用之间的通信,android提供了一个很方便的处理方式:广播机制。广播机制顾名思义,就是广播发送者无需判断具体某个接收者的存在,把广播发送出去,任务即完成。这样保证了有效通信的同时又最大限度的降低了android系统各个模块的耦合性。
Android广播有两个很重要的要素:
1 广播 - 用于发送广播
有序广播 - 被广播接收器接收后,可被终止,无法往下继续传达。 典型代表:短信广播
普通广播 - 发送至每一个已经注册(订阅)的广播接收器,无法被终止。 典型代表:开机启动广播
2 广播接收器 - 用于订阅广播后接收广播
静态注册广播 - 在AndroidManifest.xml中设置,程序不用启动亦可接收。 典型代表:很多开机启动的APP,都是接收开机启动广播带起服务的。
动态注册广播 - 代码中注册广播,程序未启动时,无法接收广播。 典型代表:Go短信,将Go短信强行停止,Go短信无法接收短信。
广播注册过程和接收广播顺序过程
图1 注册广播流程简图
静态广播接收器 由PackageManagerService负责,当手机启动时(或者新安装了应用),PackageManagerService负责扫描手机中所有已安装的APP应用(题外话,确定不再使用的APP需要卸载了),将AndroidManifest.xml中 有关注册广播的信息 解析出来,存储至一个全局静态变量当中mReceivers。
需要注意的是:
1 PackageManagerService扫描目录的顺序如下:
system/framework
system/app
vendor/app
data/app
drm/app-private
2 当处于同一目录下时:按照file.list()的返回顺序。(题外话:因为在data/app下的应用都是用户安装的,并且都是以com.xxx.xxx-1.apk 的形式出现,所以如果打算做手机管家之类的应用,需要好好的研究下包名,争取在file.list()的独木桥下抢的头筹---优先接收开机启动完成的广播。)
3 在此处并未对 接收顺序做完整的排序。(注意修饰词完整的,毕竟先扫描的当然会有一定优先级)
动态广播接收器 由ActivityManagerService负责,当APP的服务或者进程起来之后,执行了注册广播接收的代码逻辑,即进行加载,最后会存储在一个全局静态变量
mReceiverResolver中。
需要注意的是:
1 这个并非是一成不变的,当程序被杀死之后, 已注册的动态广播接收器也会被移出mReceiverResolver,直到下次程序启动,再进行动态广播的注册,当然这里面的顺序也已经变更了一次。
2 这里也并没完整的进行广播的排序,只记录的注册的先后顺序,并未有结合优先级的处理。
当有广播发出时,接收顺序如下:
接下来请看代码以片段:
- private final int broadcastIntentLocked(ProcessRecord callerApp,
- String callerPackage, Intent intent, String resolvedType,
- IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle map, String requiredPermission,
- boolean ordered, boolean sticky, int callingPid, int callingUid) {
- …………
- …………
- // 静态广播接收器list
- List receivers = null;
- // 动态广播接收器List
- List<BroadcastFilter> registeredReceivers = null;
- // 获取静态广播接收器mReceivers
- try {
- if (intent.getComponent() != null) {
- // Broadcast is going to one specific receiver class...
- ActivityInfo ai = AppGlobals.getPackageManager().
- getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
- if (ai != null) {
- receivers = new ArrayList();
- ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = ai;
- receivers.add(ri);
- }
- } else {
- // Need to resolve the intent to interested receivers...
- if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
- == 0) {
- receivers =
- AppGlobals.getPackageManager().queryIntentReceivers(
- intent, resolvedType, STOCK_PM_FLAGS);
- }
- // 获取动态广播接收器mReceiverResolver
- registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
- }
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
- }
- final boolean replacePending =
- (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
- int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
- ……
- // 如果接收到的广播 是普通广播。
- if (!ordered && NR > 0) {
- // If we are not serializing this broadcast, then send the
- // registered receivers separately so they don't wait for the
- // components to be launched.
- BroadcastRecord r = new BroadcastRecord(intent, callerApp,
- callerPackage, callingPid, callingUid, requiredPermission,
- registeredReceivers, resultTo, resultCode, resultData, map,
- ordered, sticky, false);
- // 很明显接收到普通广播之后,在这只处理了动态广播 registeredReceivers,对于普通广播而言,动态广播接收器要优先于静态广播接收器 无关设置的优先级
- boolean replaced = false;
- if (replacePending) {
- for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
- if (intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
- "***** DROPPING PARALLEL: " + intent);
- mParallelBroadcasts.set(i, r);
- replaced = true;
- break;
- }
- }
- }
- if (!replaced) {
- mParallelBroadcasts.add(r);
- scheduleBroadcastsLocked();
- }
- //将registeredReceivers置为null,后面只处理静态广播接收器,所以不会有冲突。
- registeredReceivers = null;
- NR = 0;
- }
- //如果是有序广播,将静态广播接收器和动态广播接收器组合成一个最终的顺序
- int ir = 0;
- if (receivers != null) {
- ...
- //合并的过程,注意顺序
- int NT = receivers != null ? receivers.size() : 0;
- int it = 0;
- ResolveInfo curt = null;
- BroadcastFilter curr = null;
- while (it < NT && ir < NR) {
- if (curt == null) {
- curt = (ResolveInfo)receivers.get(it);
- }
- if (curr == null) {
- curr = registeredReceivers.get(ir);
- }
- //如果动态广播接收器优先级高于或者等于静态广播接收器,那么就插到前面
- //很明显动态的要在静态的前面
- if (curr.getPriority() >= curt.priority) {
- // Insert this broadcast record into the final list.
- receivers.add(it, curr);
- ir++;
- curr = null;
- it++;
- NT++;
- } else {
- // Skip to the next ResolveInfo in the final list.
- it++;
- curt = null;
- }
- }
- }
最后举个例子:
(以下的静A 表示静态广播接收器,同理动B。)
1 静A (优先级1)
2 动B(优先级1)
3 静C (优先级2,后扫描)
4 静D (优先级2,先扫描)
5 动E (优先级2,先注册)
6 动F (优先级2,后注册)
当来了一个 有序广播,接收顺序如下:动E > 动F > 静D > 静C > 动B > 静A
当来了一个 普通广播,接收顺序如下:动E > 动F > 动B > 静D > 静C > 静A
参考文章:http://su1216.iteye.com/blog/1776121
- Android broadcast 相同优先级的顺序
- Android broadcast 相同优先级的顺序
- Android broadcast 相同优先级的顺序
- 关于android的Ordered Broadcast的优先级问题
- Broadcast Receiver(三)广播接收器的优先级
- android的广播broadcast和receiver && 广播接收器优先级的深入分析
- android的广播broadcast和receiver && 广播接收器优先级的深入分析
- Android 释放资源和进程的优先级顺序
- Android的Broadcast Receiver
- Android下的broadcast
- android broadcast 的onreceive
- android的Broadcast Service
- android Broadcast的几个问题
- BroadCast广播优先级问题
- 正则表达式的优先级顺序
- 正则表达式的优先级顺序
- 正则表达式的优先级顺序
- 权重--样式的优先级顺序
- WordPress后台友情链接的追加
- 内存溢出,tomcat内存分配调整办法
- make a website ----html
- Reverse Nodes in k-Group
- 【POJ 2396】 Budget
- Android broadcast 相同优先级的顺序
- 解决网线不能上网的方法
- div+css 选择器分组 属性选择器 css插入方法 css背景属性
- HDU 1533 Going Home
- Matlab图像处理笔记
- Android 混淆打包
- 使用extjs的mvc架构开发简单的站点
- 优秀博客推荐
- 自学基础1_linux_2_看懂各类命令格式