简介

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,否则为false
android:icon="drawable resource" // 广播icon
android: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

Android BrocastReceiver解析的更多相关文章

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

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

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

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

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

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

  4. android XMl 解析神奇xstream 三: 把复杂对象转换成 xml

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

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

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

  6. Android动画解析--XML

    动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...

  7. android 中解析XML的方法(转)

    在XML解析和使用原始XML资源中都涉及过对XML的解析,之前使用的是 DOM4J和 XmlResourceParser 来解析的.本文中将使用XmlPullParser来解析,分别解析不同复杂度的t ...

  8. 实现android上解析Json格式数据功能

    实现android上解析Json格式数据功能,该源码转载于安卓教程网的,http://android.662p.com ,个人感觉还不错的,大家可以看看一下吧. package com.practic ...

  9. android中解析文件的三种方式

    android中解析文件的三种方式     好久没有动手写点东西了,最近在研究android的相关技术,现在就android中解析文件的三种方式做以下总结.其主要有:SAX(Simple API fo ...

随机推荐

  1. 前端开发掌握nginx常用功能之rewrite

    上一篇博文对nginx最常用功能的server及location的匹配规则进行了讲解,这也是nginx实现控制访问和反向代理的基础.掌握请求的匹配规则算是对nginx有了入门,但是这些往往还是不能满足 ...

  2. Docker学习笔记-CentOS7镜像

    前言: 环境:centos7.5 64 位 正文: 第一步:下载centos7镜像 docker pull centos 第二步:建立centos7的容器 sudo docker run --priv ...

  3. Python学习笔记【第十五篇】:Python网络编程三ftp案例练习--断点续传

    开发一个支持多用户在线的FTP程序-------------------主要是学习思路 实现功能点 1:用户登陆验证(用户名.密码) 2:实现多用户登陆 3:实现简单的cmd命令操作 4:文件的上传( ...

  4. 一个applicationContext 加载错误导致的阻塞解决小结

    问题为对接一个sso的验证模块,正确的对接姿势为,接入一个 filter, 然后接入一个 SsoListener . 然而在接入之后,却导致了应用无法正常启动,或者说看起来很奇怪,来看下都遇到什么样的 ...

  5. ajax实现异步前后台交互,模拟百度搜索框智能提示

    1.什么是异步?在传统的网站项目中,填写一堆数据,最后点击提交,在点击提交的这一刻才实现数据提交,前后台交互.在你点击提交之前数据是没有提交到后台的.这样就会造成很大的不便.比如,我填了一大堆数据,结 ...

  6. mstsc远程报:这可能是由于CredSSP 加密Oracle修正的两种完美解决方法

    win10很完美,用的也很舒服!当然人无完人,也总有不尽如人意的时候.比如说我们经常用的远程mstsc,就出现了一个坑,既然出现坑了,我们就得把坑解决掉吧!下面就记录一下这个坑的解决方法. 本文地址: ...

  7. HP服务器设置iLO

    HP服务器设置iLO步凑 1.开机出现界面—按下F11进入Boot Menu: 2.选择Generic USB Boot回车: 3.选择System Configuration回车: 4.选择iLO ...

  8. 大数据入门基础系列之Hadoop1.X、Hadoop2.X和Hadoop3.X的多维度区别详解(博主推荐)

    不多说,直接上干货! 在前面的博文里,我已经介绍了 大数据入门基础系列之Linux操作系统简介与选择 大数据入门基础系列之虚拟机的下载.安装详解 大数据入门基础系列之Linux的安装详解 大数据入门基 ...

  9. ADO.NET的整理

    ADO.NET的几个对象 Connection:管理数据库的连接 Command:对数据库执行命令 DataReader:数据流读取器,返回的数据都是快速的且只是“向前”的数据流.无法实例化,只能通过 ...

  10. Windows 下获取硬盘序列号

    只获取序列号 以下任意一条命令都可以: wmic diskdrive get serialnumber wmic path win32_physicalmedia get SerialNumber w ...