1、常见分类
    BroadCastReceiver,按注册方式可以分为静态广播接收器和动态广播接收器。
    静态广播接收器:不受程序是否启动的约束,当应用程序关闭之后,还是可以接收到广播(一般广播接收器的生命周期是和当前活动的生命周期保持同步)。
    动态广播接收器:可以自由的控制注册和取消,有很大的灵活性。但是只能在程序启动之后才能收到广播。

对于广播(Broadcast),则可以分为普通广播和有序广播。
    其中普通广播不在意顺序,各进程的广播接收器基本上可以同时收到这个广播。而有序广播,系统会根据接收者声明的优先级按顺序逐个接收处理,先收到有序广播的接收器,可以对该有序广播进行修改或者截断。
    静态注册的广播接收器,在接收广播时,系统自动按有序广播的方式来串行处理(原因是进程的创建不能并发),此类接收器收到广播的先后顺序,和接收器所在package名称有关,或者说,和PMS扫描顺序有关。
    动态注册的广播接收器,如果接收普通广播,接收器收到广播的顺序则和注册顺序有关。在所有普通广播里面,动态注册的广播接收器,相对于静态注册的广播接收器,会优先收到普通广播。

同优先级的动态有序广播,注册顺序影响广播的接收顺序;同优先级的静态有序广播,扫描顺序影响其接收顺序。
除了前面提到的这些,还有一种相对不太常用的:LocalBroadcastManager方式注册的应用内广播接收器,只能通过LocalBroadcastManager动态注册。

2、注册过程简述
    动态注册的广播接收器,主要通过ContextImpl、LoadedApk,再调用AMS的registerReceiver方法完成。
静态注册的广播接收器,是在系统启动时,由PMS解析apk文件并记录receivers信息,然后AMS调用PMS的接口来查询intent匹配信息,再完成广播注册过程。

3、发送和接收过程简述
    发送广播,主要通过ContextImpl、LoadedApk、AMS、ActivityThread完成。接收广播时,先是在AMS里面处理,找到接收者然后加到一个队列,再向对应的线程发送广播消息。

从Android O开始,系统对静态注册的广播接收器添加了限制,必须指定广播接收器所在包名才可以发送,或者使用Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND这个flag,但该标志是隐藏的,如果必须使用静态广播接收器、又不能指定包名(例如发送一对多的广播),则可以使用该标志的具体数值0x01000000。

4、安全性
    可以使用权限提升广播接收的安全性。如果接收器定义了权限,发送的广播需要对应声明权限才能发送;反之一样,不然收不到。整体上,有以下几种情况:

  • 指定发送方,发送者有权限才能发此广播;
  • 指定接收方,接收者声明权限才能收到该广播;
  • 同时指定发送方和接收方(很少使用)。

无论是哪种情况,都涉及到自定义权限,所以都需要在AndroidManifest.xml中声明对应的权限。
    对于第一种情况(接收器定义权限来限制发送方),如果是动态广播接收器,可以在注册时通过registerReceiver传入该权限。静态广播接收器则是在AndroidManifest.xml里面,定义广播接收器的地方,添加android:permission属性,将该属性设为自定义权限。

5、 onReceive()中的Context入参
    这里的入参为context变量,其实例的具体类型,可以分为下面几种情况。
    1)、静态注册的广播接收器
    这种情况下,入参是android.app.ReceiverRestrictedContext类型,不能用来启动Activity、弹出AlertDialog(除了系统应用且Dialog类型是SYSTEM_ALERT_WINDOW类型)。

2)、动态注册的广播接收器
    具体又分两种情况:
    a) 在Activity里面注册广播接收器。此时onReceive的入参context就是注册广播接收器的Activty对象。
由于此时入参contex为Activity的Context对象,可用于启动Activity、弹出AlertDialog。
但考虑到onReceive()方法在主线程中,该方法需要在10秒内执行完毕,生命周期很短。如果弹出的对话框需要等待用户响应,就需要考虑对话框的管理问题。常用的做法是,将其放在Service里面管理,在Service启动的时候注册一个动态广播接收器,Service停止的时候注销之。
    b) 在Service里面注册广播接收器。此时onReceive的入参context对应该Service对象,和Service是否跨进程无关。这种情况下的Context不能启动Activity,有若干限制。
这两种情况可以统一为,onReceive的入参context就是调用registerReceiver的组件的Context。

其他还有LocalBroadcastManager注册的应用内广播接收器。其onReceive中的context是Application的Context。

(相关完整且成体系的文章,可参见本人原创的开源电子书《Android系统与性能优化》,地址:https://github.com/carylake/androidnotes)

最新文章

  1. 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序
  2. Jquery揭秘系列:谈谈bind,one,live,delegate事件及实现
  3. 【HOW】如何允许编辑用户配置文件属性
  4. Linux SAMBA Practical
  5. js for 循环中的 变量问题。
  6. Lintcode: Product of Array Exclude Itself
  7. P235 实战练习(集合类2)、摇奖程序和验证码(修改版)
  8. EventBus学习
  9. android 解释dp,px,pt,sp单位
  10. Strust2最基本使用
  11. BCM wifi分析
  12. Go语言Web框架gwk介绍 3
  13. nginx反向代理cas-server之2:生成证书,centOS下使用openssl生成CA证书(根证书、server证书、client证书)
  14. 一条sql执行过长的时间,你如何优化,从哪些方面?
  15. php之sphinx
  16. ajax参数传递之[HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]请求
  17. node连接myslq
  18. Xcode - 打开工程,提示No Scheme解决
  19. posix_memalign详细解释(转)——自定义对齐大小的内存分配函数
  20. 外部引用CSS中 link与@import的区别

热门文章

  1. 【黑客基础】Windows PowerShell 脚本学习(上)
  2. OSI案例详解+ARP+DNS
  3. OC循环方法推荐-块循环遍历(比for循环好用)
  4. Python中的Tcp协议的应用之Tcp服务端程序开发
  5. 转:关于java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication的解决
  6. JavaEE基础(02):Servlet核心API用法详解
  7. 【如何让代码变“高级”(二)】-这样操作值得一波666(Java Stream)(这么有趣)
  8. Cisco 7200 路由 PPPOE 拨号详解
  9. CNN卷积神经网络的构建
  10. 获取iOS设备的型号