简介

BroadcastReceiver(广播接收器)是Android四大组件之一,是一个用来响应系统范围内的广播组件,可以从Android系统和其它app发送或接收广播消息,类似于发布 - 订阅设计模式。其特点是异步的,广播发送者不会关心有无接收者接收。可应用于不同组件之间的通信、多线程通信和系统在特定情况下的通信。

原理

对于不同的广播类型,以及不同的BroadcastReceiver注册方式,具体实现上会有不同。但总体流程大致如下:

  1. 广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
  2. 广播发送者通过Binder机制向AMS发送广播;
  3. AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
  4. 消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。

    类型

  • 普通广播(Normal Broadcast)

普通广播是完全异步的,通过Context的sendBroadcast()方法来发送,消息传递效率比较高,但所有receivers(接收器)的执行顺序不确定。缺点是接收器不能将处理结果传递给下一个接收器,并且无法在中途终止广播。

val intent = Intent()
intent.action = RECEIVE_TOKEN
sendBroadcast(intent)
  • 系统广播(System Broadcast)

Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开机启动,充电与电量变化,网络状态改变,拍照,屏幕关闭与开启等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。

  • 有序广播(Ordered Broadcast)

“有序”是针对广播接收者而言的,指的是发送出去的广播被BroadcastReceiver按照先后循序接收,通过receiver的intent-filter中的android:priority属性来设置优先级,优先级从-1000~1000,数越大,优先级越高;priority属性相同者,动态注册的广播优先。其使用过程与普通广播非常类似,差异仅在于广播的发送方式通过Context.sendOrderedBroadcast()方法发送。

  • App应用内广播(Local Broadcast)

Android中的广播可以跨App直接通信,可能会带来消耗性能和容易引起安全性的问题,为了解决这些问题,将全局广播设置成局部广播或者使用封装好的LocalBroadcastManager(只能动态注册)类。
设置局部广播方式:

  • 注册广播时将exported属性设置为false
  • 增设相应权限permission,用于权限验证
  • 指定该广播接收器所在的包名

LocalBroadcastManager使用

//注册广播,在Activity.onResume注册
val intentFilter = IntentFilter()
val broadcastReceiver = BroadcastReceiver()
intentFilter.addAction(RECEIVE_TOKEN)
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter)
//发送广播
val intent = Intent()
intent.action = RECEIVE_TOKEN
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
//取消广播,在Activity.onPause取消
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)

注册

  • 静态注册

直接在Manifest.xml文件的节点中配置,使用< receiver >标签声明,并在标签内用 < intent-filter > 标签设置过滤器,该注册方式不管app是否处于活动状态,都会进行监听。

<receiver android:name=".BroadcastReceiver" // 继承BroadcastReceiver子类的类名android:enabled="boolean"  // 能否接收其他App的发出的广播android:exported="boolean" // 默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为falseandroid:icon="drawable resource" // 广播iconandroid:label="string resource" // 广播标签android:permission="string" // 具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收android:process="string"> // 指定自己的独立进程<intent-filter><action android:name="com.fomin.demo.ACTION_RECEIVE_TOKEN"/></intent-filter>
</receiver>

但需要注意的是,Android8.0系统对静态广播做了变更,具体可查看[https://blog.csdn.net/fomin_zhu/article/details/84454042]

  • 动态注册

直接在代码在代码中调用Context.registerReceiver()方法注册和调用unregisterReceiver
取消注册

override fun onResume() {super.onResume()//注册广播,在Activity.onResume注册val intentFilter = IntentFilter()intentFilter.addAction(RECEIVE_TOKEN)LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter)
}override fun onPause() {super.onPause()//取消广播,在Activity.onPause取消
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)
}

动态广播最好在Activity 的 onResume()注册、onPause()注销,是因为对于动态广播,有注册就必然得有注销,否则会导致内存泄露;在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。

  • 两者区别

    1. 静态注册在Manifest.xml注册,动态在代码上调用
    2. 静态是常驻的,不受生命周期影响,并且耗电和占内存;而动态是使用才注册,跟随组件生命周期

注意

不同注册方式的广播接收器回调OnReceive()中的context返回值是不一样的

  • 静态注册广播,content是android.app.ReceiverRestrictedContext,此context非Activity类型,不可直接用来构造AlertDialog
  • 动态注册广播,传入onReceive()方法里的Context对象context其实就是调用sendBroadcast()的Activty对象;但LocalBroadcastManager方式返回的是Application Context

转载于:https://www.cnblogs.com/fomin/p/10490848.html

Android BrocastReceiver解析相关推荐

  1. Android混淆解析

    此文章转载来源https://www.jianshu.com/p/84114b7feb38点击打开链接 Android混淆解析 一.混淆的目的 一款发布到市场的软件原则上都应该做代码混淆. 通过代码混 ...

  2. Android中解析XML

    Android中解析XML 转载于:https://www.cnblogs.com/zhujiabin/p/5868993.html

  3. android 如何实现无限列表,在Android中解析和创建无限/无限级别的List /子列表中的XML...

    在我的Android Application的服务器端应用程序也由我开发.在这个应用程序Android应用程序从服务器请求一些XML并解析它. XML包含描述应用程序中应该有多少标签的信息,并且每个标 ...

  4. 在linux kernel或android中解析cmdline参数

    文章目录 ★★★ 友情链接 : 个人博客导读首页-点击此处 ★★★ Kernel command line: earlycon androidboot.selinux=permissive uart_ ...

  5. android最大json,Android:解析大型JSON文件

    我正在创建一个Android应用程序,该应用程序应该将Json从文件或网址解析为jsonarray和jsonobjects. 问题是,我的JSON是3.3 MB,当我使用一个简单的代码,如下所示:(现 ...

  6. android XMl 解析神奇xstream 六: 把集合list 转化为 XML文档

    前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xs ...

  7. android XMl 解析神奇xstream 五: 把复杂对象转换成 xml ,并写入SD卡中的xml文件

    前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xs ...

  8. android XMl 解析神奇xstream 四: 将复杂的xml文件解析为对象

    前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xs ...

  9. android XMl 解析神奇xstream 二: 把对象转换成xml

    前言:对xstream不理解的请看:android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 1.Javabeen 代码 packa ...

最新文章

  1. TensorFlow全家桶的落地开花 | 2019 Google开发者日
  2. java ASM 分析类
  3. 题目1027:欧拉回路
  4. 【Leetcode | easy】最长公共前缀
  5. MongoDB数据库(5.mongodb的聚合操作以及mongodb的高级查询2)
  6. 排序算法-01冒泡排序(Python实现)
  7. 2020亚太杯数学建模_比赛 | 2020年APMCM亚太地区大学生数学建模竞赛
  8. [JavaWeb-Bootstrap]Bootstrap概述
  9. memory拷贝与string拷贝的区别
  10. scikit-learn学习之神经网络算法
  11. 微软商业智能和分析平台高歌猛进,一骑绝尘,成为当之无愧BI分析平台的领导者
  12. spring.xml从外部文件引入数据库配置信息
  13. 了解计算机网络拓扑结构,认识计算机网络拓扑结构
  14. Swing 设置无边框Frame
  15. 同一个WiFi,电脑不能访问CSDN网站,手机却可以,换一个网络电脑就可以是什么原因?
  16. 计算机系统思维导图简单画法,思维导图简单画法 有创意的思维导图
  17. 安全测试——SQL注入
  18. 交换机配置--进入web页面
  19. 人脸识别在线上金融业务中的应用风险
  20. 怎么解除Word文档限制编辑?比较方便的两种办法

热门文章

  1. WP7 APP 猜数字 V2.0 更新
  2. rancher2.0安装mysql_高可用rancher集群搭建
  3. struts2之单个文件上传
  4. 深入Mysql,SqlServer,Oracle主键自动增长的设置详解
  5. Home界面的ListView
  6. Android Broadcast编写的音乐播放器
  7. 汇编语言--CPU对存储器的读写
  8. linux命令nohup
  9. Linux下如何让自己的程序在开机时自动启动
  10. 用时间戳判断两个时间是否在同一天和时区转换问题