当前位置:   article > 正文

Android开发——BroadcastReceiver知识总结_粘性广播废弃

粘性广播废弃

0.  前言

BroadcastReceiver作为Android四大组件之一,像一个全局的监听器一样,是用来监听系统或者应用发出的广播信息,再在其onReceive()中执行相应的逻辑处理。

如可以监听系统的开机广播、电量较少的广播,也可以用来实现自己应用中不同组件之间的通信,如数据库中CURD后发送一个广播,并传递少量的数据,使某个Service中的变量发生改变。当然如果数据的发送量比较大就不建议使用广播接收者来接收了,因为BroadcastReceiver接收数据的开销还是比较大的。转载请注明出处为SEU_Calvin的博客

1.  BroadcastReceive的三种类型

1.1  普通广播

普通广播是完全异步的,而不是有所谓的接收顺序,消息传递的效率也比较高,并且无法中断广播的传播。

  1. Intent intent = new Intent();
  2. intent.setAction("com.seu.calvin.mybroadcastreceiver");
  3. intent.putExtra("data", "hello");
  4. sendBroadcast(intent);

1.2  有序广播

有序广播有所谓的优先级(谷歌文档上表示最大优先级为1000,但是实际上最大的级数是int最大值2147483647),优先级决定了接收顺序,在onReceiver()方法执行时,广播不会传播到下一个接收者,当前的广播接收者可以中断广播的传播,也可以将intent中的数据进行修改。

  1. //发送有序广播
  2. sendOrderedBroadcast(intent, null);
  3. //接收有序广播
  4. public void onReceive(Context arg0, Intent intent) {
  5. //参数为true表示前一个广播没有结果时创建新的Bundle;false表示不创建新的Bundle
  6. Bundle bundle = getResultExtras(true);
  7. bundle.putString("data", "hello again");
  8.   setResultExtras(bundle);
  9.   //终止广播传给下一个广播接收者
  10.   //abortBroadcast();
  11. }

1.3  粘性广播

粘性广播已经被废弃,我们可以通过sendStickyBroadcast()来发送粘性广播。

当粘性广播发送后会滞留在操作系统中,如果有新的符合匹配规则的广播接收者动态注册了(在广播发送之后动态注册),也将会收到这个广播消息。而对于静态注册,效果等同于普通广播。

2.  BroadcastReceive动静态注册的区别

1BroadcastReceiverManifest中静态注册后,应用一经安装,该广播接收者就常驻在系统中了(该广播接收者和应用可以认为已经脱离关系了),无论应用是否处于运行状态都可以接收对应的广播事件

动态注册的广播接收者由registerReceiver开始监听,由unregisterReceiver撤销监听,如果应用退出时没有撤销监听,应用将会报错。显然应用退出后,将不再接收对应的广播事件。

 (2)如果广播接收者是静态注册的,通过intent启动一个activity/service时,若无法匹配不会报错,反之动态注册的话会报错

 (3)如果动静态注册使用的优先级都一样,那么动态注册的广播接收者优先级更高。

3.  BroadcastReceive机制

3.1  广播接收者注册

3.1.1  静态注册

静态广播由PackageManagerService负责,当手机启动或者新安装了应用的时候,PackageManagerService会扫描手机中所有已安装的APP应用,AndroidManifest.xml中有关注册广播的信息解析出来,存储至一个全局静态变量当中。

PackageManagerService扫描目录的顺序如下:system/frameworksystem/app  vendor/appdata/appdrm/app-private,当处于同一目录下时按照file.list()的返回顺序。

因此当然是可以通过PackageManager取消静态注册的,取消后再次启动应用,静态注册就会失效。

 

3.1.2 动态注册

动态广播由ActivityManagerService负责,当代码执行到动态注册广播时进行加载(Binder通信),最后会存储在一个另外的全局静态变量中。

 

3.2  广播发送

广播发送时会通过Binder机制,分别和PackageManagerService以及ActivityManagerService进行广播的发送。后者再查找出符合匹配条件的广播接收者。

 

然后就是广播顺序,如果是普通广播

1)动态广播接收器优先于静态广播接收器;

2)同优先级的静态广播接收器:先扫描到的大于后扫描到的;

3)同优先级的动态广播接收器:先注册的大于后注册的。   

 

如果是有序广播,会将动态广播处理器和静态广播处理器合并在一起处理广播,顺序如下:

1)优先级高的先接收;

2)同优先级,动态优先于静态;

3)同优先级的静态广播接收器:先扫描到的大于后扫描到的;

4)同优先级的动态广播接收器:先注册的大于后注册的。

 

3.3  广播接收者的处理

广播接收者拿到广播后产生一个广播接收者的实例并回调BroadcastReceiver中的onReceive()方法

特别需要注意的是这个实例的生命周期只有10秒,如果10秒内没执行结束onReceiver(),系统将会报错。另外在onReceiver()执行完后,该实例将会被销毁,所以如果要处理耗时任务,不要在onReceiver()中直接创建子线程,而是通过intent调用service处理业务

4.  拓展

静态注册的广播接收器即使app已经退出,依然可以接收到广播的说法,自Android 3.1开始有可能不再成立

因为Android 3.1开始系统在Intent与广播相关的flag中增加了两个参数,分别是:

  1. intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);//包含已经停止的包
  2. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);//不包含已经停止的包

即自Android3.1开始,系统广播自带FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。详情参考Android官方文档

可以考虑使用将Service与App本身设置成不同的进程来在已退出app里接收广播。而自定义广播,自行为Intent添加flag参数即可。

转载请注明出处为:Android开发——BroadcastReceiver知识总结_SEU_Calvin的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/472306
推荐阅读
相关标签
  

闽ICP备14008679号