写点什么

BroadcastReceiver 源码分析,一线互联网大厂中高级 Android 面试真题收录

用户头像
Android架构
关注
发布于: 刚刚

ContextImpl.java


public void sendBroadcast(Intent intent) {


warnIfCallingFromSystemProcess();


String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());


intent.prepareToLeaveProcess(this);


ActivityManager.getService().broadcastIntent(


mMainThread.getApplicationThread(), intent, resolvedType, null,


Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,


getUserId());


}


2.2 AMS 处理 broadcastIntent




ActivityManagerService.java


public final int broadcastIntent(IApplicationThread caller,


Intent intent, String resolvedType, IIntentReceiver resultTo,


int resultCode, String resultData, Bundle resultExtras,


String[] requiredPermissions, int appOp, Bundle bOptions,


boolean serialized, boolean sticky, int userId) {


···


int res = broadcastIntentLocked(callerApp,


callerApp != null ? callerApp.info.packageName : null,


intent, resolvedType, resultTo, resultCode, resultData, resultExtras,


requiredPermissions, appOp, bOptions, serialized, sticky,


callingPid, callingUid, userId);


···


}


}


final int broadcastIntentLocked(ProcessRecord callerApp,


String callerPackage, Intent intent, String resolvedType,


IIntentReceiver resultTo, int resultCode, String resultData,


Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,


boolean ordered, boolean sticky, int callingPid, int callingUid, int userId){


···


//1 找到匹配的 Receiver 列表


registeredReceivers = mReceiverResolver.queryIntent(intent,


resolvedType, false /defaultOnly/, userId);


int NR = registeredReceivers != null ? registeredReceivers.size() : 0;


//是否是有序广播,并且存在接收者


if (!ordered && NR > 0) {


//取出普通任务 queue


final BroadcastQueue queue = broadcastQueueForIntent(intent);


BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,


callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,


requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,


resultCode, resultData, resultExtras, ordered, sticky, false, userId);


//添加到并行分发 queue


queue.enqueueParallelBroadcastLocked(r);


//开始分发广播


queue.scheduleBroadcastsLocked();


registeredReceivers = null;


NR = 0;


}


}


2.3 AMS 发送到队列处理广播




queue.scheduleBroadcastsLocked();会发送 BROADCAST_INTENT_MSG,调用 processNextBroadcast(true);


BroadcastQueue.java


final void processNextBroadcast(boolean fromMsg) {


synchronized (mService) {


processNextBroadcastLocked(fromMsg, false);


}


}


final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj){


while (mParallelBroadcasts.size() > 0) {


r = mParallelBroadcasts.remove(0);


final int N = r.receivers.size();


//依次取出分发


for (int i=0; i<N; i++) {


Object target = r.receivers.get(i);


//调用


deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);


}


}


}


private void deliverToRegisteredReceiverLocked(BroadcastRecord r,


BroadcastFilter filter, boolean ordered, int index) {


··· //分发广播到客户端


performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,


new Intent(r.intent), r.resultCode, r.resultData,


r.resultExtras, r.ordered, r.initialSticky, r.userId);


····


}


void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,


Intent intent, int resultCode, String data, Bundle extras,


boolean ordered, boolean sticky, int sendingUser) throws RemoteException {


// Send the intent to the receiver asynchronously using one-way binder calls.


//判断应是否为空


if (app != null) {


if (app.thread != null) {


//通知客户端


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


分发广播,Binder 采用 oneway 异步 应用端会自动串行化


app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,


data, extras, ordered, sticky, sendingUser, app.repProcState);


}


} else {


receiver.performReceive(intent, resultCode, data, extras, ordered,


sticky, sendingUser);


}


}


2.4 客户端处理 receiver




AMS 端的 app.thread.scheduleRegisteredReceiver(),会调用到注册时注册的 InnerReceiver 的 performReceive 方法


ActivityThread.java


public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,


int resultCode, String dataStr, Bundle extras, boolean ordered,


boolean sticky, int sendingUser, int processState) throws RemoteException {


updateProcessState(processState, false);


//1


receiver.performReceive(intent, resultCode, dataStr, extras, ordered,


sticky, sendingUser);


}


InnerReceiver.java


public void performReceive(Intent intent, int resultCode, String data,


Bundle extras, boolean ordered, boolean sticky, int sendingUser) {


final LoadedApk.ReceiverDispatcher rd;


···


if (rd != null) {


//调用 LoadedApk.ReceiverDispatcher 的 performReceive


rd.performReceive(intent, resultCode, data, extras,


ordered, sticky, sendingUser);


···


}


}


···


LoadedApk.ReceiverDispatcher.java


public void performReceive(Intent intent, int resultCode, String data,


Bundle extras, boolean ordered, boolean sticky, int sendingUser) {


final Args args = new Args(intent, resultCode, data, extras, ordered,


sticky, sendingUser);


···


//向 ActivityThread 发送一个 Runnable


if (intent == null || !mActivityThread.post(args.getRunnable())) {


}


}


Args.java


public final Runnable getRunnable() {


return () -> {


final BroadcastReceiver receiver = mReceiver;


final boolean ordered = mOrdered;


=


final IActivityManager mgr = ActivityManager.getService();


···


receiver.setPendingResult(this);


//这里触发了 BoradcastReciever 回调


receiver.onReceive(mContext, intent);


···


};


}


三、动态注册解析总结:


=========================================================================


1、首先动态注册 BroadcastReceiver 到 AMS,将他们存储在一个 Map 中,Map 的 key 是 IIntentReceiver 用于回调注册端,value 是一个 ReceiverList


2、发送这发送 Intent 到 AMS,筛选出匹配的 ReceiverList,遍历通知注册端


四、BroadcastReceiver 静态注册接收


=======================================================================================


4.1 PMS 解析清单文件获取注册信息




PackageParser.java


private boolean parseBaseApplication(Package owner, Resources res,


XmlResourceParser parser, int flags, String[] outError){


else if (tagName.equals("receiver")) {


Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,


true, false);


owner.receivers.add(a);


}


}


1、将 receiver 解析成一个 Activity(这个 Activity 表示的是一个组件)对象,添加到 receivers 的列表中,receivers 是一个 ArrayList


五、普通广播发送后的静态接收


============================================================================


5.1 调用 Context 的 sendBroadcast




最后会调用到


ContextImpl.java


public void sendBroadcast(Intent intent) {


warnIfCallingFromSystemProcess();


String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());


intent.prepareToLeaveProcess(this);


ActivityManager.getService().broadcastIntent(


mMainThread.getApplicationThread(), intent, resolvedType, null,


Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,


getUserId());


}


5.2 AMS 处理 broadcastIntent




ActivityManagerService.java


public final int broadcastIntent(IApplicationThread caller,


Intent intent, String resolvedType, IIntentReceiver resultTo,


int resultCode, String resultData, Bundle resultExtras,


String[] requiredPermissions, int appOp, Bundle bOptions,


boolean serialized, boolean sticky, int userId) {


···


int res = broadcastIntentLocked(callerApp,


callerApp != null ? callerApp.info.packageName : null,


intent, resolvedType, resultTo, resultCode, resultData, resultExtras,


requiredPermissions, appOp, bOptions, serialized, sticky,


callingPid, callingUid, userId);


···


}


}


final int broadcastIntentLocked(ProcessRecord callerApp,


String callerPackage, Intent intent, String resolvedType,


IIntentReceiver resultTo, int resultCode, String resultData,


Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,


boolean ordered, boolean sticky, int callingPid, int callingUid, int userId){


···


//获取接收静态广播


receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);


//通过 Intent 查找能接受的动态广播


registeredReceivers = mReceiverResolver.queryIntent(intent,


resolvedType, false /defaultOnly/, userId);


int NR = registeredReceivers != null ? registeredReceivers.size() : 0;


if (!ordered && NR > 0) {


//处理动态广播,添加到并行分发队列,OneWay 发送 binder 处理是串行的


}


//给没有处理完的动态 receiver(order 是 true),跟静态 receiver 合并到一起


if ((receivers != null && receivers.size() > 0){


//处理剩下的 receiver。加到串行分发队列


//获取 queue


BroadcastQueue queue = broadcastQueueForIntent(intent);


BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,


callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,


requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,


resultData, resultExtras, ordered, sticky, false, userId);


//添加到串行分发 queue


queue.enqueueOrderedBroadcastLocked(r);


//处理分发


queue.scheduleBroadcastsLocked();


}


return ActivityManager.BROADCAST_SUCCESS;


}


5.3 AMS 发送到队列处理广播




queue.scheduleBroadcastsLocked();会发送 BROADCAST_INTENT_MSG,调用 processNextBroadcast(true);


BroadcastQueue.java


final void processNextBroadcast(boolean fromMsg) {


synchronized (mService) {


processNextBroadcastLocked(fromMsg, false);


}


}


final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj){


while (mParallelBroadcasts.size() > 0) {


r = mParallelBroadcasts.remove(0);


final int N = r.receivers.size()


for (int i=0; i<N; i++) {


Object target = r.receivers.get(i);


//先并行分发,然后接下来分发串行广播


deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);


}


}


//如果有 pedding 广播,先直接返回,这个广播在等待应用进程启动


//如果当前广播分发超时了,废弃这个广播,处理下一个广播


broadcastTimeoutLocked(false);


//如果没有超时,并且在分发中,就先返回。什么也不做


//如果当前的广播已经分发完一个 receiver,就继续分发下一个 receiver


//如果这个 receiver 是动态注册的 receiver 就直接分发


//如果这个 receiver 是静态注册的 receiver,先看进程启动没有


//如果进程启动了,就直接分发


processCurBroadcastLocked(r, app, skipOomAdj);


//没启动的话就先启动进程,然后给广播标记为 pedding


//进程启动后 attachApplication 时继续处理这个 pending 的广播


}


BroadcastQueue.java


//处理超时


final void broadcastTimeoutLocked(boolean fromMsg) {


BroadcastRecord r = mOrderedBroadcasts.get(0);


Object curReceiver = r.receivers.get(r.nextReceiver-1);


//找到当前分发 receiver 对应的进程


if (mPendingBroadcast == r) {


mPendingBroadcast = null;


}


// Move on to the next receiver.


finishReceiverLocked(r, r.resultCode, r.resultData,


r.resultExtras, r.resultAbort, false);


//发送消息处理下一个 receiver


scheduleBroadcastsLocked();


if (!debugging && anrMessage != null) {


// Post the ANR to the handler since we do not want to process ANRs while


// potentially holding our lock.


//超时显示 ANR


mHandler.post(new AppNotResponding(app, anrMessage));


}


}


BroadcastQueue.java


//接收进程存在,通知接收进程


private final void processCurBroadcastLocked(BroadcastRecord r,


ProcessRecord app, boolean skipOomAdj) throws RemoteException {


···


app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,


mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),


r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,


app.repProcState);


···

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
BroadcastReceiver源码分析,一线互联网大厂中高级Android面试真题收录