普通广播(Normal Broadcast)
普通广播对于多个接收者来说是完全异步的,通常每个接收者都无需等待即可以接收到广播,接收者相互之间不会有影响。对于这种广播,接收者无法终止广播,即无法阻止其他接收者的接收动作。
为了验证以上论断,我们新建三个BroadcastReceiver,演示一下这个过程,FirstReceiver、SecondReceiver和ThirdReceiver的代码如下:
- package com.scott.receiver;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.util.Log;
- public class FirstReceiver extends BroadcastReceiver {
- private static final String TAG = "NormalBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = intent.getStringExtra("msg");
- Log.i(TAG, "FirstReceiver: " + msg);
- }
- }
- public class SecondReceiver extends BroadcastReceiver {
- private static final String TAG = "NormalBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = intent.getStringExtra("msg");
- Log.i(TAG, "SecondReceiver: " + msg);
- }
- }
- public class ThirdReceiver extends BroadcastReceiver {
- private static final String TAG = "NormalBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = intent.getStringExtra("msg");
- Log.i(TAG, "ThirdReceiver: " + msg);
- }
- }
看来这三个接收者都接收到这条广播了,我们稍微修改一下三个接收者,在onReceive方法的最后一行添加以下代码,试图终止广播:
- abortBroadcast();
有序广播(Ordered Broadcast)
有序广播比较特殊,它每次只发送到优先级较高的接收者那里,然后由优先级高的接受者再传播到优先级低的接收者那里,优先级高的接收者有能力终止这个广播。
为了演示有序广播的流程,我们修改一下上面三个接收者的代码,如下:
- package com.scott.receiver;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- public class FirstReceiver extends BroadcastReceiver {
- private static final String TAG = "OrderedBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = intent.getStringExtra("msg");
- Log.i(TAG, "FirstReceiver: " + msg);
- Bundle bundle = new Bundle();
- bundle.putString("msg", msg + "@FirstReceiver");
- setResultExtras(bundle);
- }
- }
- public class SecondReceiver extends BroadcastReceiver {
- private static final String TAG = "OrderedBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = getResultExtras(true).getString("msg");
- Log.i(TAG, "SecondReceiver: " + msg);
- Bundle bundle = new Bundle();
- bundle.putString("msg", msg + "@SecondReceiver");
- setResultExtras(bundle);
- }
- }
- public class ThirdReceiver extends BroadcastReceiver {
- private static final String TAG = "OrderedBroadcast";
- @Override
- public void onReceive(Context context, Intent intent) {
- String msg = getResultExtras(true).getString("msg");
- Log.i(TAG, "ThirdReceiver: " + msg);
- }
- }
代码改完之后,我们需要为三个接收者注册广播地址,我们修改一下AndroidMainfest.xml文件:
- <receiver android:name=".FirstReceiver">
- <intent-filter android:priority="1000">
- <action android:name="android.intent.action.MY_BROADCAST"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
- <receiver android:name=".SecondReceiver">
- <intent-filter android:priority="999">
- <action android:name="android.intent.action.MY_BROADCAST"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
- <receiver android:name=".ThirdReceiver">
- <intent-filter android:priority="998">
- <action android:name="android.intent.action.MY_BROADCAST"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
现在,我们需要修改一下发送广播的代码,如下:
- public void send(View view) {
- Intent intent = new Intent("android.intent.action.MY_BROADCAST");
- intent.putExtra("msg", "hello receiver.");
- sendOrderedBroadcast(intent, "scott.permission.MY_BROADCAST_PERMISSION");
- }
所以我们在AndroidMainfest.xml中定义一个权限:
- <permission android:protectionLevel="normal"
- android:name="scott.permission.MY_BROADCAST_PERMISSION" />
- <uses-permission android:name="scott.permission.MY_BROADCAST_PERMISSION" />
关于这部分如果有不明白的地方可以参考我之前写过的一篇文章:Android声明和使用权限
然后我们点击发送按钮发送一条广播,控制台打印如下:
我们看到接收是按照顺序的,第一个和第二个都在结果集中加入了自己的标记,并且向优先级低的接收者传递下去。
既然是顺序传递,试着终止这种传递,看一看效果如何,我们修改FirstReceiver的代码,在onReceive的最后一行添加以下代码:
- abortBroadcast();
此次,只有第一个接收者执行了,其它两个都没能执行,因为广播被第一个接收者终止了。
上面就是BroadcastReceiver的介绍,下面我将会举几个常见的例子加深一下大家对广播的理解和应用:
1.开机启动服务
我们经常会有这样的应用场合,比如消息推送服务,需要实现开机启动的功能。要实现这个功能,我们就可以订阅系统“启动完成”这条广播,接收到这条广播后我们就可以启动自己的服务了。我们来看一下BootCompleteReceiver和MsgPushService的具体实现:
- package com.scott.receiver;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.util.Log;
- public class BootCompleteReceiver extends BroadcastReceiver {
- private static final String TAG = "BootCompleteReceiver";
- @Override
- public void onReceive(Context context, Intent intent) {
- Intent service = new Intent(context, MsgPushService.class);
- context.startService(service);
- Log.i(TAG, "Boot Complete. Starting MsgPushService...");
- }
- }
- package com.scott.receiver;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- import android.util.Log;
- public class MsgPushService extends Service {
- private static final String TAG = "MsgPushService";
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG, "onCreate called.");
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.i(TAG, "onStartCommand called.");
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public IBinder onBind(Intent arg0) {
- return null;
- }
- }
- <!-- 开机广播接受者 -->
- <receiver android:name=".BootCompleteReceiver">
- <intent-filter>
- <!-- 注册开机广播地址-->
- <action android:name="android.intent.action.BOOT_COMPLETED"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </receiver>
- <!-- 消息推送服务 -->
- <service android:name=".MsgPushService"/>
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
如果我们查看已运行的服务就会发现,MsgPushService已经运行起来了。