Android源码分析--广播的注册、发送和接收

简介: Android源码分析--广播的注册、发送和接收

广播的注册、发送和接收过程


广播的注册、发送和接收都与AMS有着密不可分的关系。


广播的注册


广播的注册可分为静态注册和动态注册两种,静态注册在应用安装时由PackageManagerService来完成注册过程,下面我主要来分析动态广播注册。


ContextImpl请求AMS注册广播


微信截图_20220517185107.png



  • 在ContextImpl的registerReceiverInternal方法中,首先是和服务绑定类似的,通过LoadedApk类型的mPackageInfo对象的getReceiverDispatcher方法来获取IIntentReceiver类型的rd对象,用于广播的跨进程通信。然后调用IActivityManager的registerReceiver方法,最终调用AMS的registerReceiver方法,并将IIntentReceiver类型的rd对象传入。


  • 在AMS的registerReceiver方法中,首先是调用getRecordForAppLocked方法获取调用注册广播的应用程序进程信息,然后根据进程信息获取对应在AMS中存储的所有粘性广播的intent,然后和传入的参数filter的粘性广播进行对比,找到所有匹配的intent存入到allSticky列表中,最终加入到广播队列中执行。


  • 除此之外,在AMS的registerReceiver中还调用了HashMap类型,存放了所有应用进程的广播接收者列表mRegisteredReceivers,通过传入之前的IIntentReceiver对象获取到对应的广播接收者列表ReceiverList,并将其传入创建BroadcastFilter,用以描述注册的广播接收者。最后将BroadcastFilter添加到IntentResolver类型的mReceiverResolver中,这样当AMS接收到广播时,就可以从mReceiverResolver中直接找到对应的广播接收者,从而达到注册广播的目的。


广播的发送


广播可以发送多种类型,包括无序广播(普通广播)、有序广播和粘性广播。


Android广播的分类:


1、 普通(无序)广播:使用sendBroadcast发送广播。这种广播可以依次传递给各个处理器去处理。


2、 有序广播:使用sendOrderedBroadcast发送广播。这种广播在处理器端的处理顺序是按照处理器的不同优先级来区分的,高优先级的处理器会优先截获这个消息,并且可以将这个消息删除。


3、 粘性消息:使用sendStickyBroadcast发送广播。粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态,粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据。


注意:普通广播和粘性消息不能被截获,而有序广播是可以被截获的。


这里我们以最简单的普通广播发送为例进行分析。


ContextImpl请求AMS发送广播


微信截图_20220517185159.png


  • 当我们需要发送无序广播时,需要调用Context的sendBroadcast方法,然后在ContextWrappersendBroadcast中调用ContextImplsendBroadcast方法,最终会调用AMS的broadcastIntent方法。


  • 在AMS的broadcastIntent方法中,首先对发送的广播进行合法性校验,然后调用其broadcastIntentLocked方法。


  • 在AMS的broadcastIntentLocked方法中做了很多事情,对广播做了一系列的处理后,最终调用broadcastQueueForIntent构建了广播队列,然后新建BroadcastRecord对象并将其传入广播队列中,同时执行广播队列的scheduleBroadcastLocked方法。


广播的接收


AMS到BroadcastReceiver接收广播


微信截图_20220517185233.png


  • 在BroadcastQueue的scheduleBroadcastLocked方法中,发送了类型为BROADCAST_INTENT_MSG类型的消息,并在消息处理中最终调用了其processNextBroadcastLocked方法,并在其中遍历存储了无序广播的列表,然后调用deliverToRegisteredReceiverLocked将这些无序广播的信息描述发送给对应的广播接收者。


  • 在BroadcastQueue的deliverToRegisteredReceiverLocked方法中主要检查广播发送者和广播接收者的权限,并最终会调用其performReceiveLocked方法,然后在其方法中调用ApplicationThread的scheduleRegisteredReceiver方法。


  • 在ApplicationThread的scheduleRegisteredReceiver方法中会调用IIntentReceiver类型的对象receiver的performReceive方法,而IIntentReceiver是Binder通信的客户端,InnerReceiver在本地的代理,它会调用InnerReceiver的performReceive方法,最终会调用ReceiverDispatcherperformReceive方法。


  • 在ReceiverDispatcher的performReceive方法中,会构建类型为Args类型的对象,最终通过mActivityThread(H),将Args对象的getRunnable方法获取的Runnable发送到线程的消息队列中执行。在Args对象的Runnable方法中会调用BroadcastReceiver类型的receiver对象的onReceive方法,这样注册的广播接收者就收到了广播并得到了intent。
相关文章
|
4月前
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
253 2
|
11月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
664 1
安卓项目:app注册/登录界面设计
|
5月前
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
Ubuntu 开发工具 Android开发
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
本文介绍了在基于Ubuntu 22.04的环境下配置Python 3.9、安装repo工具、下载和同步AOSP源码包以及处理repo同步错误的详细步骤。
952 0
Repo下载AOSP源码:基于ubuntu22.04 环境配置,android-12.0.0_r32
|
8月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
359 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
475 1
|
Android开发 Docker 容器
docker中编译android aosp源码,出现Build sandboxing disabled due to nsjail error
在使用Docker编译Android AOSP源码时,如果遇到"Build sandboxing disabled due to nsjail error"的错误,可以通过在docker run命令中添加`--privileged`参数来解决权限不足的问题。
2169 1
|
API 开发工具 Android开发
Android源码下载
Android源码下载
1486 0
|
开发工具 uml git
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
本文分享了下载AOSP源码的方法,包括如何使用repo工具和处理常见的repo sync错误,以及配置Python环境以确保顺利同步特定版本的AOSP代码。
1887 0
AOSP源码下载方法,解决repo sync错误:android-13.0.0_r82
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
909 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题