首页 > 技术文章 > 安卓 BroadcastReceiver笔记

zhen-android 2017-04-24 01:58 原文

安卓广播相关概念

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.
 *---------------------------------------------------------------------------*/
View Code

 

推荐阅读