文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

ActivityManagerService广播怎么注册与发送

2023-07-05 08:33

关注

今天小编给大家分享一下ActivityManagerService广播怎么注册与发送的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

注册广播接收器

广播接收器可以分为动态和静态,静态广播接收器就是在 AndroidManifest.xml 中注册的,而动态的广播接收器是在代码中通过 Context#registerReceiver() 注册的。

静态广播接收器,在发送广播时,服务端会从 PKMS 中收集,而动态的广播接收器,需要接收方发送给服务端。因此,下面只分析动态广播接收器的注册过程

// ContextImpl.javapublic Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,        IntentFilter filter, String broadcastPermission, Handler scheduler) {    return registerReceiverInternal(receiver, user.getIdentifier(),            filter, broadcastPermission, scheduler, getOuterContext(), 0);}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) {            // 默认主线程 Handler            if (scheduler == null) {                scheduler = mMainThread.getHandler();            }            // 1. 获取 IIntentReceiver 对象            // 其实这里获取的就是一个 Binder 对象,用于注册给 AMS,从而接收广播信息的回调            rd = mPackageInfo.getReceiverDispatcher(                receiver, context, scheduler,                mMainThread.getInstrumentation(), true);        } else {            // ...        }    }    try {        // 2. 向 AMS 注册 IIntentReceiver        final Intent intent = ActivityManager.getService().registerReceiverWithFeature(                mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(),                AppOpsManager.toReceiverId(receiver), rd, filter, broadcastPermission, userId,                flags);        if (intent != null) {            intent.setExtrasClassLoader(getClassLoader());            intent.prepareToEnterProcess(ActivityThread.isProtectedBroadcast(intent),                    getAttributionSource());        }        return intent;    } catch (RemoteException e) {        throw e.rethrowFromSystemServer();    }}

广播接收方注册接收器的过程如下

当接收方收到来自服务端的广播消息后,会通过 IIntentReceiver 对象,调用 BroadcastReceiver#onReceive() 来处理广播。

现在来看下服务端是如何完成广播接收器的注册工作的

// AcitityManagerService.javapublic Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,        String callerFeatureId, String receiverId, IIntentReceiver receiver,        IntentFilter filter, String permission, int userId, int flags) {    enforceNotIsolatedCaller("registerReceiver");    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) {        // 确保接收方进程存在,并该进程的 uid 和 pid        if (caller != null) {            callerApp = getRecordForAppLOSP(caller);            if (callerApp == null) {                throw new SecurityException(                        "Unable to find app for caller " + caller                        + " (pid=" + Binder.getCallingPid()                        + ") when registering receiver " + receiver);            }            if (callerApp.info.uid != SYSTEM_UID                    && !callerApp.getPkgList().containsKey(callerPackage)                    && !"android".equals(callerPackage)) {                throw new SecurityException("Given caller package " + callerPackage                        + " is not running in process " + callerApp);            }            callingUid = callerApp.info.uid;            callingPid = callerApp.getPid();        } 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);        Iterator<String> actions = filter.actionsIterator();        if (actions == null) {            ArrayList<String> noAction = new ArrayList<String>(1);            noAction.add(null);            actions = noAction.iterator();        }        // Collect stickies of users        int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };        // 遍历 IntentFilter 保存的所有 action,匹配相应的 sticky 广播,并保存到 stickyIntents        // 从这里可以看出,可以先发送 sticky 广播,然后再注册 sticky 广播接收器        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);                    }                }            }        }    }    // 刚才是用 action 匹配 sticky 广播,现在使用 IntentFilter 再次过滤    // 过滤后的 sticky 广播 ,保存到 allSticky    // 因此 allSticky 保存的才是最终完美匹配到的 sticky 广播    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;            }            // If intent has scheme "content", it will need to acccess            // provider that needs to lock mProviderMap in ActivityThread            // and also it may need to wait application response, so we            // cannot lock ActivityManagerService here.            if (filter.match(resolver, intent, true, TAG) >= 0) {                if (allSticky == null) {                    allSticky = new ArrayList<Intent>();                }                allSticky.add(intent);            }        }    }    // The first sticky in the list is returned directly back to the client.    // 从这里可以看出,如果注册的广播接收器为 null,那么表示要获取最近一次 sticky 广播的数据    Intent sticky = allSticky != null ? allSticky.get(0) : null;    if (receiver == null) {        return sticky;    }    // ...    synchronized (this) {        IApplicationThread thread;        // 注意学会这里的操作,如何判断原来的进程已经死亡        if (callerApp != null && ((thread = callerApp.getThread()) == null                || thread.asBinder() != caller.asBinder())) {            // Original caller already died            return null;        }        // 1. mRegisteredReceivers 建立客户端与服务端的广播接收器的映射        // 客户端注册的广播接收器是 IIntentReceiver, 而服务端的是 ReceiverList        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.mReceivers.numberOfReceivers();                if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {                    throw new IllegalStateException("Too many receivers, total of "                            + totalReceiversForApp + ", registered for pid: "                            + rl.pid + ", callerPackage: " + callerPackage);                }                // ProcessRecord#mReceivers 保存 ReceiverList                rl.app.mReceivers.addReceiver(rl);            } else {                // ...            }            mRegisteredReceivers.put(receiver.asBinder(), rl);        } else {            // ...        }        // 2. 创建服务端的广播过滤器 BroadcastFilter,并保存到 mReceiverResolver        BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,                receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps);        if (rl.containsFilter(filter)) {            Slog.w(TAG, "Receiver with filter " + filter                    + " already registered for pid " + rl.pid                    + ", callerPackage is " + callerPackage);        } else {            // ReceiverList 是 ArrayList 子类,之所以用一个列表保存 BroadcastFilter            // 是因为在注册广播接收器时,可以为同一个广播接收器匹配多个过滤器            rl.add(bf);            if (!bf.debugCheck()) {                Slog.w(TAG, "==> For Dynamic broadcast");            }            // 解析过滤器的数据,然后用相应的数据结构保存            mReceiverResolver.addFilter(bf);        }        // Enqueue broadcasts for all existing stickies that match        // this filter.        // 注意,这里处理的情况是,注册的 sticky 广播接收器不为 null        // 那么把匹配到的 sticky 广播,发送给这个广播接收器        // 是不是非常有意思,注册 sticky 广播接收器,就能立即收到广播,这得益于 sticky 广播被缓存        if (allSticky != null) {            // 很奇怪,BroadcastFilter 怎么是广播接收器呢?            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, null, OP_NONE, null, receivers,                        null, 0, null, null, false, true, true, -1, false, null,                        false );                queue.enqueueParallelBroadcastLocked(r);                queue.scheduleBroadcastsLocked();            }        }        return sticky;    }}

服务端对于动态注册的广播接收器的处理过程如下

这些数据结构都是相互关联的,有何种用意呢?当发送方发送广播到 AMS,AMS 会使用 mReceiverResolver 匹配 BroadcastFilter,BroadcastFilter 找到 ReceiverList,ReceiverList 找到 IIntentReceiver,IIntentReceiver 发送广播给接收方。

另外,由于 sticky 广播是会被缓存的,当注册 sticky 广播的接收器时,有以下两种处理方式

发送广播

发送广播的方法,有多个重载方法,挑选一个最简单的来分析,如下

// ContextImpl.javapublic 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, null ,                null, AppOpsManager.OP_NONE, null, false, false, getUserId());    } catch (RemoteException e) {        throw e.rethrowFromSystemServer();    }}
// ActivityManagerService.javapublic final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,        Intent intent, String resolvedType, IIntentReceiver resultTo,        int resultCode, String resultData, Bundle resultExtras,        String[] requiredPermissions, String[] excludedPermissions,        String[] excludedPackages, int appOp, Bundle bOptions,        boolean serialized, boolean sticky, int userId) {    enforceNotIsolatedCaller("broadcastIntent");    synchronized(this) {        intent = verifyBroadcastLocked(intent);        final ProcessRecord callerApp = getRecordForAppLOSP(caller);        final int callingPid = Binder.getCallingPid();        final int callingUid = Binder.getCallingUid();        final long origId = Binder.clearCallingIdentity();        try {            return broadcastIntentLocked(callerApp,                    callerApp != null ? callerApp.info.packageName : null, callingFeatureId,                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,                    requiredPermissions, excludedPermissions, excludedPackages, appOp, bOptions,                    serialized, sticky, callingPid, callingUid, callingUid, callingPid, userId);        } finally {            Binder.restoreCallingIdentity(origId);        }    }}final int broadcastIntentLocked(ProcessRecord callerApp,        String callerPackage, String callerFeatureId, Intent intent, String resolvedType,        IIntentReceiver resultTo, int resultCode, String resultData,        Bundle resultExtras, String[] requiredPermissions, String[] excludedPermissions,        String[] excludedPackages, int appOp, Bundle bOptions, boolean ordered,        boolean sticky, int callingPid,        int callingUid, int realCallingUid, int realCallingPid, int userId) {    return broadcastIntentLocked(callerApp, callerPackage, callerFeatureId, intent,            resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,            excludedPermissions, excludedPackages, appOp, bOptions, ordered, sticky, callingPid,            callingUid, realCallingUid, realCallingPid, userId,            false ,            null , null );}final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,        @Nullable String callerFeatureId, Intent intent, String resolvedType,        IIntentReceiver resultTo, int resultCode, String resultData,        Bundle resultExtras, String[] requiredPermissions,        String[] excludedPermissions, String[] excludedPackages, int appOp, Bundle bOptions,        boolean ordered, boolean sticky, int callingPid, int callingUid,        int realCallingUid, int realCallingPid, int userId,        boolean allowBackgroundActivityStarts,        @Nullable IBinder backgroundActivityStartsToken,        @Nullable int[] broadcastAllowList) {    // 克隆一个 Intent,防止原始 intent 数据被修改    intent = new Intent(intent);    // ...    // If we have not finished booting, don't allow this to launch new processes.    // AMS 还没有启动完成前,广播只能发送给动态注册的广播接收器,这样可以防止拉起新的进程    if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);    }    // ...    final String action = intent.getAction();    BroadcastOptions brOptions = null;    // bOptions 可以解决发送广播的一些限制,例如从后台启动Activity,只有系统 app 才能用到的 API    if (bOptions != null) {        // ...    }    // 限制受保护的广播,只能由系统代码发送    final boolean isProtectedBroadcast;    try {        isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);    } catch (RemoteException e) {        Slog.w(TAG, "Remote exception", e);        return ActivityManager.BROADCAST_SUCCESS;    }    final boolean isCallerSystem;    switch (UserHandle.getAppId(callingUid)) {        case ROOT_UID:        case SYSTEM_UID:        case PHONE_UID:        case BLUETOOTH_UID:        case NFC_UID:        case SE_UID:        case NETWORK_STACK_UID:            isCallerSystem = true;            break;        default:            isCallerSystem = (callerApp != null) && callerApp.isPersistent();            break;    }    if (!isCallerSystem) {        if (isProtectedBroadcast) {            String msg = "Permission Denial: not allowed to send broadcast "                    + action + " from pid="                    + callingPid + ", uid=" + callingUid;            Slog.w(TAG, msg);            throw new SecurityException(msg);        } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)                || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {            // ...        }    }    boolean timeoutExempt = false;    if (action != null) {        // 如果系统配置文件中允许发送这个后台广播,那么添加 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND 标志位        // 例如 frameworks/base/data/etc/framework-sysconfig.xml 允许发送如下后台广播        // <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" />        if (getBackgroundLaunchBroadcasts().contains(action)) {            if (DEBUG_BACKGROUND_CHECK) {                Slog.i(TAG, "Broadcast action " + action + " forcing include-background");            }            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);        }        switch (action) {            // 对一些特殊的广播进行处理...        }    }    // 1. 缓存 sticky 广播到 mStickyBroadcasts    if (sticky) {        // 检查权限        if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,                callingPid, callingUid)                != PackageManager.PERMISSION_GRANTED) {            String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="                    + callingPid + ", uid=" + callingUid                    + " requires " + android.Manifest.permission.BROADCAST_STICKY;            Slog.w(TAG, msg);            throw new SecurityException(msg);        }        if (requiredPermissions != null && requiredPermissions.length > 0) {            Slog.w(TAG, "Can't broadcast sticky intent " + intent                    + " and enforce permissions " + Arrays.toString(requiredPermissions));            return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;        }        if (intent.getComponent() != null) {            throw new SecurityException(                    "Sticky broadcasts can't target a specific component");        }        // 确保使用 userId 发送的 sticky 广播,不会与使用 USER_ALL 发送的 sticky 广播有冲突        if (userId != UserHandle.USER_ALL) {            ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(                    UserHandle.USER_ALL);            if (stickies != null) {                ArrayList<Intent> list = stickies.get(intent.getAction());                if (list != null) {                    int N = list.size();                    int i;                    for (i=0; i<N; i++) {                        if (intent.filterEquals(list.get(i))) {                            throw new IllegalArgumentException(                                    "Sticky broadcast " + intent + " for user "                                    + userId + " conflicts with existing global broadcast");                        }                    }                }            }        }        // 获取 userId 对应的 sticky 广播缓存,并把这个stikcy广播添加/替换到缓存中        ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);        if (stickies == null) {            stickies = new ArrayMap<>();            mStickyBroadcasts.put(userId, stickies);        }        ArrayList<Intent> list = stickies.get(intent.getAction());        if (list == null) {            list = new ArrayList<>();            stickies.put(intent.getAction(), list);        }        final int stickiesCount = list.size();        int i;        // 存在就替换        for (i = 0; i < stickiesCount; i++) {            if (intent.filterEquals(list.get(i))) {                // This sticky already exists, replace it.                list.set(i, new Intent(intent));                break;            }        }        // 不存在就添加        if (i >= stickiesCount) {            list.add(new Intent(intent));        }    }    int[] users;    if (userId == UserHandle.USER_ALL) {        // 如果以 USER_ALL 名字发送,那么获取所有的启动的 user        users = mUserController.getStartedUserArray();    } else {        users = new int[] {userId};    }    // Figure out who all will receive this broadcast.    // 现在开始找出谁需要接收这个广播    List receivers = null;    List<BroadcastFilter> registeredReceivers = null;    // 2. 收集动态和静态广播接收器    // Intent.FLAG_RECEIVER_REGISTERED_ONLY 表示广播只能发送给动态注册的广播接收器    // 没有指定这个标志位,那么就需要收集静态注册的广播接收器    if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)             == 0) {        // receivers 此时保存的是静态广播接收器        receivers = collectReceiverComponents(                intent, resolvedType, callingUid, users, broadcastAllowList);    }    if (intent.getComponent() == null) {        if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {            // ...以 USER_ALL 身份,从 shell 发送的广播,那么需要获取所有用户注册的广播接收器        } else {            // 收集单个用户注册的动态广播接收器            registeredReceivers = mReceiverResolver.queryIntent(intent,                    resolvedType, false , userId);        }    }    // 是否替换即将发送的广播    final boolean replacePending =            (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;    if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()            + " replacePending=" + replacePending);    // broadcastAllowList 是能接收广播 app 白名单    // 如果收集的动态注册的广播接收器,不属于白名单中的 app,那么移除它    if (registeredReceivers != null && broadcastAllowList != null) {        for (int i = registeredReceivers.size() - 1; i >= 0; i--) {            final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);            if (owningAppId >= Process.FIRST_APPLICATION_UID                    && Arrays.binarySearch(broadcastAllowList, owningAppId) < 0) {                registeredReceivers.remove(i);            }        }    }    // 3. 对于非有序广播(包括sticky广播),先"并行"地发送给动态广播接收器    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;    if (!ordered && NR > 0) {        if (isCallerSystem) {            checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,                    isProtectedBroadcast, registeredReceivers);        }        final BroadcastQueue queue = broadcastQueueForIntent(intent);        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,                callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,                requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,                registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered,                sticky, false, userId, allowBackgroundActivityStarts,                backgroundActivityStartsToken, timeoutExempt);        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);        final boolean replaced = replacePending                && (queue.replaceParallelBroadcastLocked(r) != null);        // Note: We assume resultTo is null for non-ordered broadcasts.        if (!replaced) {            queue.enqueueParallelBroadcastLocked(r);            queue.scheduleBroadcastsLocked();        }        registeredReceivers = null;        // 注意,对于发送非有序广播,当把广播发送给动态接收器后, NR 重置为 0        NR = 0;    }    // 4. 对于有序广播,按照优先级从高到低的顺序,合并静态和动态广播接收器到 receivers    int ir = 0;    // receivers 收集的是静态注册的广播接收器    if (receivers != null) {        // ...        // NT 表示静态广播接收器的数量        int NT = receivers != null ? receivers.size() : 0;        int it = 0;        ResolveInfo curt = null;        BroadcastFilter curr = null;        // 注意 NR 的值,前面发送非有序广播给动态接收器时,NR 重置为 0        // 如果此时 NR 还不为 0, 那么表示发送的是有序广播        // 那么根据广播的优先级,按照从高到低的顺序,把动态广播接收器和静态广播接收器,合并到 receivers        while (it < NT && ir < NR) {            if (curt == null) {                curt = (ResolveInfo)receivers.get(it);            }            if (curr == null) {                curr = registeredReceivers.get(ir);            }            if (curr.getPriority() >= curt.priority) {                // Insert this broadcast record into the final list.                receivers.add(it, curr);                ir++;                curr = null;                it++;                NT++;            } else {                // Skip to the next ResolveInfo in the final list.                it++;                curt = null;            }        }    }    while (ir < NR) {        if (receivers == null) {            receivers = new ArrayList();        }        receivers.add(registeredReceivers.get(ir));        ir++;    }    if (isCallerSystem) {        checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,                isProtectedBroadcast, receivers);    }    // 5. “序列化”地发送广播    // 注意,这里分两种情况    // 如果发送的非有序广播,那么 receivers 只保存了静态注册的广播接收器    // 如果发送的是有序广播,那么 receivers 保存了静态和动态注册的广播接收器    if ((receivers != null && receivers.size() > 0)            || resultTo != null) {        BroadcastQueue queue = broadcastQueueForIntent(intent);        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,                callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,                requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,                receivers, resultTo, resultCode, resultData, resultExtras,                ordered, sticky, false, userId, allowBackgroundActivityStarts,                backgroundActivityStartsToken, timeoutExempt);        final BroadcastRecord oldRecord =                replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;        if (oldRecord != null) {            // 处理替换广播的情况 ....        } else {            queue.enqueueOrderedBroadcastLocked(r);            queue.scheduleBroadcastsLocked();        }    } else {        // 没有找到接收广播的接收器,简单记录下这个发送广播的操作 ...    }    return ActivityManager.BROADCAST_SUCCESS;}

这段代码设计的并不是很好,很多细节都杂糅到一个方法中。对于一些细节,我进行了详细的注释,有兴趣的读者可以自行研究,而本文只关心发送广播的主要流程。

我不打算按照代码的逻辑来讲解流程,我自己总结了一套流程。

对于非有序广播(包括 sticky 广播),发送流程如下

为何要把非有序广播(包括 sticky 广播)优先发送给动态接收器?最简单的理由就是,不需要先拉起进程!因为"快”,所以先发送。

对于有序广播,发送的流程如下

有序广播,为何不先发送给动态接收器呢?因为它强调一个“有序”,所以要根据优先级来发送。

对于 sticky 广播,由于它的特性,是需要对它的广播 Intent 进行缓存的。根据前面注册广播接收器的分析,当注册的广播接收器匹配到缓存的 sticky 广播 Intent,那么会立即返回数据给接收方,无论是通过函数的返回值,还是直接调用 BroadcastReceiver#onReceive()。

以上就是“ActivityManagerService广播怎么注册与发送”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯