什么是Broadcast?
Broadcast,广播,是一种跨进程的消息收发机制。
既然是消息收发,当然存在发送和接收两方。
广播的优点是跨进程。发送方不用关心接收方是谁,只需标注广播的类型,注册对应类型的接收方便可接收。
广播的分类
广播可以按照不同方式进行区分。
根据优先级,分为普通广播和有序广播(之前还有一种粘性广播,在android4.0后被取消,本文不再描述)。
普通广播的接收者,可以看做是并联电路。几乎同时收到广播,没有先后。
有序广播的接收者,按照优先级,从高到低,依次接收,可以看做是串联电路。并且优先级高的接收者,在接收到广播后,可以决定是否继续广播。
根据区域,分为全局广播和本地广播。全局广播是跨进程的,所有进程都能接收到广播。而本地广播,是指仅在同一进程内进行的广播。其它进程接收不到,安全性较高。
广播还可以分为自定义广播和系统广播。
例如,当网络状态发生变化时,android系统会发送action为“android.net.conn.CONNECTIVITY_CHANGE”的系统广播。
用户也可以根据自己的需求,定义自己的广播action。
注册方式
广播接收者跟activity和service类似,都需要注册。但广播的注册分为两种方式,动态注册和静态注册。
动态注册,是在代码中进行注册,因此,仅当程序启动时,才能接收广播。需要注意的是,如果广播的接收者使用动态注册,则需要在必要时,对注册进行注销。
静态注册,则是在Mainfest中进行声明注册。
需要注意的是,本地广播由于只在进程内局部传输,即进程的生命周期内有效,因此只能使用动态注册。
有些系统广播的接收,只能动态注册,静态注册无法接收。例如之前所提到的网络状态监听。
如何发送普通广播
普通的广播发送,需要使用sendBroadcast(Intent)方法。
需要在Intent中指定action名称,可以为自定义,可以为系统。当然,Intent中可以带数据。
Intent intent=new Intent();
intent.setAction("com.breakloop.nfc");
Bundle bundle=new Bundle();
bundle.putString("msg","find card");
intent.putExtras(bundle);
sendBroadcast(intent);
如何发送有序广播
有序广播跟普通广播的发送,唯一不同的是调用方法。
sendOrderedBroadcast(Intent,receiverPermission);
其中第二个参数为String类型,表明接收者所在应用必须拥有对应的权限(Permission,可以自定义)。例如指定“android.permission.INTERNET”。
若无指定,可以设置为null.
Intent intent=new Intent();
intent.setAction("com.breakloop.nfc");
Bundle bundle=new Bundle();
bundle.putString("msg","find card");
intent.putExtras(bundle);
sendOrderedBroadcast(intent,null);
如何发送本地广播
本地广播的发送,以及接收者的注册/注销,都是由LocalBroadcastManager来控制的。
(a)发送本地广播
Intent intent=new Intent();
intent.setAction("com.breakloop.nfc");
Bundle bundle=new Bundle();
bundle.putString("msg","find card");
intent.putExtras(bundle);
LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(this);
localBroadcastManager.sendBroadcast(intent);
(b)注册本地广播接收器
MyReceiver myReceiver=new MyReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.breakloop.nfc");
localBroadcastManager.registerReceiver(myReceiver,intentFilter);
其中MyReceiver 为自定义的广播接收器。
(c)注销本地广播接收器
localBroadcastManager.unregisterReceiver(myReceiver);
如何创建广播接收器
自定义广播接收器,实现BroadcastReceiver接口。该接口只有一个方法
public void onReceive(Context context, Intent intent)
例如
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle=intent.getExtras();
if(bundle==null){
return;
}
Intent newIntent;
if (intent.getAction().equalsIgnoreCase("com.breakloop.nfc")){
newIntent=new Intent(context,MainActivity.class);
}else {
newIntent=new Intent(context,OtherActivity.class);
}
newIntent.putExtras(bundle);
context.startActivity(newIntent);
}
}
如何动态注册广播接收器
MyReceiver myReceiver=new MyReceiver();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("com.breakloop.nfc");
intentFilter.setPriority(Integer.MAX_VALUE);//用于定义优先级,Optional
registerReceiver(myReceiver,intentFilter);
如何注销动态广播接收器
unregisterReceiver(myReceiver);
注:如果仅让处于栈顶端的Activity接收到广播,可以在onResume中注册广播接收器,在onPause中注销。
如何静态注册广播接收器
需要在Mainfest的Application内,注册接收器类名,以及接受的Intentfilter action。
当然,一个接收器可以接收多个广播。例如。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="com.breakloop.nfc.A"/>
<action android:name="com.breakloop.nfc.B"/>
</intent-filter>
</receiver>
如何定义有序广播的优先级
<receiver android:name=".MyReceiver">
<intent-filter android:priority="1000">
<action android:name="com.breakloop.nfc.A"/>
<action android:name="com.breakloop.nfc.B"/>
</intent-filter>
</receiver>
需要在intent-filter中添加android:priority来指定优先级,其中1000为优先级值。该值越大,优先级越高。官方定义优先级最大最小分别为1000和-1000。
但Intentfilter的priority为Integer类型,可以设置为Integer.MAX和Integer.MIN。
如何在接收有序广播后,阻断广播的传播。
在OnReceive方法中调用abortBroadcast(),即可停止广播的继续进行。