博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android开发——BroadcastReceiver知识总结
阅读量:4045 次
发布时间:2019-05-24

本文共 2828 字,大约阅读时间需要 9 分钟。

0.  前言

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

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

1.  BroadcastReceive的三种类型

1.1  普通广播

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

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

1.2  有序广播

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

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

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中增加了两个参数,分别是:

intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);//包含已经停止的包intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);//不包含已经停止的包
即自Android3.1开始,系统广播自带FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。详情参考。

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

转载请注明出处为:

你可能感兴趣的文章
关于对象赋值及返回临时对象过程中的构造与析构
查看>>
VS 2005 CRT函数的安全性增强版本
查看>>
SQL 多表联合查询
查看>>
Visual Studio 2010:C++0x新特性
查看>>
drwtsn32.exe和adplus.vbs进行dump文件抓取
查看>>
cppcheck c++静态代码检查
查看>>
在C++中使用Lua
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.147 - LeetCode1108
查看>>
No.174 - LeetCode1305 - 合并两个搜索树
查看>>
No.175 - LeetCode1306
查看>>
No.176 - LeetCode1309
查看>>