" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android廣播Broadcast的啟動流程

 更新時間:2023年03月30日 15:05:38   作者:新小夢  
這篇文章主要為大家介紹了Android廣播Broadcast啟動流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

本文整體閱讀下來相對ActivityService的啟動流程較容易,比較貼近我們日常代碼開發(fā)習慣。我們曾經(jīng)有個整機項目,多個APP跨進程交互,本來想采用AIDL進行的,但最終考慮到項目工期和其他同事的能力,最終在采用廣播方式進行IPC。

那時,自己也在想,這么多個APP相互發(fā)信息,數(shù)據(jù)量也大,對整機性能有影響么?會不會存在丟失和內存問題。一臉茫然,網(wǎng)上也不會有類似信息告訴總結這種情況,本文也不會總結這個答案,因為看完之后心中自然有數(shù)了。

在AMS中持有集合用于存儲所有的廣播,應用程序可以從向其注冊和解注冊廣播。當應用發(fā)送廣播時,AMS檢查相關權限和特殊的Intent。然后再根據(jù)對應IntentFilter匹配到一個或多個Receiver,在應用進程回調其onReceive函數(shù)。

閱讀源碼本身就是一份苦活,不可能一次就讀懂,或者了解透的。只有反復的閱讀,輸入與輸出,才會越來越輕松。所以個人建議,先粗讀,了解個大概的思路就行。收藏或點贊,等自己ready,再好好結合源碼閱讀。一定要Fuck Code!

廣播的注冊

我們常在ActivityService、甚至Application中調用registerReceiver函數(shù)來注冊動態(tài)廣播,該函數(shù)其實來自它們共同的父類ContextWrapper中。ContextWrapperContext的子類,我們會在介紹Context的文章介紹它們的關系。

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ù),調用了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();
        }
    }

分析一:

傳遞進來的BroadcastReceiver不為null,LoadedApk類型的mPackageInfo只要應用進程啟動,該屬性就會被賦值,context這里指向Activity。schedulernull,賦值為主線程的H類型mH對象。分析一,主要通過上面的變量來獲得IIntentReceiver類型rd對象。

getReceiverDispatcher函數(shù)先從緩存檢測是否有相同類型的BroadcastReceiver對應的ReceiverDispatcher。沒有的話,則新建并緩存起來。 一個context對應多個BroadcastReceiver,而一個BroadcastReceiver對應用一個ReceiverDispatcher。

ReceiverDispatcherLoadedDispatcher的靜態(tài)內部類,其內部還有一個AIDL類型本地實現(xiàn)靜態(tài)類InnerReceiver。在ReceiverDispatcher的構造函數(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ù)的分析二,調用了AMSregisterReceiverWithFeature函數(shù)。

該函數(shù)是Broadcast整個注冊過程結束的地方,根據(jù)新注冊的BroadcastReceiver,處理粘性廣播的發(fā)送和當前注冊Receiver的添加。

分析一:

粘性廣播存儲在AMS的SparseArray<ArrayMap<String, ArrayList<Intent>>>類型的 mStickyBroadcasts中。SparseArraykeyuserId,而ArrayMapkeyaction,valueIntent。即我們可以通過用戶id在mStickyBroadcasts找到當前進程對應所有粘性廣播(和針對所有進程的粘性廣播),然后根據(jù)對應的action找到對應的Intent。這里將他們收集到stickyIntents集合中。

分析二:

所有廣播的接收者BroacastReceiver存儲在AMSHashMap<IBinder, ReceiverList>類型的mRegisteredReceivers中。這里的IBinder類型就是應用進程前面創(chuàng)建的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;
        }
    }

廣播的解注冊

回到ContextWrapperunregisterReceiver函數(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");
    }
}

這里通過receivercontext獲得IIntentReceiver實例rd,然后調用AMS的unregisterReceiver函數(shù)。其中LoadedApkforgetReceiverDispatcher函數(shù),主要是從mReceivers獲取IIntentReceiver的實例,并將receiver對應的內容從緩存移除。

AMS的unregisterReceiver函數(shù)。主要是將注冊過程添加到mRegisteredReceivers、ProcessProcess.Receivers、mReceiverResolver中對應的內容移除。并終止正在發(fā)送的廣播。

   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,看看廣播發(fā)送是否會賦值
					//從處理邏輯來看,就是廣播內容
                    final BroadcastRecord r = rl.curBroadcast;
                    if (r != null &amp;&amp; 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 &gt;= 0; i--) {
        mReceiverResolver.removeFilter(rl.get(i));
    }
}

廣播的發(fā)送

定位到ContextWrappersendBroadcast函數(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();
    }
}

調用AMSbroadcastIntentWithFeature函數(shù)。內部又調用了broadcastIntentLocked函數(shù)。是所有Intent處理的地方,很長很長。有對特殊類型的Intent處理,例如Intent.ACTION_PACKAGE_REMOVEDIntent.ACTION_TIME_CHANGED。該函數(shù)主要將有序和無序廣播接收者(匹配Intent)添加到receivers列表,并創(chuàng)建BroadcastRecord對象r,持有receivers列表。并根據(jù)intent獲得對應的廣播隊列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í)行隊列事務會從其中取出。

scheduleBroadcastsLocked函數(shù)。調用BroadcastHandler類型的mHandler發(fā)送一個BROADCAST_INTENT_MSG消息。

#BroadcastQueue xxm
public void scheduleBroadcastsLocked() {
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

BroadcastHandlerhandleMessage函數(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ù)內容太長了,主要是將粘性廣播和無序廣播發(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ù)。主要進行權限檢查。

#BroadcastQueue xxm
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
        BroadcastFilter filter, boolean ordered, int index) {
    boolean skip = false;
    ...
    //廣播filter進行權限檢查,不通過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īng)啟動,直接調用 app.thread.scheduleRegisteredReceiver,如果未啟動,則直接回調 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īng)啟動,則調用ApplicationThreadscheduleRegisteredReceiver函數(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);
}       

調用了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();
        }
    }
}

調用了分析 一ReceiverDispatcherperformReceive函數(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將相關數(shù)據(jù)封裝成內部類Args類型的args,然后在分析2通過Handler類型的mActivityThread執(zhí)行getRunnable返回的Runable對象的run函數(shù)。這時切換到應用進程的主線程。

Args.getRunnable函數(shù)回調了我們注冊廣播是復寫的onReceiver函數(shù)。

public final Runnable getRunnable() {
    return () -> {
			...
            ClassLoader cl = mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
            //調用廣播接收者的onReceive
            receiver.onReceive(mContext, intent);
            ...
      }
}

總結

大道至簡,所謂注冊就是在每個地方維持一個集合,實現(xiàn)所謂的增刪改查,根據(jù)業(yè)務需求增加不同邏輯,例如權限檢查,接收者所在進程的狀態(tài)。

以上就是詳解Android廣播Broadcast的啟動流程的詳細內容,更多關于Android Broadcast啟動流程的資料請關注腳本之家其它相關文章!

相關文章

  • Android Activity的生命周期與啟動模式全面解讀

    Android Activity的生命周期與啟動模式全面解讀

    雖然說我們天天都在使用Activity,但是你真的對Activity的生命機制完全了解了嗎?Activity的生命周期方法只有七個,但是其實那只是默認的情況。也就是說在其他情況下,Activity的生命周期可能不會是按照我們以前所知道的流程,這就要說到Activity的啟動模式
    2021-10-10
  • android仿360加速球實現(xiàn)內存釋放

    android仿360加速球實現(xiàn)內存釋放

    本篇文章實現(xiàn)了Android仿360加速球實現(xiàn)內存釋放,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • Android getActivity()為空的問題解決辦法

    Android getActivity()為空的問題解決辦法

    這篇文章主要介紹了Android getActivity()為空的問題解決辦法的相關資料,導致apk空指針崩潰問題,很嚴重的問題,為了解決這問題,上網(wǎng)搜索了很多資料,需要的朋友可以參考下
    2017-07-07
  • Android微信右滑退出功能的實現(xiàn)代碼

    Android微信右滑退出功能的實現(xiàn)代碼

    這篇文章主要介紹了Android微信右滑退出功能的實現(xiàn)代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Android開發(fā)筆記SQLite優(yōu)化記住密碼功能

    Android開發(fā)筆記SQLite優(yōu)化記住密碼功能

    這篇文章主要為大家詳細介紹了Android開發(fā)筆記SQLite優(yōu)化記住密碼功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 如何在原有Android項目中快速集成React Native詳解

    如何在原有Android項目中快速集成React Native詳解

    創(chuàng)建一個React Native項目并寫一個純的 React Native 應用可以參考官方指南。下面這篇文章主要給大家介紹了關于如何在原有Android項目中快速集成React Native的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2017-12-12
  • android遞歸壓縮上傳多張圖片到七牛的實例代碼

    android遞歸壓縮上傳多張圖片到七牛的實例代碼

    本篇文章主要介紹了android遞歸壓縮上傳多張圖片到七牛的實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • android實現(xiàn)快遞跟蹤進度條

    android實現(xiàn)快遞跟蹤進度條

    這篇文章主要為大家詳細介紹了android實現(xiàn)快遞跟蹤進度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Android仿優(yōu)酷視頻的懸浮窗播放效果

    Android仿優(yōu)酷視頻的懸浮窗播放效果

    這篇文章主要介紹了Android仿優(yōu)酷視頻的懸浮窗播放效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • android異步消息機制 從源碼層面解析(2)

    android異步消息機制 從源碼層面解析(2)

    這篇文章主要為大家詳細介紹了android異步消息機制,從源碼層面解析,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09

最新評論