Android广播机制分析

1.1. 广播简介

        Android 广播与生活中的广播概念不同,它是指系统中产生事件后的通知。Android 广播不关心接收者是否收到处理或者如何处理广播,可以说是一种单向的通知。
        Android 通过 BraodcastReceiver 来监听系统发出的广播,不同的 BraodcastReceiver 通过设置不同的 fliter 来区分监听广播的类型。有些广播的监听需要相应的权限。

1.2. 注册广播

        BraodcastReceiver 必须经过注册才能具有监听功能,注册的方式有两种:

1.2.1. 静态注册

        通过在 AndroidManifest.xml 中注册对应的 receiver,并设置要监听的 action

        其中 MyReceiver 为继承 BroadcastReceiver 的类,重写了 onReceiver 方法,并在 onReceiver方法中对广播进行处理。<intent-filter>标签设置过滤器,接收指定 action 广播。静态注册方式的特点:不管改应用程序是否处于活动状态,都会进行监听。action 可以为自定义 action,也可以是系统自带的 action。

1.2.2. 动态注册

动态注册是在程序中对 BroadcastReceiver 完成监听注册

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. 生命周期

        BroadcastReceiver 生命周期只有 8 秒左右,如果在 onReceive()内做超过 8 秒内的事情,就会报ANR(Application Not Response)程序无响应的错误信息。它的生命周期为从回调 onReceive()方法开始到该方法返回结果后结束。因此,如果要在收到广播后做耗时操作,最好放到 service 中去做,子线程也不好,当子线程未结束的时候,BroadcastReceiver 已经销毁。

1.4. 发送广播

1.4.1. Android 中发送广播的三种形式

        广播被分为三种不同的类型:“普通广播(Normal broadcasts)”、“有序广播(Ordered broadcasts)”和“粘性广播(Sticky broadcast)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有广播接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播 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 广播

假设有如下优先级的 5 个接收器
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. 只能动态接受广播源码分析

有些广播,我们无法用静态接收器接收,比如 ACTION_SCREEN_ON,当屏幕被点亮的时候系统发送此广播。

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 的说明

public static final int
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(电池电量发生变化的时候,系统发送此广播)该广播就是这样

void com.android.server.BatteryService.sendIntent()

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 的流程

        静态 receiver 的注册是由 PackageManagerService 开机的时候负责初始 PMS 在开机的时候会对系统一些目录逐个扫描,解析 apk 文件。静态广播接收器就是在 PMS 做这件事情的时候顺便处理的。
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 的流程

        动态注册最终会调用到 AMS 中的 registerReceiver 函数,最终所有动态注册的 receiver 都保存到 AMS 的成员变量 mReceiverResolver 中。静态广播和动态广播如何注册的,我们已经全部分析完了。静态广播是 PackageManagerService负责,保存到其成员变量 mReceivers 中,动态广播是 ActivityManagerService 负责,保存到其成员变量 mReceiverResolver 中。

1.8. 广播发送过程分析

1.8.1. 分析

Context 中的 sendBroadCast 函数的实现是在 ContextImpl 中,和发送广播相关的有如下六个函数:

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 处理

        如果是非 ordered 广播,那么 mParallelBroadcasts 将存储所有动态接收器,然后合并的时候,mParallelBroadcasts 设置为 null,所以不会合并到 receivers 中,如果是 ordered 广播,那么mParallelBroadcasts 将合并到 receivers 中,然后,不管是哪种广播,最后都是调用scheduleBroadcastsLocked 继续处理,最终到 processNextBroadcast 函数上。广播是否有序,即通过 Boolean 变量 ordered 进行设置。

1.8.2. 总结

        发送过程情况分为两种(scheduleBroadcastsLocked),ordered 广播和非 ordered 广播、非ordered 广播。先处理动接收器,然后处理静态接收器 ordered 广播同时处理动态接收器和静态接收器先将动态接收器与静态接收器合并,保持着与优先级相同的顺序,优先级高的在前面,否则顺序不变。静态接收器与动态接收器优先级相同的话,动态接收器在前。

时间: 2024-09-21 02:03:39

Android广播机制分析的相关文章

android 广播机制,短信电话 拦截

问题描述 android 广播机制,短信电话 拦截 我需要做的是一个安卓小项目,广播机制实现对短信.电话 的拦截,电话短信 均为sqlite数据库的两张表 ,求大神指定? 解决方案 android 关于特定短信电话拦截android短信和广播机制android--广播及短信拦截 解决方案二: 电话 contacts2.db 短信 mmssms.db 解决方案三: http://blog.sina.com.cn/s/blog_a28e3dd901018wky.html

Android广播机制

一.Android广播机制介绍 广播机制最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的. Android中广播的是操作系统中产生的各种各样的事件.例如,收到一条短信就会产生一个收到短信息的事件.而Android操作系统一旦内部产生了这些事件,就会向所有的广播接收器对象来广播这些事件. BraodcastReceiver(广播接收器)是为了实现系统广播而提供的一种组件,并且广播事件处理机制是系统级别的.比如,我们可以发出一种广播来测试是否收到短信,这时候就可以定义一

图解 Android 广播机制

从现实生活中理解广播机制 一听到广播我们第一感觉就会联想到小时候村里面的广播,每逢村里有什么活动都是通过广播发送的.收听收音机也是一种广播,在收音机中有很多个广播电台,每个广播电台播放的内容都不相同.接受广播时广播(发送方)并不在意我们(接收方)接收到广播时如何处理.好比我们收听交通电台的广播,电台中告诉我们现在在交通状况如何,但它并不关心我们接收到广播时做如何做出处理,这不是广播应该关心的问题,OK,到这里我们从生活中的一些小例子浅浅的理解了一下广播,那么Android 中的广播是如何操作的呢

Android安全机制分析

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; Android系统是基于Linux内核开发的,因此,Android系统不仅保留和继承了Linux操作系统的安全机制,而且其系统架构的各个层次 都有独特的安全特性. 1. Linux内核层安全机制       Android的Linux内核包含了强制访问控制机制和自主访问控制机制.强制访问控制机制由Linux安全模块来实现,但Google出于某种原因,并没有将LSM编

Android BroadcastReceiver广播机制概述_Android

Android广播机制概述Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通信方式,可以使用的场景如下: 1.同一app内部的同一组件内的消息通信(单个或多个线程之间): 2.同一app内部的不同组件之间的消息通信(单个进程):  3.同一app具有多个进程的不同组件之间的消息通信:  4.不同app之间的组件之间消息通信:  5.Android系统在特定情况下与App之间的消息

Android BroadcastReceiver广播机制概述

Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通信方式,可以使用的场景如下: 1.同一app内部的同一组件内的消息通信(单个或多个线程之间): 2.同一app内部的不同组件之间的消息通信(单个进程):  3.同一app具有多个进程的不同组件之间的消息通信:  4.不同app之间的组件之间消息通信:  5.Android系统在特定情况下与App之间的消

Android广播接收机制详细介绍(附短信接收实现)_Android

Android中广播(BroadcastReceiver)的详细讲解. 1. BroadcastReceiver的注册过程: (1).广播消息发出来后,只有订阅了该广播的对象才会接收发出来的广播消息并做出相应处理. **(2).**Android广播分为两个方面:广播发送者和广播接收者.Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型.广播接收者通过Binder机制向AMS进行注册,AMS查找符合相应条件的Broadcastreceiver,将广播发送到BroadcastRe

深入浅析Android消息机制_Android

在Android中,线程内部或者线程之间进行信息交互时经常会使用消息,这些基础的东西如果我们熟悉其内部的原理,将会使我们容易.更好地架构系统,避免一些低级的错误. 每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时,是不可能在这个UI线程做的,因为Android在3.0以后的版本已经禁止了这件事情,直接抛出一个异常.所以我们需要一个子线程来处理那些

深入浅析Android消息机制

在Android中,线程内部或者线程之间进行信息交互时经常会使用消息,这些基础的东西如果我们熟悉其内部的原理,将会使我们容易.更好地架构系统,避免一些低级的错误. 每一个Android应用在启动的时候都会创建一个线程,这个线程被称为主线程或者UI线程,Android应用的所有操作默认都会运行在这个线程中. 但是当我们想要进行数据请求,图片下载,或者其他耗时操作时,是不可能在这个UI线程做的,因为Android在3.0以后的版本已经禁止了这件事情,直接抛出一个异常.所以我们需要一个子线程来处理那些