Android 四大组件之 BroadCastReceiver
BroadCastReceiver是一种全局的监听器。用于监听系统全局的广播消息。由于他是一种全局的监听器,所以他可以轻松实现,系统中不同组件之间的通信。
1.创建BroadCastReceiver
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 当监听到广播消息时,执行这个方法。 String content=intent.getStringExtra("content"); Toast.makeText(context, "你发送的是:"+content, Toast.LENGTH_SHORT).show(); } }
BroadCastReceiver接收到广播,就会执行onReceive方法。可以使用Intent接收数据信息。
2.注册BroadCastReceiver
(1)静态注册
静态注册,就是在AndroidManifest.xml文件中,注册BroadCastReceiver。
<receiver android:name=".MyReceiver"> <intent-filter> <action android:name="com.example.MY_LISTENER"></action> </intent-filter> </receiver>
(2)动态注册
动态注册,就是在代码中注册BroadCastReceiver, 如果使用动态注册,可以在Activity的onResume()中注册,onPause中注销,或者在onCreate()中注册,onDestory注销。
//实例化广播接收器 MyReceiver myReceiver = new MyReceiver(); //过滤广播,这里“com.example.MY_LISTENER”是我自定义的,可以随便写,广播时候保持一致就可以 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.MY_LISTENER"); //注册广播 registerReceiver(myReceiver, intentFilter); //注销广播 //unregisterReceiver(myReceiver)
关于registerReceiver方法有两种重载。
第一种:registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
第一个参数:负责接收广播的BroadcastReceiver(广播接收器);
第二个参数:是意图过滤器;
第二种:registerReceiver(receiver, filter, broadcastPermission, scheduler)
第一个参数:负责接收广播的BroadcastReceiver(广播接收器);
第二个参数:意图过滤器(哪些广播可以被这个接收器接收);
第三个参数:广播权限;
第四个参数:Hander;
(3)关于“静态注册”和“动态注册”的区别!
当静态注册一个BroadcastReceiver时,不论应用程序启动与否,都可以接收对应的的广播。
动态注册的时候,如果不执行unregisterReceiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。
(4)注意:权限重复现象
如果AndroidManifest.xml(功能清单文件)里注册了权限,在该方法再注册,则 receiver 无法收到广播;
如果AndroidManifest.xml(功能清单文件)里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候, receiver能收到广播。
3.广播的类型与发送
普通广播:对于Receiver(接收者)来说,普通广播是完全异步的,可以在同一时刻被所有Receiver(接收者)接收到,消息传递速度表较快。
发送广播:
button_start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //发送广播依然需要使用Intent Intent intent = new Intent(); //这个Action是我们在AndroidManifest.xml中为Receiver配置的 intent.setAction("com.example.MY_LISTENER"); //给Receiver传入参数 intent.putExtra("content", "Hello Receiver"); //发送广播 sendBroadcast(intent); } });
接收广播:
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 当监听到广播消息时,执行这个方法。 String content=intent.getStringExtra("content"); Toast.makeText(context, "你发送的是:"+content, Toast.LENGTH_SHORT).show(); } }
有序广播:通过给Receiver(接收者)指定优先级,系统会安排优先级高的Receiver接收广播,然后优先级高的Receiver再把广播传播到优先级较低的Receiver中。可以在优先级高的Receiver中使用abortBroadcast(),终止广播的传递,这样就不会被优先级较低Receiver接收到。
不仅如此,也可以在优先级高的Receiver中,把处理的结果及相关信息,通过setResultExtras(Bundle)方法,传递到下一个Receiver中(使用getResultExtras(true)接收上一个接收者存入的数据)。
注意:当具有相同优先级的Receiver,系统执行哪个Receiver是随机的。如果都没有指定优先级,动态注册(代码注册)的最先收到广播。
指定Receiver的优先级
(1)在AndroidManifest.xml文件中,通过 android:priority=""来指定优先级。
<receiver android:name=".MyReceiver"> <intent-filter android:priority="10"> <action android:name="com.example.MY_LISTENER"></action> </intent-filter> </receiver>
(2)通过 IntentFilter 的setPriority() 指定。
注意:优先级的范围 -1000~1000
例:
定义三个接收者
MyReceiver1
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 把接收到的num,乘以10。
int num = intent.getIntExtra("num", 0);
num = num * 10;
Bundle b = new Bundle();
b.putInt("num", num);
//把处理结果传递给下一个接收者
setResultExtras(b);
Toast.makeText(context, "1,接收到的是:" + String.valueOf(num),
Toast.LENGTH_SHORT).show();
}
}
MyReceiver2
public class MyReceiver2 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 把接收到的num,乘以10。
int num = getResultExtras(true).getInt("num");
num = num * 10;
Bundle b = new Bundle();
b.putInt("num", num);
//把处理结果传递给下一个接收者
setResultExtras(b);
Toast.makeText(context, "2,接收到的是:" + String.valueOf(num),
Toast.LENGTH_SHORT).show();
//终止广播向下一个接收者传递。
//abortBroadcast();
}
}
MyReceiver3
public class MyReceiver3 extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 把接收到的num,乘以10。
int num = getResultExtras(true).getInt("num");
num = num * 10;
Toast.makeText(context, "3,接收到的是:" + String.valueOf(num),
Toast.LENGTH_SHORT).show();
}
}
发送有序广播:
button_start = (Button) findViewById(R.id.button1);
button_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.example.MY_LISTENER");
//给第一个Receiver传入参数
intent.putExtra("num",1);
//发送广播,注意:这里使用的是sendOrderedBroadcast
sendOrderedBroadcast(intent, null);
}
});
这里使用了sendOrderedBroadcast()发送有序广播,该方法有两个参数,第一个参数是Intent。第二个参数是权限,如果给广播指定权限,那么只有具备该权限的Receiver,才能接收到。
4生命周期
BroadCastReceiver的生命周期非常简短:接收到广播→onReceive()→结束;
所以在onReceive方法中,不要执行耗时的任务,如果该方法执行时间超过10秒,Android就会认为该程序无响应,并弹出ANR的对话框。如果必须执行耗时任务可以考虑,在onReceive中开启服务来执行,但不要使用线程,因为BroadCastReceiver的生命周期很短,可能出现子线程还没有结束,BroadCastReceiver就已经退出了。
如果当BroadCastReceiver所在的进程结束,虽然该进程中可能有用户启动的新线程,但是由于该进程内没有活动的组件,系统会在内存紧张的时候,优先结束掉该进程,这就会导致BroadCastReceiver启动的子线程不能执行完。
提示:我们还可以监听系统广播。例如系统的“启动完成”广播,我可以实现开机启动项。网络变化等等。
特殊的BroadcastReceiver
LocalBroadcastManager本地广播
Sticky Broadcast粘性广播
OrderedBroadcastReceiver有序广播
StickyOrderedBroadcast粘性有序广播
相关资料:
http://www.cnblogs.com/trinea/archive/2012/11/09/2763182.html
http://yangguangfu.iteye.com/blog/1063732