广播是怎么注册的呢?

阶段 | 组件/数据结构 | 作用描述 | 存储位置/关联关系 |
App进程阶段 | BroadcastReceiver | 开发者自定义的广播接收器,实现onReceive 方法处理事件。 | App进程(Activity/Service等组件内) |
ReceiverDispatcher | 将BroadcastReceiver封装为跨进程可调用的 IIntentReceiver接口对象。 | LoadedApk中创建,关联InnerReceiver | |
InnerReceiver | 继承IIntentReceiver.Stub的Binder实体,AMS通过它回调App主线程的onReceive | 作为Binder服务端存在于App进程,代理对象传递至AMS | |
SystemServer进程阶段 | ReceiverList | 以InnerReceiver的Binder为Key,管理同一接收器的多个BroadcastFilter | 存储在AMS的mRegisteredReceivers(HashMap) |
BroadcastFilter | 关联IntentFilter与ReceiverList,描述接收器感兴趣的广播类型。 | 注册到mReceiverResolver(全局匹配引擎)和ReceiverList | |
BroadcastQueue | 管理待分发的广播,分为有序和无序队列。 | AMS中维护,异步分发广播 | |
核心数据结构 | mRegisteredReceivers | 维护所有动态注册的ReceiverList,避免重复注册。 | AMS内存(HashMap结构) |
mReceiverResolver | 基于IntentFilter的快速匹配引擎,优化广播分发效率。 | AMS内存(IntentResolver子类) | |
mStickyBroadcasts | 缓存粘性广播,按用户ID和Action分类存储。 | AMS内存(SparseArray结构),供新注册接收器匹配历史广播 |
源码流程:
app.registerReceiver()->Context.registerReceiver(BroadcastReceiver, IntentFilter)#Context.registerReceiver(BroadcastReceiver, IntentFilter)->Context.registerReceiverInternal()##Context.registerReceiverInternal()->LoadedApk.getReceiverDispatcher:返回一个为IIntentReceiver类型的ReceiverDispatcher(广播快递员)###LoadedApk.getReceiverDispatcher->ReceiverDispatcher实例化####ReceiverDispatcher实例化->InnerReceiver实例化:可以看到 InnerReceiver extends IIntentReceiver.Stub 是跨进程对象的一个实体##Context.registerReceiverInternal()->ActivityManagerService.registerReceiverWithFeature(IIntentReceiver)###ActivityManagerService.registerReceiverWithFeature(IIntentReceiver)->ActivityManagerService.registerReceiverWithFeatureTraced####ActivityManagerService.registerReceiverWithFeatureTraced->RegisteredReceivers.get(receiver.asBinder())创建ReceiverList,并mRegisteredReceivers全局注册表记录####ActivityManagerService.registerReceiverWithFeatureTraced->new BroadcastFilter:创建BroadcastFilter并注册到Resolver,并mReceiverResolver注册到全局过滤器####ActivityManagerService.registerReceiverWithFeatureTraced->new BroadcastRecord创建广播记录并加入队列,并mBroadcastQueue.enqueueBroadcastLocked(r)异步分发
源码重点函数分析:
注册广播接收器
registerReceiver来时往里面看,因为Activity是Context的子类,这个注册的方法的实现则是在ContextImpl当中,其中最终调用的方法为registerReceiverInternal,代码如下
/*** 动态注册广播接收器的核心方法,完成跨进程通信的Binder封装和AMS注册* @param receiver 开发者定义的广播接收器实例* @param userId 用户ID(多用户支持)* @param filter 意图过滤器,描述接收器感兴趣的广播类型* @param broadcastPermission 接收广播所需的权限(可选)* @param scheduler 指定回调线程的Handler(null则使用主线程Handler)* @param context 关联的Context对象* @param flags 注册标志位* @return 匹配的粘性广播Intent(若无则返回null)*/private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,IntentFilter filter, String broadcastPermission,Handler scheduler, Context context, int flags) {// 1. 创建跨进程通信对象IIntentReceiverIIntentReceiver rd = null;if (receiver != null) {if (mPackageInfo != null && context != null) {// 1.1 使用主线程Handler(若未指定)if (scheduler == null) {scheduler = mMainThread.getHandler(); // 获取ActivityThread的H主线程Handler[1,3](@ref)}// 1.2 通过LoadedApk获取ReceiverDispatcher(封装跨进程Binder对象)rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler,mMainThread.getInstrumentation(), true); // true表示需要注册[1,5](@ref)} else {// 1.3 备用路径:直接创建ReceiverDispatcher(非标准场景)if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = new LoadedApk.ReceiverDispatcher(mMainThread.getApplicationThread(),receiver, context, scheduler, null, true).getIIntentReceiver();}}try {// 2. 跨进程调用AMS注册广播final Intent intent = ActivityManager.getService().registerReceiverWithFeature(mMainThread.getApplicationThread(), // 应用主线程的IApplicationThread对象mBasePackageName, // 包名标识getAttributionTag(), // 归因标签(用于权限跟踪)AppOpsManager.toReceiverId(receiver), // 接收器唯一IDrd, // 跨进程回调接口filter, // 意图过滤器broadcastPermission, // 所需权限userId, // 用户IDflags); // 标志位[5](@ref)// 3. 处理返回的粘性广播(若存在)if (intent != null) {intent.setExtrasClassLoader(getClassLoader());// 3.1 准备Intent数据安全传输到应用进程intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),getAttributionSource()); // 检查签名权限保护[3](@ref)}return intent;} catch (RemoteException e) {throw e.rethrowFromSystemServer(); // 处理Binder通信异常}}
通过 LoadedApk.getReceiverDispatcher() 将 BroadcastReceiver 包装为 IIntentReceiver(Binder接口),内部创建 ReceiverDispatcher 和 InnerReceiver(IIntentReceiver.Stub 实现类),构成双向通信桥梁
获取广播分发器 getReceiverDispatcher
桥接BroadcastReceiver和Binder通信,含InnerReceiver和Handler
/*** 为BroadcastReceiver创建/获取跨进程通信的IIntentReceiver对象* @param r 开发者定义的广播接收器实例* @param context 关联的Context对象(通常为Activity/Service)* @param handler 指定回调线程的Handler(主线程Handler)* @param instrumentation 测试工具类(正常场景为null)* @param registered 是否为持久化注册(动态注册通常为true)* @return IIntentReceiver Binder接口对象,用于AMS跨进程回调*/public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,Context context, Handler handler,Instrumentation instrumentation, boolean registered) {// 线程安全:通过synchronized保护mReceivers数据结构synchronized (mReceivers) {LoadedApk.ReceiverDispatcher rd = null;ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;// 1. 尝试从缓存中获取已注册的ReceiverDispatcherif (registered) {// 1.1 获取当前Context对应的接收器映射表map = mReceivers.get(context); // mReceivers: ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>>if (map != null) {rd = map.get(r); // 检查是否已存在相同接收器的Dispatcher}}// 2. 缓存未命中时创建新对象if (rd == null) {// 2.1 构造ReceiverDispatcher(含跨进程Binder对象)rd = new ReceiverDispatcher(mActivityThread.getApplicationThread(), // IApplicationThread对象r, // 用户定义的BroadcastReceivercontext,handler, // 主线程Handler(确保onReceive在主线程执行)instrumentation,registered);// 2.2 持久化注册时加入缓存if (registered) {if (map == null) {map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mReceivers.put(context, map); // 建立Context到接收器映射的关系}map.put(r, rd); // 缓存键:BroadcastReceiver对象}} else {// 3. 缓存命中时校验有效性rd.validate(context, handler); // 检查Context和Handler是否匹配}// 4. 标记为活跃状态(防止被意外回收)rd.mForgotten = false;// 5. 返回InnerReceiver(IIntentReceiver.Stub的实现类)return rd.getIIntentReceiver();}}
AMS注册广播接收器方法
动态注册核心步骤
ReceiverList管理:同一IIntentReceiver Binder对象对应一个ReceiverList,避免重复注册。
BroadcastFilter注册:将广播过滤器加入全局mReceiverResolver,后续广播分发时快速匹配
private Intent registerReceiverWithFeatureTraced(IApplicationThread caller, String callerPackage,String callerFeatureId, String receiverId, IIntentReceiver receiver,IntentFilter filter, String permission, int userId, int flags) {// 1. 权限与调用者验证enforceNotIsolatedCaller("registerReceiver"); // 禁止隔离进程调用ProcessRecord callerApp = getRecordForAppLOSP(caller); // 获取调用者进程记录// 验证调用者包名与进程匹配性(防止伪造身份)if (!UserHandle.isCore(callerApp.info.uid) && !callerApp.getPkgList().containsKey(callerPackage)) {throw new SecurityException("Package/Process mismatch");}// 2. 用户ID处理与优先级检查userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, ...);if (UserHandle.isCore(callingUid)) {// 系统进程注册重要广播时需设置优先级(如USER_ACTION/PACKAGE_ACTION等)if (filter.getPriority() == 0) {filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); // 默认高优先级}}// 3. 粘性广播(Sticky Broadcast)匹配ArrayList<StickyBroadcast> stickyBroadcasts = null;synchronized (mStickyBroadcasts) {// 遍历IntentFilter的Action,查找匹配的粘性广播for (String action : filter.actionsIterator()) {for (int userId : {UserHandle.USER_ALL, callingUserId}) {ArrayMap<String, ArrayList<StickyBroadcast>> stickies = mStickyBroadcasts.get(userId);if (stickies != null && stickies.containsKey(action)) {stickyBroadcasts.addAll(stickies.get(action)); // 收集匹配的粘性广播}}}}// 4. 动态接收器注册核心逻辑synchronized (this) {// 4.1 创建或获取ReceiverList(同一Binder对象对应一个ReceiverList)ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());if (rl == null) {rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver);if (rl.app != null) {rl.app.mReceivers.addReceiver(rl); // 关联到进程记录} else {receiver.asBinder().linkToDeath(rl, 0); // 跨进程死亡监听}mRegisteredReceivers.put(receiver.asBinder(), rl); // 全局注册表记录}// 4.2 创建BroadcastFilter并注册到ResolverBroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, ...);if (!rl.containsFilter(filter)) {rl.add(bf); // 添加到ReceiverListmReceiverResolver.addFilter(bf); // 注册到全局过滤器}// 5. 处理匹配的粘性广播(立即分发给新注册的接收器)if (stickyBroadcasts != null) {ArrayList<BroadcastFilter> receivers = new ArrayList<>();receivers.add(bf);for (StickyBroadcast broadcast : stickyBroadcasts) {// 创建广播记录并加入队列BroadcastRecord r = new BroadcastRecord(..., broadcast.intent, ..., receivers);mBroadcastQueue.enqueueBroadcastLocked(r); // 异步分发}}return stickyBroadcasts != null ? stickyBroadcasts.get(0).intent : null; // 返回首个粘性Intent}}
广播注册流程中的LoaderApk和AMS的数据结构关系图

广播注册流程小结
1. App进程:打包“快递员”
需求发起:App调用registerReceiver,就像下单寄快递,告诉系统要接收哪种广播(IntentFilter)
包装处理:
ReceiverDispatcher:系统把开发者写的BroadcastReceiver打包成“快递员”,负责跨进程送货(IIntentReceiver接口)
InnerReceiver:这个“快递员”有个Binder工牌(IIntentReceiver.Stub),AMS凭工牌找到App的家(主线程)送货
2. 跨进程:向AMS“登记收货地址”
Binder快递:把“快递员”的工牌和收货要求(IntentFilter)通过Binder寄给AMS(registerReceiverWithFeature)
防重复注册:AMS用工牌(Binder对象)当身份证,检查是否已登记过,避免重复注册
3. AMS:建立“收货档案”
档案管理:
ReceiverList:以Binder工牌为Key,建一个“收货清单”,记录同一接收器的所有过滤条件
BroadcastFilter:把IntentFilter和接收器绑定,存到全局“快递分拣系统”(mReceiverResolver)
粘性广播:如果历史广播中有匹配的“包裹”,直接塞进分发队列(mBroadcastQueue)马上派送
关键角色比喻
组件 | 比喻 | 作用 |
ReceiverDispatcher | 快递员+物流单 | 连接App和AMS,确保广播送到主线程 |
mRegisteredReceivers | 客户档案库 | 用Binder工牌管理所有注册的接收器,避免重复 |
mReceiverResolver | 智能分拣机 | 根据IntentFilter快速匹配接收器,类似快递分拣中心 |
mBroadcastQueue | 快递派送车 | 分前台/后台/离线三种车队,决定广播的派送优先级 |