目录
一.概述
二.注册广播
三.发送广播
四.处理广播
五.广播的优先级
一、概述
广播(Broadcast)机制用于进程/线程间通信,因此在我们应用程序内发出的广播,其他的应用程序应该也是可以收到的。广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。
BroadcastReceiver分为两类:
- 静态广播接收者:通过AndroidManifest.xml的标签来申明的BroadcastReceiver。
- 动态广播接收者:通过AMS.registerReceiver()方式注册的BroadcastReceiver,动态注册更为灵活,可在不需要时通过unregisterReceiver()取消注册。
从广播发送方式可分为三类:
- 普通广播:通过Context.sendBroadcast()发送,可并行处理
- 有序广播:通过Context.sendOrderedBroadcast()发送,串行处理
- Sticky广播:通过Context.sendStickyBroadcast()发送
二.注册广播
1.静态注册广播
常驻型广播,这个广播接收者会在程序运行的整个过程中一直存在,不会被注销掉,当程序被杀掉后不会再接收到广播了。它的注册方式就是在你应用程序的AndroidManifast.xml 中进行注册,这种注册方式通常又被称作静态注册。这种方式可以理解为通过清单文件注册的广播是交给操作系统去处理的。在Manifest.xml中注册广播,是一种比较推荐的方法,因为它不需要手动注销广播(如果广播未注销,程序退出时可能会出错)。
<receiver android:name=".receiver.WakeReceiver">
<intent-filter>
<!-- 利用系统广播拉活-->
<action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- Android开机广播-->
<!-- 系统广播,接收打电话的广播 ,这个需要配置权限 -->
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.USER_PRESENT" /><!--锁屏解锁-->
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><!--网络变化-->
<action android:name="com.wake.gray" /><!-- 自定义广播 -->
</intent-filter>
</receiver>
2.动态注册广播
动态注册广播不是常驻型广播,也就是说广播跟随程序的生命周期
步骤如下:
实例化自定义的广播接收者
实例化意图过滤器,并设置要过滤的广播类型(如,我们接收收到短信系统发出的广播)
使用Context的registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)方法注册广播
public static final String BROADCAST_ACTION = "com.example.corn";
private BroadcastReceiver mBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BROADCAST_ACTION);
registerReceiver(mBroadcastReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mBroadcastReceiver);
}
3.两种注册广播的区别
第一种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行,比如静态注册实现开机启动
第二种不是常驻型广播,也就是说广播跟随程序的生命周期。
动态注册的广播的优先级高于静态注册的广播
三.发送广播
根据广播的发送方式,可以将其分为以下几种类型:
Normal Broadcast:普通广播
Ordered broadcast:有序广播
Sticky Broadcast:粘性广播(在 android 5.0/api 21中deprecated,不再推荐使用,相应的还有粘性有序广播,同样已经deprecated)
1.普通广播
普通广播(Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的
Context类提供两个方法可以用于发送普通广播:
sendBroadcast(Intent intent);
sendBroadcast(Intent intent, String receiverPermission);
差别是第二个设置权限。
发给特定的用户:
sendBroadcastAsUser(Intent intent, UserHandle user);
sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission);
2.有序广播
有序广播(Ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了,只是其的主要发送方式变为:sendOrderedBroadcast(intent, receiverPermission, ...)。
1>多个具当前已经注册且有效的BroadcastReceiver接收有序广播时,是按照先后顺序接收的,先后顺序判定标准遵循为:将当前系统中所有有效的动态注册和静态注册的BroadcastReceiver按照priority属性值从大到小排序,对于具有相同的priority的动态广播和静态广播,动态广播会排在前面。
2>先接收的BroadcastReceiver可以对此有序广播进行截断,使后面的BroadcastReceiver不再接收到此广播,也可以对广播进行修改,使后面的BroadcastReceiver接收到广播后解析得到错误的参数值。当然,一般情况下,不建议对有序广播进行此类操作,尤其是针对系统中的有序广播。
五.App应用内广播(Local Broadcast)
我们发送和接收的广播全部都是属于系统全局广播,即发出的广播可以被其他任何的任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易会引起安全性的问题,比如说我们发送的一些携带关键性数据的广播有可能被其他的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播。为了能够简单地解决广播的安全性问题,Android 引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,这样所有的安全性问题就都不存在了。
1.使用它发送的广播将只在自身App内传播,因此你不必担心泄漏隐私数据
2.其它App无法对你的App发送该广播,因为你的App根本就不可能接收到非自身应用发送的该广播,因此你不必担心有安全漏洞可以利用
3.比系统的全局广播更加高效
/registerReceiver(mBroadcastReceiver, intentFilter);
//注册应用内广播接收器
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
intent.putExtra("name", "qqyumidi");
//sendBroadcast(intent);
//发送应用内广播
localBroadcastManager.sendBroadcast(intent);
注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(静态注册或其他方式动态注册的ContextReceiver是接收不到的)。
六.广播的优先级
有序广播的接收者按照一定的优先级进行消息的接收。如:A,B,C的优先级依次降低,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。
另外Ordered broadcasts的接收者可以通过abortBroadcast()的方式取消广播的传播,也可以通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。例如:
<receiver
android:name=".FirstReceiver">
<intent-filter
android:priority="999">
<action android:name="com.mark.broadcast.receiver" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".MyReceiver" >
<intent-filter
android:priority="1000">
<action android:name="com.mark.broadcast.receiver" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
如上两个receiver我们分别设置为priority为999,和1000,及时MyReceiver是后注册的,但是其优先级比FirstReceiver高,则MyReceiver会先处理广播。