1. 基本概念
在Android 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver 是对发送出来的Broadcast 进行过滤接受并响应的一类组件,是Android 四大组件之一。
广播接收者(BroadcastReceiver)用于接收广播的,广播的发送是通过调用sendBroadcast(Intent),sendOrderedBroadcast(Intent)来实现的。通常一个广播可以被多个广播接收者所接收。
广播被分为两种不同的类型:“普通广播(Normal Broadcasts)”也叫无序广播和“有序广播(OrderedBroadcasts)”。
1、普通广播是完全异步(就是不会被某个广播接收者终止)的,可以在同一时刻(逻辑上)被所有接收者接收到(其实被接收者接收到也是由顺序的,接收者配置的优先级越高,越先接收到,也就是说广
播接收者的优先级对于无序广播也是有用的),消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播的传播。
2、有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A 接收者的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。在传递的过程中如果有某个接收者终止(abortBroadCast)了该广播,那么后面的接收者就接收不到该广播。
3、广播接收者属于四大组件之一,因此通常需要AndroidManifest.xml 中进行注册,优先级别声明在intent-filter 元素的android:priority 属性中,数越大优先级别越高,取值范围:-1000 到1000,优先级别也可以调用IntentFilter 对象的setPriority()进行设置。
4、有序广播的接收者可以终止广播的传播,广播的传播一旦终止,后面的接收者就无法接收到广播,有序广播的接收者可以将数据传递给下一个接收者,如:A 得到广播后,可以往它的结果对象中存入数据,当广播传给B 时,B 可以从A 的结果对象中得到A 存入的数据。
5、Context.sendBroadcast() 发送的是普通广播,所有订阅者都有机会获得并进行处理。
6、Context.sendOrderedBroadcast() 发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终
止, 后面的接收者就再也无法获取到广播。对于有序广播, 前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的据。
2. Android 系统常见的广播
Android 为了将系统运行时的各种“事件”通知给其他应用(或者说通知给我们程序员,让我们程序员好做出相应的反应。举个生活中的例子:比如我们坐火车,当前方到达某站的时候,火车乘务员会给所有乘客发送即将到站的广播,这样乘客收到广播后就可以提前准备下车),因此内置了多种广播,比如:系统电量的改变、屏幕的锁屏、网络状态的改变、接收到新的短信、拨打电话事件、sdcard 的挂载和移除、应用的安装和卸载等等。比如我们开发的在线播放视频类的APP,那么我们就有必要监听网络转态改变的事件广播,如果用户的网络状态从wifi 改变为了4G 上网,那么应该提示用户是否使用4G 网络继续播放视频,如果不提示用户,那么就可能导致用户流量被大量使用,一会儿功夫,用户可能就要停机了。
接下来我们会用4 个案例来演示广播接收者的使用。
2.1 案例-IP 拨号器
需求分析
什么是IP 拨号服务?我们为什么要用IP 服务?所谓的IP 拨号就是通过接入数据网络来传播语音信息。IP 拨号的目的在于转接至其他频道,减少话费等用处。移动17951,联通17911,打长途时在电话号码前加上这个就便宜了,如果你的手机上有这个键的话,那么打电话时输入长途电话号码后,直接按那个键就拨出去了,它会自动加上IP。通俗的说就是打长途便宜。
例如手机拨打长途电话:
移动拨区号+电话号=0.25/分市话+0.7/分长途=0.95/分;
移动拨17951+区号+电话号=0.25/分市话+0.3/分长途=0.55/分。
了解了IP 拨号的用途之后,接下来,我们通过程序在用户拨出去的号码前自动加上一个IP 号码,为用户省钱。
之所以能实现这样的功能,是因为拨号的时候Android 系统会发送一个有序广播,该广播中携带了用户拨打的号码,我们通过注册广播接收者就可以获取到该广播,同时将该广播中的数据进行修改。从而实现了用户号码自动加IP 号的功能。
为了能让用户自己决定IP 号码,我们需要一个界面(如图1-2),让那个用户输入IP 号码,然后将该IP 号码保存到SharedPreferences 中。
布局文件如下
|
|
实现代码
在该案例中总共用到了两个类一个是MainActivity.java 负责让用户输入IP 号码,另外一个是自定义的广播接收者IPCallerReceiver 负责监听用户的拨打电话事件。
|
|
编写自定义广播接收者需要自定义一个类然后继承系统提供的BroadCastReceiver 类,然后覆写抽象方法onReceive。
|
|
在清单文件中进行注册
广播是Android 四大组件之一,因此需要在AndroidManifest.xml 中进行注册。同时监听用户的拨打电话行为也属于侵犯用户隐私的行为,因此需要添加权限。
注册广播
|
|
大家可以发现广播接收者的注册也需要通过intent-filter 来监听特定的广播,如果是监听Android 系统的,那么在action 中就需要配置系统提供的常量。如果监听自定义发送的广播,那么就需要配置自定义广播设置的action。
声明权限
|
|
2.2 案例-短信监听器
系统接收到短信时会将该事件以有序广播(部分自定义的ROM 可能已经修改了这个策略,比如:小米的MIUI 系统) 的形式发送出去, 因此我们只需要自定义一个BroadCastReceiver 监听该广播(android.provider.Telephony.SMS_RECEIVED)即可监听到短信的到来。由于该广播是有序的,因此如果将我们自定义的BroadCastReceiver 配置了较高的优先级,那么我们就能先于系统短信app 接收到该广播,
然后终止该广播,从而就实现了短信拦截功能。
通过该案例我们可以学到:
- 什么是有序广播?
- 如何终止有序广播
- 如何从广播中获取短信
- 广播的优先级概念
在该案例中我们要做一个类似短信黑名单的应用,主界面提供一个EditText 和一个Button,让用户输入一个“黑名单”,点击保存之后,如果该号码发短信过来,那么我们的应用就将其拦截
2.3 案例-监听应用的安装和卸载
在Android 系统中,安装应用和卸载应用事件也都会发送特定的广播,我们可以通过监听这些广播间接获取到用户新安装了什么软件,卸载了哪些软件,进而可以统计用户的偏好,或统计某个软件的存留率。
需求很简单,监听应用的安装和卸载,并将其报名打印出来即可。
该应用不需要界面,代码也很简单,只需要一个自定义广播接收这就可以了。
3. 发送无序广播
4. 发送有序广播
5. 特殊的广播接收者-锁屏与解屏
拦截短信的广播
|
|
注册静态广播
|
|
反注册广播,防止内存泄露
|
|
注册广播并设置优先级
|
|
案例1:IP拨号器
|
|
|
|
案例2:短信防火墙
|
|
案例3:监听SD卡状态
|
|
案例4:手机勒索软件
|
|
案例5:监控应用的状态
|
|
案例6:发送自定义广播
|
|