BroadcastReceiver的源码分析

简介: android提供了广播机制,通过BroadcastReceiver可以在不同的进程间传递消息。类似于观察者模式,A应用通过注册广播表示A对消息subject感兴趣,当B应用发出subject类型的消息的时候,A应用就能收到对应的消息。

android提供了广播机制,通过BroadcastReceiver可以在不同的进程间传递消息。类似于观察者模式,A应用通过注册广播表示A对消息subject感兴趣,当B应用发出subject类型的消息的时候,A应用就能收到对应的消息。

android提供静态和动态两种方式进行消息注册,静态注册指的是在AndroidManifest.xml中进行注册,动态注册指的是在Activity通过registerReceiver的方式进行广播注册。

静态广播注册流程

静态广播注册指的是在AndroidManifest.xml注册Receiver,当Apk安装时会将静态注册的Receiver信息注册到PMS中,APK的安装流程(https://www.jianshu.com/p/953475cea991)如下:

img_47f9af2b2d4df381166bec1d6ccdd5d9.png
APK安装流程

其中installPackageLI完成了Apk的解析,生成了Package对象,scanPackageLi包括四大组件注册之类的操作。

img_6744e0c68bdeddac14b880581737c087.png
PMS.scanPackageDirtyLI注册静态广播

解析到APK里的静态广播会注册到PMS的mReceivers对象中,mReceivers类型为ActivityIntentResolver。

动态广播注册流程

Activity通过registerReceiver方式进行广播注册,注册流程如下:

img_e462376d8b9cd6d59914b4a470d15e71.png
registerReceiver流程

ContextImpl.registerReceiverInternal

img_9c1bba5dec41715fba98f9d5bf04f230.png
ContextImpl.registerReceiverInternal

该函数根据BroadcastReceiver对象生成IIntentReceiver对象,该对象和ApplicationThread的功能一样,试想一下,APP进程向AMS进程注册广播,当AMS收到广播向APP进程分发时需要用到Binder调用,IIntentReceiver就是进行跨进程调用的。

img_9943ed5b8f75c0d254b32cc0399d8268.png
AMS.registerReceiver

AMS将IIntentReceiver保存到mReisterdReceivers中,最终保存到mReceiverResolver.addFilter(bf);中。

sendBroadcast发送广播

img_ffc546bf2daaef71d17b5e905a29ce64.jpe
sendBroascast流程

发送广播最终走到了AMS.broadcastIntentLocked,其中核心的代码如下所示:

img_443bd0c7192d975147b24c7693baaa98.png
AMS.broadcastIntentLocked

broadcastIntentLocked中receivers表示静态注册的广播,通过collectReceiverComponents从PMS那里获取;registerdReceivers表示动态注册的广播,从mReceiverResolver那里获取。在获取到要接受所有广播后,就调用如下函数进行广播分发。

img_427ad0c8090bc913223424e2ad1da1c1.png
广播分发

scheduleBroadcastsLocked开始进行广播发送

img_1e92c46a8996b4bbdbd17ca009c9dfe1.png
BroadcastQueue.scheduleBroadcastsLocked

Handler消息最终调用了BroadcastQueue.processNextBroadcast,然后调用了performReceiveLocked,

img_9138edcd6643fa0fd5c4389ae014e87e.png
processNextBroadcast

processNextBroadcast调用了performReceiverLocked

img_33abe4993f60029de5d324de280f925f.png
performReceiverLocked

performReceiverLocked继续调用IItentReceiver.performReceiver,该调用的Binder方式,

img_e8208ec92c18e3006a653f1eaa261283.png
IItentReceiver.performReceiver

最终调用了Args.run

img_8ce322886298bd74f2866264afe2dc31.png
Args.run

Args.run通过类加载器加载Receiver对象,并最终调用onReceive函数,至此,广播发送完成。

目录
相关文章
|
Java Shell Linux
Android——编译(二):android.mk的相关知识
Android——编译(二):android.mk的相关知识
809 0
|
移动开发 API HTML5
HTML5作业(三)-----问卷调查表设计
该实验旨在通过设计一个问卷调查表来理解和熟悉表单API及各种组件的使用。要求包括使用不同类型的表单组件(如单选、多选、多行输入),设置输入提示,验证表单内容不为空,以及保持文档格式整洁美观。提供的HTML代码展示了一个包含姓名、年龄、性别选择、多选水果和单选颜色问题的问卷,并在提交前进行必要检查。
206 0
|
机器学习/深度学习 人工智能 自然语言处理
探索深度学习与自然语言处理的前沿技术:Transformer模型的深度解析
探索深度学习与自然语言处理的前沿技术:Transformer模型的深度解析
609 1
|
Ubuntu 开发工具 git
ubuntu 14.04的git 错误: gnutls_handshake() failed: Handshake failed
本文提供了一个解决Ubuntu 14.04系统上使用Git时遇到的"gnutls_handshake() failed: Handshake failed"错误的脚本,通过替换git的默认加密传输库gnutls为更稳定的openssl,并指导如何编译安装新版本的git来解决问题。
763 0
|
存储 缓存 监控
警惕网络背后的陷阱:揭秘DNS缓存中毒如何悄然改变你的网络走向
【8月更文挑战第26天】DNS缓存中毒是一种网络攻击,通过篡改DNS服务器缓存,将用户重定向到恶意站点。攻击者利用伪造响应、事务ID猜测及中间人攻击等方式实施。这可能导致隐私泄露和恶意软件传播。防范措施包括使用DNSSEC、限制响应来源、定期清理缓存以及加强监控。了解这些有助于保护网络安全。
442 1
|
编解码 安全 Ubuntu
Android Selinux 问题处理笔记
这篇文章是关于处理Android系统中SELinux权限问题的笔记,介绍了如何通过分析SELinux拒绝的日志、修改SELinux策略文件,并重新编译部署来解决权限问题,同时提供了一些SELinux的背景知识和实用工具。
1183 0
|
机器学习/深度学习 算法 大数据
[ICLR 2024] 基于Pathways架构的自适应多尺度时间序列预测模型Pathformer
阿里云计算平台大数据基础工程技术团队主导,与华东师范大学数据科学与工程学院合作的论文《Pathformer: Multi-Scale Transformers With Adaptive Pathways For Time Series Forecasting》被ICLR 2024接收,该论文提出了基于Pathways架构的自适应多尺度时间序列预测模型Pathformer,它从时间分辨率和时间距离角度进行多尺度时序建模,同时进一步提出自适应Pathways来动态调整多尺度建模过程,基于两者,Pathformer在阿里云数据集和公开数据集上取得SOTA预测效果,并展现出不错的泛化性和迁移性。
|
存储 缓存 NoSQL
深入浅出Redis(十):Redis的Lua脚本
深入浅出Redis(十):Redis的Lua脚本
|
关系型数据库 MySQL 数据处理
一文彻底理解乐观锁与悲观锁
一文彻底理解乐观锁与悲观锁
1414 0
|
存储 XML 缓存
基于Android T:包管理机制详解(上)
PKMS在我们开发中经常会碰到,了解其底层原理对我们开发也是很有帮助的,比如**包体积优化,应用启动优化等**。