安卓广播机制初探

上一篇 / 下一篇  2015-11-23 11:29:49 / 个人分类:安卓开发

安卓的广播机制就是这么个事儿:系统通过intent去发送事件,具体的apk注册自己的广播接收器BroadcastReceiver去监听广播,一旦收到 广播就用对应的方式在onrecevier方法中去处理或者不处理它:

例子:自定义广播接收器BroadcastReceiver:
public class MyBR extends BroadcastReceiver{

public MyBR(){
System.out.println('自定义了一个由registerReceiver()注册的广播接收器')
}
@override
//onReceive方法中做具体的操作
public void onReceive(Context context, Intent intent){
String action =intent.getAction();
System.out.println('MyBR收到了一个'+action+'消息');
if (isOrderedBroadcast()){
System.out.println('这是一个有序广播,被我拦截');
this.abortBroadcast();
}else{
System.out.println("这不是一个有序广播");
}

Bundle bundle = intent.getExtras();//定义了一个bundle对象去接收intent中的键值对数据
if (bundle != null) {
System.out.println("该消息携带的数据如下:");

Set set=bundle.keySet(); //定义了一个set去去的bundle的值
Iterator iterator = set.iterator();//迭代器出现了这就是为什么有了bundle还用set封装,set才有迭代器的属性
while (iterator.hasNext()) { // 取得集合中的一个内容
 
String str = (String) iterator.next();// 依次取得Bundle中的内容
 
System.out.println(str + "--->" + bundle.get(str)); //打印
 
}
}esle {
System.out.println("该消息没有携带数据");
}
Toast toast = Toast.makeText(context, "MyBroadcastReceiver4收到了一个"+ action + "消息", 

Toast.LENGTH_LONG);
 
toast.show(); //将这个消息截获(从消息容器移除)这样其他处理器就没法接收到这个消息
 
this.abortBroadcast();
}}


安卓广播的分类:
1.普通广播:所有注册的广播接收器都可以接收:
Intent intent = new Intent();  intent.setAction("asdfasdf");
Android_09_10Activity.this.sendBroadcast(intent);

2.有序广播:这种广播在处理器端的处理顺序是按照广播接收器的不同优先级来区分的,高优先级的处广播接收器会优先处理这个消息,并且可以将这个消息截获删除:
Intent intent = new Intent();
intent.setAction("asdfasdf"); Android_09_10Activity.this.sendOrderedBroadcast(intent,null);

3.粘性消息:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态。
Intent intent = new Intent();
intent.setAction("qwerqwer");  Android_09_10Activity.this.sendStickyBroadcast(intent);

注意:普通广播和粘性消息不同被截获,而有序广播是可以被截获的


广播接收器BroadcastReceiver有两种注册方式:

1.在代码中以函数的方式动态注册,记住这样做就必要代码去销毁之:
IntentFilter intentFilter=new IntentFilter('fqvfgwqevgwq');
intentFilter .setPriority(0);
Activity.this.registerReceiver(receiver,intentFilter);//用注册函数把注册的intent过滤器扔到recevier上即可
销毁注册的接收器:
Activity.this.unregisterReceiver(receiver,intentFilter)

2.在manifest文件中注册,有个缺点是,一旦注册永久存在,好处是比在代码中注册优先级高


BroadcastReceiver的生命周期:
very 简单的,就是调用它,实现onReceive(),然后就被销毁,下次要用,下次再按这个顺序来一遍


BroadcastReceiver是如何判断,刷选广播的呢?
首先在mainfest中,每一个广播接收类,都有这一行代码:
<receiver android:name='.myBroadcast'>
  <intent-filter>
      <action android:name='com.broadcast.test'></action>
  </intent-filter>
</receiver>

intent-filter就定义了这个广播接收器对象接收什么样的消息,就是要intent-filter里面定义的action中的动作,比如上面代码就是我们自己定义的一个动作,除此而外,安卓自己还有很多动作,如: ACTION_VIEW,ACTION_EDIT,这个后面说intent,会再弄个文章细说,暂且不表 不管是系统的动作还是自定义的动作Action,之后的处理都是在onReceive()中,通过intent.getAction()方法判断传进的动作去做不同的处理即可


小结:
在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
使用广播必须要有一个intent 对象必设置其action动作对象
使用广播必须在配置文件中显式的指明该广播对象
每次接收广播都会重新生成一个接收广播的对象
在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理
如果在AndroidManifest.xml中注册,当应用程序关闭的时候,也会接收到广播。在应用程序中注册就不产生这种情况了。


测试中经常遇到keyinputdispatch引发的anr,之后也经常看到很broadcast的anr,这里有个解释,大概看看:
在安卓中,程序的响应被活动管理器Activity Manager和窗口管理器Window Manager 两个系统服务监视,如果BroadcastReceiver 在 10 秒内没有执行完毕,安卓就认为该程序无响应,所以在BroadcastReceiver 中不要放一些耗时的操作,如果需要完成一项比较耗时的工作,应该通过发送Intent 给 Service ,由 Service 来完成。而不是使用子线程的方法来解决,因为 BroadcastReceiver 的生命周期很短(在 onReceive() 执行后 BroadcastReceiver 的实例就会被销毁),子线程可能还没有结束BroadcastReceiver 就先结束了。如果BroadcastReceiver 结束了,它的宿主进程还在运行,那么子线程还会继续执行。但宿主进程此时很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。 


使用广播消息的例子:
1.一个经典的电话黑名单,首先通过将黑名单号码保存在数据库里面,当来电时,我们接收到来电广播并将黑名单号码与数据库中的某个数据做匹配,如果匹配的话则做出相应的处理,比如挂掉电话、比如静音等等。
2.电池监控程序,batterymonitor,其实原理就是去监听系统电池广播,然后做了加工,叫你看到每分钟电量的变化









TAG:

 

评分:0

我来说两句

Open Toolbar