一、Android广播机制概述
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。
广播作为Android组件间的通信方式,可以使用的场景如下:
- 同一app内部的同一组件内的消息通信(单个或多个线程之间);
- 同一app内部的不同组件之间的消息通信(单个进程);
- 同一app具有多个进程的不同组件之间的消息通信;
- 不同app之间的组件之间消息通信;
- Android系统在特定情况下与App之间的消息通信。
二、广播的分类
- Normal Broadcast(普通广播):通常调用sendBroadcast(Intent)(Intent, String)方法发送
- System Broadcast(系统广播):发生各种事件时,系统自动发送
- Ordered Broadcast(有序广播):调用sendOrderedBroadcast(Intent, String)方法发送
- Local Broadcast(本地广播):调用LocalBroadcastManager.sendBroadcast(intent)方法发送
- Sticky Broadcast(粘性广播):已弃用(API 21)
1).Normal Broadcast:普通广播
此处将普通广播界定为:开发者自己定义的intent,以context.sendBroadcast_"AsUser"(intent, ...)形式。具体可以使用的方法有:
sendBroadcast(intent)
sendBroadcast(intent,receiverPermission)
sendBroadcastAsUser(intent,userHandler)
sendBroadcastAsUser(intent,userHandler,receiverPermission)。
普通广播会被注册了的相应的感兴趣(intent-filter匹配)接收,且顺序是无序的。如果发送广播时有相应的权限要求,BroadCastReceiver如果想要接收此广播,也需要有相应的权限。
- 发送示例如下:
- 若被注册了的
BroadCastReceiver
注册的intentFilter
的action
与上述匹配,则会接收此广播,且顺序是无序的。如果发送时有相应的权限要求,则BroadCastReceiver
只有拥有相应的权限才能接受。
2).System Broadcast: 系统广播
Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。
如:开启启动,网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。
文末提供详细系统广播清单,不包含使用说明(位于SDK下boradcast_action.txt ),请自行查找Google官方文档
3).Ordered broadcast:有序广播
有序广播的有序广播中的“有序”是针对广播接收者而言的,指的是发送出去的广播被BroadcastReceiver按照先后循序接收。有序广播的定义过程与普通广播无异,只是其的主要发送方式变为:sendOrderedBroadcast(intent, receiverPermission, ...)。
- 定义过程与普通广播一样,调用
sendOrderedBroadcast()
,同样也有对应的sendOrderedBroadcastAsUser()
方法,只不过同样针对于预装在系统映像的应用。
对于有序广播,其主要特点总结如下:
1>多个具当前已经注册且有效的BroadcastReceiver接收有序广播时,是按照先后顺序接收的,先后顺序判定标准遵循为:将当前系统中所有有效的动态注册和静态注册的BroadcastReceiver按照priority属性值从大到小排序,对于具有相同的priority的动态广播和静态广播,动态广播会排在前面。
priority
值不同:由大到小排序priority
值相同:动态注册优于静态注册
2>先接收的BroadcastReceiver可以对此有序广播进行截断,使后面的BroadcastReceiver不再接收到此广播,也可以对广播进行修改,使后面的BroadcastReceiver接收到广播后解析得到错误的参数值。当然,一般情况下,不建议对有序广播进行此类操作,尤其是针对系统中的有序广播。
- 按顺序接收
- 允许优先级高的
BroadcastReceiver
截断广播。 - 允许优先级高的
BroadcastReceiver
修改广播
4).Sticky Broadcast:粘性广播(在 android 5.0/api 21中deprecated,不再推荐使用,相应的还有粘性有序广播,同样已经deprecated)
5).Local Broadcast:App应用内广播(此处的App应用以App应用进程为界)
Android中的广播可以跨进程甚至跨App直接通信,且注册是exported对于有intent-filter的情况下默认值是true,由此将可能出现安全隐患如下:
1.其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;
2.其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。
无论哪种情形,这些安全隐患都确实是存在的。由此,最常见的增加安全性的方案是:
1.对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的此广播不被接收;
2.在广播发送和接收时,都增加上相应的permission,用于权限验证;
3.发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
App应用内广播可以理解成一种局部广播的形式,广播的发送者和接收者都同属于一个App。实际的业务需求中,App应用内广播确实可能需要用到。同时,之所以使用应用内广播时,而不是使用全局广播的形式,更多的考虑到的是Android广播机制中的安全性问题。
相比于全局广播,App应用内广播优势体现在:
1.安全性更高;
2.更加高效。
为此,Android v4兼容包中给出了封装好的LocalBroadcastManager类,用于统一处理App应用内的广播问题,使用方式上与通常的全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将主调context变成了LocalBroadcastManager的单一实例。
- 代码示例如下:
三、广播接收者(BroadCastReceiver)的两种注册方式
1).常驻型广播(静态注册)
常驻型广播,这个广播接收者会在程序运行的整个过程中一直存在,不会被注销掉,当程序被杀掉后不会再接收到广播了。它的注册方式就是在你应用程序的AndroidManifast.xml 中进行注册,这种注册方式通常又被称作静态注册。这种方式可以理解为通过清单文件注册的广播是交给操作系统去处理的。在Manifest.xml中注册广播,是一种比较推荐的方法,因为它不需要手动注销广播(如果广播未注销,程序退出时可能会出错)。
例如:下边是注册的一些系统广播接收者
首先写一个类继承自BroadCastReceiver。
然后在清单文件中进行静态的注册配置。这样就完成了对接收拨打电话广播的注册,在整个程序运行的过程中,只要手机拨打电话了都能接收到这个广播,并会执行onReceive中的代码。