Android 初步之Android组件 BroadcastReceiver
BroadCast Receiver是啥
Broadcast Receiver是用于接收广播通知的组件。广播是一种同时通知多个对象的事件通知机制。
Android中的广播来源于系统事件,例如按下拍照键,电池电量低,安装新应用等。还有普通应用程序。如启动特定线程,文件下载完毕等。
广播接收器通常初始化独立的组件或者在onReceiver方法中发送通知给用户,如果广播接收器需要完成更加耗时的任务,应该启动一个服务而不是一个线程,因为不活跃的广播接收器可能被系统停止。
BroadCast Receiver分类
- 普通广播
sendBroadcast()这个方法的广播能够按照注册的先后顺序发送给所有广播接收者,如果设置了广播接收者的优先级,优先级如果恰好与注册顺序相同,则不会有任何问题,如果顺序不一样,会出leaked IntentReceiver 这样的异常,并且在前面的广播接收者不能调用abortBroadcast()方法将其终止,如果调用会出BroadcastReceiver trying to return result during a non-ordered broadcast的异常,先接收到广播的receiver可以修改广播数据。 - 有序广播
sendOrderedBroadcast()方法priority的属性能起作用,并且在队列前面的receiver可以随时终止广播的发送。还有这个api能指定final的receiver,这个receiver是最后一个接收广播时间的receiver,并且一定会接收到广播事件,是不能被前面的receiver拦截的。这个特性可以用来统计系统中能监听某种广播的Receiver的数目。 - 粘性的广播
sendStickyBroadcast()字面意思是发送粘性的广播,使用这个api需要权限android.Manifest.permission.BROADCAST_STICKY,粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,超过10秒的时候系统会将这个广播置为可以被销毁的候选,一旦系统资源不够的时候,就会撤销这个广播。
使用BroadCast Receiver 监听广播
要让BroadCast Receiver 监听广播需要完成如下操作:
- 在代码中进行动态注册广播,或者在Manifest 清单文件中静态注册
二者的对比如下: - 使用意图过滤器Intent Filter 来指定它要监听的BroadCast Intent
- 创建新的BroadCast Receiver 重写onReceive方法,在接收到一个通过Intent Filter 过滤后的BroadCast Intent,就会执行onReceive方法,在onReceive方法中可以更新内容,启动Service,更新UI或者使用Notification Manager来通知用户。BroadCast 也运行在主线程中,因此主要的处理工作不能在BroadCast Receiver中直接完成
动态注册广播
- 动态注册:
IntentFilter intentFilter = new IntentFilter(Constant.ACTION_NAME);
broadCast = new EchoBroadCast();
registerReceiver(broadCast, intentFilter); - 取消注册:
unregisterReceiver(broadCast);
- 发送广播:
Intent intent = new Intent(Constant.ACTION_NAME);
Bundle b = new Bundle();
b.putString("Message", "This is The Message From MainActivity!");
intent.putExtras(b);
sendBroadcast(intent); - 服务类的编写:
public class EchoBroadCast extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String ACTION = intent.getAction();
if(ACTION.equals(Constant.ACTION_NAME)){
Log.i(Constant.TAG_NAME, intent.getExtras().getString("Message"));
}
}
}静态注册BroadCast Receiver
<receiver android:name="com.example.testbroadcastreceiverregiststatic.EchoBroadCast" >
<intent-filter>
<action android:name="com.example.testbroadcastreceiverregiststatic.ACTION" />
</intent-filter>
</receiver>
OrderedBroadCast
当发送有序广播的时候,Intent将会按照优先级顺序被传递给所有具有合适权限的已经注册的接收器,优先级越大越先接收到。
启动广播代码:
sendOrderedBroadcast(intent, null); |
广播中的重要方法:
setResultExtras(b); // 优先接收到Broadcast的接收者可以通过setResultExtras(Bundle)方法将处理结果存入Broadcast中,然后传给下一个接收者 |
Bundle b = getResultExtras(true); |
abortBroadcast();// 终止广播 |
清单文件中注册:
<receiver android:name="com.example.testbroadcastordered.FirstReceiver"> |
第一个广播代码:
public void onReceive(Context context, Intent intent) { |
其他广播代码:
public void onReceive(Context context, Intent intent) { |
最后一个广播代码:
public void onReceive(Context context, Intent intent) { |
StickyBroadCast
Sticky Intent 可以保存它们最后一次广播的值,并且当有一个新的接收者,被注册为接收该广播的时候,它们会把这些值作为Intent返回,当调用regesterReceiver来指定一个匹配的Sticky BroadCast Intent 的intentFilter 时,返回值将是最后一次Intent广播。
要广播自己的Sticky,必须拥有BROADCAST_STICKY用户权限,不是必须指定一个接收器来获取Sticky Intent的当前值。
注册:
IntentFilter filter = new IntentFilter("com.example.testbroadcaststicky.ACTION"); |
发送:
intent = new Intent("com.example.testbroadcaststicky.ACTION"); |
移除:
removeStickyBroadcast(intent); |
设置权限:
android.permission.BROADCAST_STICKY |
public void onClick(View v) { |
从上面截图可以看出在发送10次Intent后最后一个intent数值为9,下一次注册StickyBroadCast的时候接收到的是上一次的最后一个Intent,数值为9,如果再发送一次值为88888888的Intent,这时候最后一个Intent的值为88888888,如果再次注册,返回的是88888888
广播接受者实现过程需要注意的点
- 广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁。
- 广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框。
- 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉。
- 耗时的较长的工作最好放在服务中完成。