詳解Android廣播Broadcast的啟動(dòng)流程
正文
本文整體閱讀下來(lái)相對(duì)Activity
和Service
的啟動(dòng)流程較容易,比較貼近我們?nèi)粘4a開(kāi)發(fā)習(xí)慣。我們?cè)?jīng)有個(gè)整機(jī)項(xiàng)目,多個(gè)APP跨進(jìn)程交互,本來(lái)想采用AIDL進(jìn)行的,但最終考慮到項(xiàng)目工期和其他同事的能力,最終在采用廣播方式進(jìn)行IPC。
那時(shí),自己也在想,這么多個(gè)APP相互發(fā)信息,數(shù)據(jù)量也大,對(duì)整機(jī)性能有影響么?會(huì)不會(huì)存在丟失和內(nèi)存問(wèn)題。一臉茫然,網(wǎng)上也不會(huì)有類似信息告訴總結(jié)這種情況,本文也不會(huì)總結(jié)這個(gè)答案,因?yàn)榭赐曛笮闹凶匀挥袛?shù)了。
在AMS中持有集合用于存儲(chǔ)所有的廣播,應(yīng)用程序可以從向其注冊(cè)和解注冊(cè)廣播。當(dāng)應(yīng)用發(fā)送廣播時(shí),AMS檢查相關(guān)權(quán)限和特殊的Intent
。然后再根據(jù)對(duì)應(yīng)IntentFilter
匹配到一個(gè)或多個(gè)Receiver
,在應(yīng)用進(jìn)程回調(diào)其onReceive
函數(shù)。
閱讀源碼本身就是一份苦活,不可能一次就讀懂,或者了解透的。只有反復(fù)的閱讀,輸入與輸出,才會(huì)越來(lái)越輕松。所以個(gè)人建議,先粗讀,了解個(gè)大概的思路就行。收藏或點(diǎn)贊,等自己ready,再好好結(jié)合源碼閱讀。一定要Fuck Code!
廣播的注冊(cè)
我們常在Activity
或Service
、甚至Application
中調(diào)用registerReceiver
函數(shù)來(lái)注冊(cè)動(dòng)態(tài)廣播,該函數(shù)其實(shí)來(lái)自它們共同的父類ContextWrapper
中。ContextWrapper
是Context
的子類,我們會(huì)在介紹Context
的文章介紹它們的關(guān)系。
public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
這里Context
類型的mBase
,在Activity
的創(chuàng)建過(guò)程實(shí)際被賦值為ContextImpl
實(shí)例。
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); }
經(jīng)過(guò)registerReceiver
重載函數(shù),調(diào)用了registerReceiverInternal
函數(shù)。
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(); } }
分析一:
傳遞進(jìn)來(lái)的BroadcastReceiver
不為null
,LoadedApk
類型的mPackageInfo
只要應(yīng)用進(jìn)程啟動(dòng),該屬性就會(huì)被賦值,context
這里指向Activity
。scheduler
為null
,賦值為主線程的H
類型mH
對(duì)象。分析一,主要通過(guò)上面的變量來(lái)獲得IIntentReceiver
類型rd
對(duì)象。
getReceiverDispatcher
函數(shù)先從緩存檢測(cè)是否有相同類型的BroadcastReceiver
對(duì)應(yīng)的ReceiverDispatcher
。沒(méi)有的話,則新建并緩存起來(lái)。 一個(gè)context
對(duì)應(yīng)多個(gè)BroadcastReceiver
,而一個(gè)BroadcastReceiver
對(duì)應(yīng)用一個(gè)ReceiverDispatcher
。
ReceiverDispatcher
是LoadedDispatcher
的靜態(tài)內(nèi)部類,其內(nèi)部還有一個(gè)AIDL
類型本地實(shí)現(xiàn)靜態(tài)類InnerReceiver
。在ReceiverDispatcher
的構(gòu)造函數(shù)中會(huì)創(chuàng)建InnerReceiver
的實(shí)例。
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
函數(shù)的分析二,調(diào)用了AMS
的registerReceiverWithFeature
函數(shù)。
該函數(shù)是Broadcast
整個(gè)注冊(cè)過(guò)程結(jié)束的地方,根據(jù)新注冊(cè)的BroadcastReceiver
,處理粘性廣播的發(fā)送和當(dāng)前注冊(cè)Receiver
的添加。
分析一:
粘性廣播存儲(chǔ)在AMS的SparseArray<ArrayMap<String, ArrayList<Intent>>>
類型的 mStickyBroadcasts
中。SparseArray
的key
為userId
,而ArrayMap
的key
為action
,value
為Intent
。即我們可以通過(guò)用戶id在mStickyBroadcasts
找到當(dāng)前進(jìn)程對(duì)應(yīng)所有粘性廣播(和針對(duì)所有進(jìn)程的粘性廣播),然后根據(jù)對(duì)應(yīng)的action
找到對(duì)應(yīng)的Intent
。這里將他們收集到stickyIntents
集合中。
分析二:
所有廣播的接收者BroacastReceiver
存儲(chǔ)在AMS
類 HashMap<IBinder, ReceiverList>
類型的mRegisteredReceivers
中。這里的IBinder
類型就是應(yīng)用進(jìn)程前面創(chuàng)建的InnerReceiver
類實(shí)例在AMS的引用。因?yàn)閺V播接收者BroadcastReceiver
對(duì)應(yīng)一個(gè)或多個(gè)Broadcast
,所以這里通過(guò)繼承自ArrayList<BroadcastFilter>
的ReceiverList
來(lái)表達(dá)這種關(guān)系。通過(guò)BroadcastFilter
來(lái)表示當(dāng)前接收者感興趣的廣播。
分析三:
對(duì)匹配到的粘性Intent進(jìn)入廣播隊(duì)列廣播。
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) { //獲得當(dāng)前引用進(jìn)程的ProcessRecord callerApp = getRecordForAppLocked(caller); ... callingUid = callerApp.info.uid; callingPid = callerApp.pid; } else { callerPackage = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); } //是否快應(yīng)用(類似小程序) instantApp = isInstantApp(callerApp, callerPackage, callingUid); userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage); //分析一:當(dāng)前注冊(cè)廣播中感興趣的action列表 Iterator<String> actions = filter.actionsIterator(); if (actions == null) { ArrayList<String> noAction = new ArrayList<String>(1); noAction.add(null); actions = noAction.iterator(); } //從歷史粘性廣播中查找與當(dāng)前注冊(cè)的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; } //當(dāng)前注冊(cè)廣播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或者第一個(gè)粘性intent Intent sticky = allSticky != null ? allSticky.get(0) : null; if (receiver == null) { return sticky; } synchronized (this) { ... //分析二: //從緩存或新建ReceiverList對(duì)象,與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. //分析三:對(duì)匹配到action的粘性廣播進(jìn)行廣播 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; } }
廣播的解注冊(cè)
回到ContextWrapper
的unregisterReceiver
函數(shù)。
#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"); } }
這里通過(guò)receiver
和context
獲得IIntentReceiver
實(shí)例rd
,然后調(diào)用AMS的unregisterReceiver
函數(shù)。其中LoadedApk
的forgetReceiverDispatcher
函數(shù),主要是從mReceivers
獲取IIntentReceiver
的實(shí)例,并將receiver
對(duì)應(yīng)的內(nèi)容從緩存移除。
AMS的unregisterReceiver
函數(shù)。主要是將注冊(cè)過(guò)程添加到mRegisteredReceivers
、ProcessProcess
.Receivers、mReceiverResolver
中對(duì)應(yīng)的內(nèi)容移除。并終止正在發(fā)送的廣播。
public void unregisterReceiver(IIntentReceiver receiver) { ... final long origId = Binder.clearCallingIdentity(); try { boolean doTrim = false; synchronized(this) { //獲得當(dāng)前對(duì)應(yīng)的ReceiverList ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl != null) { //默認(rèn)情況為null,看看廣播發(fā)送是否會(huì)賦值 //從處理邏輯來(lái)看,就是廣播內(nèi)容 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)); } }
廣播的發(fā)送
定位到ContextWrapper
的sendBroadcast
函數(shù)。
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, null, false,false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
調(diào)用AMS
的broadcastIntentWithFeature
函數(shù)。內(nèi)部又調(diào)用了broadcastIntentLocked
函數(shù)。是所有Intent處理的地方,很長(zhǎng)很長(zhǎng)。有對(duì)特殊類型的Intent處理,例如Intent.ACTION_PACKAGE_REMOVED
和Intent.ACTION_TIME_CHANGED
。該函數(shù)主要將有序和無(wú)序廣播接收者(匹配Intent)添加到receivers
列表,并創(chuàng)建BroadcastRecord
對(duì)象r,持有receivers
列表。并根據(jù)intent
獲得對(duì)應(yīng)的廣播隊(duì)列queue
,將r
添加到queue
中,執(zhí)行queue.scheduleBroadcastsLocked
函數(shù)。
#AMS xxm @GuardedBy("this") final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, @Nullable String callerFeatureId, 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 realCallingUid, int realCallingPid, int userId, boolean allowBackgroundActivityStarts, @Nullable int[] broadcastWhitelist) { intent = new Intent(intent); ... int[] users; if (userId == UserHandle.USER_ALL) { // Caller wants broadcast to go to all started users. users = mUserController.getStartedUserArray(); } else { // Caller wants broadcast to go to one specific user. users = new int[] {userId}; } // Figure out who all will receive this broadcast. List receivers = null; List<BroadcastFilter> registeredReceivers = null; // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents( intent, resolvedType, callingUid, users, broadcastWhitelist); } if (intent.getComponent() == null) { if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) { // Query one target user at a time, excluding shell-restricted users for (int i = 0; i < users.length; i++) { if (mUserController.hasUserRestriction( UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) { continue; } //查詢已注冊(cè)的Receiver,在注冊(cè)過(guò)程會(huì)被添加 List<BroadcastFilter> registeredReceiversForUser = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, users[i]); if (registeredReceivers == null) { registeredReceivers = registeredReceiversForUser; } else if (registeredReceiversForUser != null) { registeredReceivers.addAll(registeredReceiversForUser); } } } else { //查詢已注冊(cè)的Receiver,在注冊(cè)過(guò)程會(huì)被添加 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId); } } final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; ... int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { ... //通過(guò)intent獲得廣播隊(duì)列 final BroadcastQueue queue = broadcastQueueForIntent(intent); //將所有數(shù)據(jù)都封裝到BroadcastRecord中 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId, allowBackgroundActivityStarts, timeoutExempt); ... final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null); if (!replaced) { //將廣播添加到queue的mParallelBroadcasts數(shù)組列表中 queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } registeredReceivers = null; NR = 0; } ... return ActivityManager.BROADCAST_SUCCESS; }
enqueueParallelBroadcastLocked
函數(shù)將BroadcastRecord
對(duì)象r
添加到ArrayList
類型的mParallelBroadcasts
,后續(xù)執(zhí)行隊(duì)列事務(wù)會(huì)從其中取出。
scheduleBroadcastsLocked
函數(shù)。調(diào)用BroadcastHandler
類型的mHandler
發(fā)送一個(gè)BROADCAST_INTENT_MSG
消息。
#BroadcastQueue xxm public void scheduleBroadcastsLocked() { if (mBroadcastsScheduled) { return; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true; }
BroadcastHandler
的handleMessage
函數(shù)。執(zhí)行了processNextBroadcast
函數(shù)。
#BroadcastHandler xxm public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { processNextBroadcast(true); } break; case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true); } } break; } }
processNextBroadcast
函數(shù)內(nèi)容太長(zhǎng)了,主要是將粘性廣播和無(wú)序廣播發(fā)送給接收者。這里只看函數(shù)前半部分對(duì)無(wú)序廣播的處理。其中無(wú)序廣播是從mParallelBroadcasts
取出所有廣播,并遍歷每個(gè)廣播的過(guò)濾器filter
,將廣播和廣播filter
傳遞給deliverToRegisteredReceiverLocked
函數(shù)
#BroadcastQueue xxm if (fromMsg) { mBroadcastsScheduled = false; } //遍歷無(wú)序廣播數(shù)組 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); //開(kāi)始傳遞廣播 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); } addBroadcastToHistoryLocked(r); }
deliverToRegisteredReceiverLocked
函數(shù)。主要進(jìn)行權(quán)限檢查。
#BroadcastQueue xxm private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { boolean skip = false; ... //廣播filter進(jìn)行權(quán)限檢查,不通過(guò)skip=true ... if (skip) { r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED; return; } ... r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED; ... performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); ... }
performReceiveLocked
函數(shù)。如果接收者所在的進(jìn)程已經(jīng)啟動(dòng),直接調(diào)用 app.thread.scheduleRegisteredReceiver
,如果未啟動(dòng),則直接回調(diào) receiver.performReceive
。
#BroadcastQueue xxm void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { if (app != null) { if (app.thread != null) { try { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.getReportedProcState()); } catch (RemoteException ex) { synchronized (mService) { app.scheduleCrash("can't deliver broadcast"); } throw ex; } } else { throw new RemoteException("app.thread must not be null"); } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } }
如果進(jìn)程已經(jīng)啟動(dòng),則調(diào)用ApplicationThread
的scheduleRegisteredReceiver
函數(shù)。
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); receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); }
調(diào)用了LoadedApk.ReceiverDispatcher.InnerReceiver
類的performReceive
函數(shù)。
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final LoadedApk.ReceiverDispatcher rd; if (intent == null) { rd = null; } else { rd = mDispatcher.get(); } if (rd != null) { //分析一 rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { IActivityManager mgr = ActivityManager.getService(); try { if (extras != null) { extras.setAllowFds(false); } mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
調(diào)用了分析 一ReceiverDispatcher
的performReceive
函數(shù)
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { //分析1 final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); ... //分析2 if (intent == null || !mActivityThread.post(args.getRunnable())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); args.sendFinished(mgr); } } }
ReceiverDispatcher.performReceive
函數(shù)中分析1將相關(guān)數(shù)據(jù)封裝成內(nèi)部類Args
類型的args
,然后在分析2通過(guò)Handler
類型的mActivityThread
執(zhí)行getRunnable
返回的Runable
對(duì)象的run
函數(shù)。這時(shí)切換到應(yīng)用進(jìn)程的主線程。
Args.getRunnable
函數(shù)回調(diào)了我們注冊(cè)廣播是復(fù)寫的onReceiver
函數(shù)。
public final Runnable getRunnable() { return () -> { ... ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); //調(diào)用廣播接收者的onReceive receiver.onReceive(mContext, intent); ... } }
總結(jié)
大道至簡(jiǎn),所謂注冊(cè)就是在每個(gè)地方維持一個(gè)集合,實(shí)現(xiàn)所謂的增刪改查,根據(jù)業(yè)務(wù)需求增加不同邏輯,例如權(quán)限檢查,接收者所在進(jìn)程的狀態(tài)。
以上就是詳解Android廣播Broadcast的啟動(dòng)流程的詳細(xì)內(nèi)容,更多關(guān)于Android Broadcast啟動(dòng)流程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android?Service啟動(dòng)綁定流程詳解
- Android framework ATMS啟動(dòng)流程
- Android應(yīng)用啟動(dòng)白屏處理方案詳解
- Android基準(zhǔn)配置文件Baseline?Profile方案提升啟動(dòng)速度
- Android開(kāi)發(fā)InputManagerService創(chuàng)建與啟動(dòng)流程
- Android10 App啟動(dòng)Activity源碼分析
- Android10 App 啟動(dòng)分析進(jìn)程創(chuàng)建源碼解析
- Android?應(yīng)用程序的啟動(dòng)流程示例詳解
相關(guān)文章
Android Activity的生命周期與啟動(dòng)模式全面解讀
雖然說(shuō)我們天天都在使用Activity,但是你真的對(duì)Activity的生命機(jī)制完全了解了嗎?Activity的生命周期方法只有七個(gè),但是其實(shí)那只是默認(rèn)的情況。也就是說(shuō)在其他情況下,Activity的生命周期可能不會(huì)是按照我們以前所知道的流程,這就要說(shuō)到Activity的啟動(dòng)模式2021-10-10android仿360加速球?qū)崿F(xiàn)內(nèi)存釋放
本篇文章實(shí)現(xiàn)了Android仿360加速球?qū)崿F(xiàn)內(nèi)存釋放,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10Android getActivity()為空的問(wèn)題解決辦法
這篇文章主要介紹了Android getActivity()為空的問(wèn)題解決辦法的相關(guān)資料,導(dǎo)致apk空指針崩潰問(wèn)題,很嚴(yán)重的問(wèn)題,為了解決這問(wèn)題,上網(wǎng)搜索了很多資料,需要的朋友可以參考下2017-07-07Android微信右滑退出功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android微信右滑退出功能的實(shí)現(xiàn)代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-01-01Android開(kāi)發(fā)筆記SQLite優(yōu)化記住密碼功能
這篇文章主要為大家詳細(xì)介紹了Android開(kāi)發(fā)筆記SQLite優(yōu)化記住密碼功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07如何在原有Android項(xiàng)目中快速集成React Native詳解
創(chuàng)建一個(gè)React Native項(xiàng)目并寫一個(gè)純的 React Native 應(yīng)用可以參考官方指南。下面這篇文章主要給大家介紹了關(guān)于如何在原有Android項(xiàng)目中快速集成React Native的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼
本篇文章主要介紹了android遞歸壓縮上傳多張圖片到七牛的實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08android實(shí)現(xiàn)快遞跟蹤進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)快遞跟蹤進(jìn)度條,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05