詳解Android廣播Broadcast的啟動流程
正文
本文整體閱讀下來相對Activity和Service的啟動流程較容易,比較貼近我們?nèi)粘4a開發(fā)習(xí)慣。我們曾經(jīng)有個整機(jī)項目,多個APP跨進(jìn)程交互,本來想采用AIDL進(jìn)行的,但最終考慮到項目工期和其他同事的能力,最終在采用廣播方式進(jìn)行IPC。
那時,自己也在想,這么多個APP相互發(fā)信息,數(shù)據(jù)量也大,對整機(jī)性能有影響么?會不會存在丟失和內(nèi)存問題。一臉茫然,網(wǎng)上也不會有類似信息告訴總結(jié)這種情況,本文也不會總結(jié)這個答案,因為看完之后心中自然有數(shù)了。
在AMS中持有集合用于存儲所有的廣播,應(yīng)用程序可以從向其注冊和解注冊廣播。當(dāng)應(yīng)用發(fā)送廣播時,AMS檢查相關(guān)權(quán)限和特殊的Intent。然后再根據(jù)對應(yīng)IntentFilter匹配到一個或多個Receiver,在應(yīng)用進(jìn)程回調(diào)其onReceive函數(shù)。
閱讀源碼本身就是一份苦活,不可能一次就讀懂,或者了解透的。只有反復(fù)的閱讀,輸入與輸出,才會越來越輕松。所以個人建議,先粗讀,了解個大概的思路就行。收藏或點贊,等自己ready,再好好結(jié)合源碼閱讀。一定要Fuck Code!
廣播的注冊
我們常在Activity或Service、甚至Application中調(diào)用registerReceiver函數(shù)來注冊動態(tài)廣播,該函數(shù)其實來自它們共同的父類ContextWrapper中。ContextWrapper是Context的子類,我們會在介紹Context的文章介紹它們的關(guān)系。
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
這里Context類型的mBase,在Activity的創(chuàng)建過程實際被賦值為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);
}
經(jīng)過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)來的BroadcastReceiver不為null,LoadedApk類型的mPackageInfo只要應(yīng)用進(jìn)程啟動,該屬性就會被賦值,context這里指向Activity。scheduler為null,賦值為主線程的H類型mH對象。分析一,主要通過上面的變量來獲得IIntentReceiver類型rd對象。
getReceiverDispatcher函數(shù)先從緩存檢測是否有相同類型的BroadcastReceiver對應(yīng)的ReceiverDispatcher。沒有的話,則新建并緩存起來。 一個context對應(yīng)多個BroadcastReceiver,而一個BroadcastReceiver對應(yīng)用一個ReceiverDispatcher。
ReceiverDispatcher是LoadedDispatcher的靜態(tài)內(nèi)部類,其內(nèi)部還有一個AIDL類型本地實現(xiàn)靜態(tài)類InnerReceiver。在ReceiverDispatcher的構(gòu)造函數(shù)中會創(chuàng)建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函數(shù)的分析二,調(diào)用了AMS的registerReceiverWithFeature函數(shù)。
該函數(shù)是Broadcast整個注冊過程結(jié)束的地方,根據(jù)新注冊的BroadcastReceiver,處理粘性廣播的發(fā)送和當(dāng)前注冊Receiver的添加。
分析一:
粘性廣播存儲在AMS的SparseArray<ArrayMap<String, ArrayList<Intent>>>類型的 mStickyBroadcasts中。SparseArray的key為userId,而ArrayMap的key為action,value為Intent。即我們可以通過用戶id在mStickyBroadcasts找到當(dāng)前進(jìn)程對應(yīng)所有粘性廣播(和針對所有進(jìn)程的粘性廣播),然后根據(jù)對應(yīng)的action找到對應(yīng)的Intent。這里將他們收集到stickyIntents集合中。
分析二:
所有廣播的接收者BroacastReceiver存儲在AMS類 HashMap<IBinder, ReceiverList>類型的mRegisteredReceivers中。這里的IBinder類型就是應(yīng)用進(jìn)程前面創(chuàng)建的InnerReceiver類實例在AMS的引用。因為廣播接收者BroadcastReceiver對應(yīng)一個或多個Broadcast,所以這里通過繼承自ArrayList<BroadcastFilter>的ReceiverList來表達(dá)這種關(guān)系。通過BroadcastFilter來表示當(dāng)前接收者感興趣的廣播。
分析三:
對匹配到的粘性Intent進(jìn)入廣播隊列廣播。
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)前注冊廣播中感興趣的action列表
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
//從歷史粘性廣播中查找與當(dāng)前注冊的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)前注冊廣播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的粘性廣播進(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;
}
}
廣播的解注冊
回到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");
}
}
這里通過receiver和context獲得IIntentReceiver實例rd,然后調(diào)用AMS的unregisterReceiver函數(shù)。其中LoadedApk的forgetReceiverDispatcher函數(shù),主要是從mReceivers獲取IIntentReceiver的實例,并將receiver對應(yīng)的內(nèi)容從緩存移除。
AMS的unregisterReceiver函數(shù)。主要是將注冊過程添加到mRegisteredReceivers、ProcessProcess.Receivers、mReceiverResolver中對應(yīng)的內(nèi)容移除。并終止正在發(fā)送的廣播。
public void unregisterReceiver(IIntentReceiver receiver) {
...
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
synchronized(this) {
//獲得當(dāng)前對應(yīng)的ReceiverList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
//默認(rèn)情況為null,看看廣播發(fā)送是否會賦值
//從處理邏輯來看,就是廣播內(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處理的地方,很長很長。有對特殊類型的Intent處理,例如Intent.ACTION_PACKAGE_REMOVED和Intent.ACTION_TIME_CHANGED。該函數(shù)主要將有序和無序廣播接收者(匹配Intent)添加到receivers列表,并創(chuàng)建BroadcastRecord對象r,持有receivers列表。并根據(jù)intent獲得對應(yīng)的廣播隊列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;
}
//查詢已注冊的Receiver,在注冊過程會被添加
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
//查詢已注冊的Receiver,在注冊過程會被添加
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) {
...
//通過intent獲得廣播隊列
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對象r添加到ArrayList類型的mParallelBroadcasts,后續(xù)執(zhí)行隊列事務(wù)會從其中取出。
scheduleBroadcastsLocked函數(shù)。調(diào)用BroadcastHandler類型的mHandler發(fā)送一個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)容太長了,主要是將粘性廣播和無序廣播發(fā)送給接收者。這里只看函數(shù)前半部分對無序廣播的處理。其中無序廣播是從mParallelBroadcasts取出所有廣播,并遍歷每個廣播的過濾器filter,將廣播和廣播filter傳遞給deliverToRegisteredReceiverLocked函數(shù)
#BroadcastQueue xxm
if (fromMsg) {
mBroadcastsScheduled = false;
}
//遍歷無序廣播數(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);
//開始傳遞廣播
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)限檢查,不通過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)啟動,直接調(diào)用 app.thread.scheduleRegisteredReceiver,如果未啟動,則直接回調(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)啟動,則調(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通過Handler類型的mActivityThread執(zhí)行getRunnable返回的Runable對象的run函數(shù)。這時切換到應(yīng)用進(jìn)程的主線程。
Args.getRunnable函數(shù)回調(diào)了我們注冊廣播是復(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é)
大道至簡,所謂注冊就是在每個地方維持一個集合,實現(xiàn)所謂的增刪改查,根據(jù)業(yè)務(wù)需求增加不同邏輯,例如權(quán)限檢查,接收者所在進(jìn)程的狀態(tài)。
以上就是詳解Android廣播Broadcast的啟動流程的詳細(xì)內(nèi)容,更多關(guān)于Android Broadcast啟動流程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android Activity的生命周期與啟動模式全面解讀
雖然說我們天天都在使用Activity,但是你真的對Activity的生命機(jī)制完全了解了嗎?Activity的生命周期方法只有七個,但是其實那只是默認(rèn)的情況。也就是說在其他情況下,Activity的生命周期可能不會是按照我們以前所知道的流程,這就要說到Activity的啟動模式2021-10-10
android仿360加速球?qū)崿F(xiàn)內(nèi)存釋放
本篇文章實現(xiàn)了Android仿360加速球?qū)崿F(xiàn)內(nèi)存釋放,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
Android getActivity()為空的問題解決辦法
這篇文章主要介紹了Android getActivity()為空的問題解決辦法的相關(guān)資料,導(dǎo)致apk空指針崩潰問題,很嚴(yán)重的問題,為了解決這問題,上網(wǎng)搜索了很多資料,需要的朋友可以參考下2017-07-07
Android開發(fā)筆記SQLite優(yōu)化記住密碼功能
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)筆記SQLite優(yōu)化記住密碼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
如何在原有Android項目中快速集成React Native詳解
創(chuàng)建一個React Native項目并寫一個純的 React Native 應(yīng)用可以參考官方指南。下面這篇文章主要給大家介紹了關(guān)于如何在原有Android項目中快速集成React Native的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12

