这篇“Android广播Broadcast的启动流程是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android广播Broadcast的启动流程是什么”文章吧。
广播的注册
我们常在
Activity或
Service、甚至
Application中调用
registerReceiver函数来注册动态广播,该函数其实来自它们共同的父类
ContextWrapper中。
ContextWrapper是
Context的子类,我们会在介绍
Context的文章介绍它们的关系。
public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
这里
Context类型的
mBase,在
Activity的创建过程实际被赋值为
ContextImpl实例。
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext(), 0); }
经过
registerReceiver重载函数,调用了
registerReceiverInternal函数。
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context, int flags) { IIntentReceiver rd = null; //分析一 if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( receiver, context, scheduler, null, true).getIIntentReceiver(); } } try { 分析二: final Intent intent = ActivityManager.getService().registerReceiverWithFeature( mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd, filter, broadcastPermission, userId, flags); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
分析一:
传递进来的
BroadcastReceiver不为
null,
LoadedApk类型的
mPackageInfo只要应用进程启动,该属性就会被赋值,
context这里指向
Activity。
scheduler为
null,赋值为主线程的
H类型
mH对象。分析一,主要通过上面的变量来获得
IIntentReceiver类型
rd对象。
getReceiverDispatcher函数先从缓存检测是否有相同类型的
BroadcastReceiver对应的
ReceiverDispatcher。没有的话,则新建并缓存起来。 一个
context对应多个
BroadcastReceiver,而一个
BroadcastReceiver对应用一个
ReceiverDispatcher。
ReceiverDispatcher是
LoadedDispatcher的静态内部类,其内部还有一个
AIDL类型本地实现静态类
InnerReceiver。在
ReceiverDispatcher的构造函数中会创建
InnerReceiver的实例。
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r, Context context, Handler handler, Instrumentation instrumentation, boolean registered) { synchronized (mReceivers) { LoadedApk.ReceiverDispatcher rd = null; ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null; if (registered) { map = mReceivers.get(context); if (map != null) { rd = map.get(r); } } if (rd == null) { rd = new ReceiverDispatcher(r, context, handler, instrumentation, registered); if (registered) { if (map == null) { map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>(); mReceivers.put(context, map); } map.put(r, rd); } } else { rd.validate(context, handler); } rd.mForgotten = false; return rd.getIIntentReceiver(); } }
回到
registerReceiverInternal函数的分析二,调用了
AMS的
registerReceiverWithFeature函数。
该函数是
Broadcast整个注册过程结束的地方,根据新注册的
BroadcastReceiver,处理粘性广播的发送和当前注册
Receiver的添加。
分析一:
粘性广播存储在AMS的
SparseArray<ArrayMap<String, ArrayList<Intent>>>类型的
mStickyBroadcasts中。
SparseArray的
key为
userId,而
ArrayMap的
key为
action,
value为
Intent。即我们可以通过用户id在
mStickyBroadcasts找到当前进程对应所有粘性广播(和针对所有进程的粘性广播),然后根据对应的
action找到对应的
Intent。这里将他们收集到
stickyIntents集合中。
分析二:
所有广播的接收者
BroacastReceiver存储在
AMS类
HashMap<IBinder, ReceiverList>类型的
mRegisteredReceivers中。这里的
IBinder类型就是应用进程前面创建的
InnerReceiver类实例在AMS的引用。因为广播接收者
BroadcastReceiver对应一个或多个
Broadcast,所以这里通过继承自
ArrayList<BroadcastFilter>的
ReceiverList来表达这种关系。通过
BroadcastFilter来表示当前接收者感兴趣的广播。
分析三:
对匹配到的粘性Intent进入广播队列广播。
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage, String callerFeatureId, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { enforceNotIsolatedCaller("registerReceiver"); //粘性Intent ArrayList<Intent> stickyIntents = null; ProcessRecord callerApp = null; final boolean visibleToInstantApps = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0; int callingUid; int callingPid; boolean instantApp; synchronized(this) { if (caller != null) { //获得当前引用进程的ProcessRecord callerApp = getRecordForAppLocked(caller); ... callingUid = callerApp.info.uid; callingPid = callerApp.pid; } else { callerPackage = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); } //是否快应用(类似小程序) instantApp = isInstantApp(callerApp, callerPackage, callingUid); userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage); //分析一:当前注册广播中感兴趣的action列表 Iterator<String> actions = filter.actionsIterator(); if (actions == null) { ArrayList<String> noAction = new ArrayList<String>(1); noAction.add(null); actions = noAction.iterator(); } //从历史粘性广播中查找与当前注册的action一致的intent //添加到stickyIntents // Collect stickies of users int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) }; while (actions.hasNext()) { String action = actions.next(); for (int id : userIds) { ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id); if (stickies != null) { ArrayList<Intent> intents = stickies.get(action); if (intents != null) { if (stickyIntents == null) { stickyIntents = new ArrayList<Intent>(); } stickyIntents.addAll(intents); } } } } } //处理content类型的Intent ArrayList<Intent> allSticky = null; if (stickyIntents != null) { final ContentResolver resolver = mContext.getContentResolver(); // Look for any matching sticky broadcasts... for (int i = 0, N = stickyIntents.size(); i < N; i++) { Intent intent = stickyIntents.get(i); // Don't provided intents that aren't available to instant apps. if (instantApp && (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) { continue; } //当前注册广播IntentFilter是否与action一致的intent的匹配 //处理content类型 if (filter.match(resolver, intent, true, TAG) >= 0) { if (allSticky == null) { allSticky = new ArrayList<Intent>(); } allSticky.add(intent); } } } //receiver为null,直接返回null或者第一个粘性intent Intent sticky = allSticky != null ? allSticky.get(0) : null; if (receiver == null) { return sticky; } synchronized (this) { ... //分析二: //从缓存或新建ReceiverList对象,与Receiver绑定 ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); if (rl.app != null) { final int totalReceiversForApp = rl.app.receivers.size(); if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) { throw new IllegalStateException("Too many receivers, total of " + totalReceiversForApp + ", registered for pid: " + rl.pid + ", callerPackage: " + callerPackage); } //添加到ProcessRecord记录中 rl.app.receivers.add(rl); } else { try { receiver.asBinder().linkToDeath(rl, 0); } catch (RemoteException e) { return sticky; } rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); } ... //新建BroadcastFilter,并添加到BroadcastList BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId, permission, callingUid, userId, instantApp, visibleToInstantApps); if (rl.containsFilter(filter)) { ... } else { rl.add(bf); //添加到接收者解析器 mReceiverResolver.addFilter(bf); } // Enqueue broadcasts for all existing stickies that match // this filter. //分析三:对匹配到action的粘性广播进行广播 if (allSticky != null) { ArrayList receivers = new ArrayList(); receivers.add(bf); final int stickyCount = allSticky.size(); for (int i = 0; i < stickyCount; i++) { Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, null, -1, -1, false, null, null, OP_NONE, null, receivers, null, 0, null, null, false, true, true, -1, false, false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */); queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } } return sticky; } }
广播的解注册
回到
ContextWrapper的
unregisterReceiver函数。
#ContextWrapper public void unregisterReceiver(BroadcastReceiver receiver) { mBase.unregisterReceiver(receiver); } #ContextImpl public void unregisterReceiver(BroadcastReceiver receiver) { if (mPackageInfo != null) { IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( getOuterContext(), receiver); try { ActivityManager.getService().unregisterReceiver(rd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } }
这里通过
receiver和
context获得
IIntentReceiver实例
rd,然后调用AMS的
unregisterReceiver函数。其中
LoadedApk的
forgetReceiverDispatcher函数,主要是从
mReceivers获取
IIntentReceiver的实例,并将
receiver对应的内容从缓存移除。
AMS的
unregisterReceiver函数。主要是将注册过程添加到
mRegisteredReceivers、
ProcessProcess.Receivers、
mReceiverResolver中对应的内容移除。并终止正在发送的广播。
public void unregisterReceiver(IIntentReceiver receiver) { ... final long origId = Binder.clearCallingIdentity(); try { boolean doTrim = false; synchronized(this) { //获得当前对应的ReceiverList ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl != null) { //默认情况为null,看看广播发送是否会赋值 //从处理逻辑来看,就是广播内容 final BroadcastRecord r = rl.curBroadcast; if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) { final boolean doNext = r.queue.finishReceiverLocked( r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); if (doNext) { doTrim = true; r.queue.processNextBroadcast(false); } } //从processRecord中移除 if (rl.app != null) { rl.app.receivers.remove(rl); } //从mRegisteredReceivers和mReceiverResolver移除 removeReceiverLocked(rl); if (rl.linkedToDeath) { rl.linkedToDeath = false; rl.receiver.asBinder().unlinkToDeath(rl, 0); } } } // If we actually concluded any broadcasts, we might now be able // to trim the recipients' apps from our working set if (doTrim) { trimApplications(OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER); return; } } finally { Binder.restoreCallingIdentity(origId); } } void removeReceiverLocked(ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); for (int i = rl.size() - 1; i >= 0; i--) { mReceiverResolver.removeFilter(rl.get(i)); } }
广播的发送
定位到
ContextWrapper的
sendBroadcast函数。
public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); } public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntentWithFeature(mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, nul