安卓 BroadcastReceiver笔记
安卓广播相关概念
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。从实现原理看上,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度上解耦,使得系统能够方便集成,更易扩展。
广播作为Android组件间的通信方式,可以使用的场景如下:
1.同一app内部的同一组件内的消息通信(单个或多个线程之间);
2.同一app内部的不同组件之间的消息通信(单个进程);
3.同一app具有多个进程的不同组件之间的消息通信;
4.不同app之间的组件之间消息通信;
5.Android系统在特定情况下与App之间的消息通信。
广播可实现应用内线程、进程间及应用间的通信。实际开发应用中广播主要用于监听系统状态变化及替代AIDL实现应用进程间通信的一种简化方式。
可以将其分为以下几种类型:
1).Normal Broadcast:普通广播
此处将普通广播界定为:开发者自己定义的intent,以context.sendBroadcast_"AsUser" (intent, ...)形式。具体可以使用的方法有:
sendBroadcast(intent)
sendBroadcast(intent, receiverPermission)
sendBroadcastAsUser(intent, userHandler)
sendBroadcastAsUser(intent, userHandler,receiverPermission)。
普通广播会被注册了的相应的感兴趣(intent-filter匹配)接收,且顺序是无序的。如果发送广播时有相应的权限要求,BroadCastReceiver如果想要接收此广播,也需要有相应的权限。
2).System Broadcast: 系统广播
Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动,网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。
3)Ordered broadcast:有序广播
有序广播的有序广播中的“有序”是针对广播接收者而言的,指的是发送出去的广播被Broadcast Receiver按照先后循序接收。有序广播的定义过程与普通广播无异,只是其的主要发送方式变为:sendOrderedBroadcast(intent, receiverPermission, ...)。
对于有序广播,其主要特点总结如下:
1>多个具当前已经注册且有效的BroadcastReceiver接收有序广播时,是按照先后顺序接收的,先后顺序判定标准遵循为:将当前系统中所有有效的动态注册和静态注册的BroadcastReceiver按照priority属性值从大到小排序,对于具有相同的priority的动态广播和静态广播,动态广播会排在前面。
2>先接收的BroadcastReceiver可以对此有序广播进行截断,使后面的BroadcastReceiver不再接收到此广播,也可以对广播进行修改,使后面的BroadcastReceiver接收到广播后解析得到错误的参数值。当然,一般情况下,不建议对有序广播进行此类操作,尤其是针对系统中的有序广播。
4)Sticky Broadcast:粘性广播(在 android 5.0/api 21中deprecated,不再推荐使用,相应的还有粘性有序广播,同样已经deprecated)。
既然已经deprecated,此处不再多做总结。
5)LocalBroadcastReceiver:App应用内广播(此处的App应用以App应用进程为界)
App应用内广播可以理解成一种局部广播的形式,广播的发送者和接收者都同属于一个App。实际的业务需求中,App应用内广播确实可能需要用到。同时,之所以使用应用内广播时,而不是使用全局广播的形式,更多的考虑到的是Android广播机制中的安全性问题。相比于全局广播,App应用内广播优势体现在:
1.安全性更高;
2.更加高效。
代码部分
广播的使用流程:
S1.添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
S2.注册广播:
<receiver android:name=".test.broadcast.exam.exam0.NetworkBroadcastReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
S3.广播处理:
public class NetworkBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
}
}
广播的主要方法:
// 广播的注册 //动态注册: //动态注册时,无须在AndroidManifest中注册<receiver/>组件。直接在代码中通过调用Context的registerReceiver函数,可以在程序中动态注册BroadcastReceiver。registerReceiver的定义形式如下: registerReceiver(BroadcastReceiver receiver, IntentFilter filter) registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) 示例: mBroadcastReceiver = new MyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BROADCAST_ACTION); registerReceiver(mBroadcastReceiver, intentFilter); 静态注册: 直接在AndroidManifest.xml文件中进行注册。规则如下: <receiver android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:process="string" > . . . </receiver> <receiver android:name=".MyBroadcastReceiver" > <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> android:exported ——此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。(同样的,activity/service中的此属性默认值一样遵循此规则)同时,需要注意的是,这个值的设定是以application或者application user id为界的,而非进程为界(一个应用中可能含有多个进程); android:name —— 此broadcastReceiver类名; android:permission ——如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收; android:process ——broadcastReceiver运行所处的进程。默认为app的进程。可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程) intent-filter由于指定此广播接收器将用于接收特定的广播类型。 // 自定义广播的发送 Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION); intent.putExtra("name", "qqyumidi"); sendBroadcast(intent); // 广播的接收 public void onReceive(Context context, Intent intent) { } // LocalBroadcastReceiver本地广播 //registerReceiver(mBroadcastReceiver, intentFilter); //注册应用内广播接收器 localBroadcastManager = LocalBroadcastManager.getInstance(this); localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter); //unregisterReceiver(mBroadcastReceiver); //取消注册应用内广播接收器 localBroadcastManager.unregisterReceiver(mBroadcastReceiver); Intent intent = new Intent(); intent.setAction(BROADCAST_ACTION); intent.putExtra("name", "qqyumidi"); //sendBroadcast(intent); //发送应用内广播 localBroadcastManager.sendBroadcast(intent);
参考:
Android总结篇系列:Android广播机制 cnblogs
Android四大组件:BroadcastReceiver史上最全面解析 简书
总结1
/*---------------------------------------- *-描述--Broadcast例题总结. *-描述--S1.广播的使用步骤: * SS1.创建MyBroadcastReceiver继承BroadcastReceiver,并重写onReceive方法 * SS2.注册广播接收器 * SSS1.静态的注册方式:在manifest里配置 * SSS2.动态JAVA代码注册方式 * SS3.使用Intent发送广播 *-描述--S2.Broadcast广播的三种类型: * SS1.普通广播 无序,测试发现动态注册的广播先收到 sendBroadcast() * SS2.有序广播 有序,根据定义的优先级(priority),高的先收到 sendOrderedBroadcast() * SS3.带权限的广播 sendOrderedBroadcast() *-描述--S3.广播的相关方法及属性: * SS1.动态注册广播 registerReceiver(广播接收器,意图过滤器) * SS2.取消注册广播 unregisterReceiver(广播接收器) * SS3.静态注册广播 * <intent-filter android:priority="100"> //优先级 * <action android:name="dir.exam2" /> // * </intent-filter> * SS4.配置权限 * 声明权限 * <permission android:name="exam2.per1" android:protectionLevel="normal" /> * 使用权限 * <uses-permission android:name="exam2.per1" /> * SS5.取消广播 abortBroadcast() *-描述--S4.广播之间传参: * SS1.上下级广播之间的传参 * setResultData() setResultCode() setResultExtra() setResult() * getResultData() getResultCode() getResultExtra() * SS2.通过Intent传参 intent.putExtra(msg) *-描述--S5.本地广播: * SS1.自定义BroadcastReceiver子类 * SS2.注册接收器,动态或静态 * LocalBroadcastManager.getInstance(this).registerReceiver(接收器,过滤器) * SS3.发送广播 localManager.sendBroadcast(intent); * SS4.取消注册 unregisterReceiver(广播接收器) *-描述--B1.None. *---------------------------------------------------------------------------*/