详解Android广播Broadcast的启动流程

目录
  • 正文
  • 广播的注册
  • 广播的解注册
  • 广播的发送
  • 总结

正文

本文整体阅读下来相对ActivityService的启动流程较容易,比较贴近我们日常代码开发习惯。我们曾经有个整机项目,多个APP跨进程交互,本来想采用AIDL进行的,但最终考虑到项目工期和其他同事的能力,最终在采用广播方式进行IPC。

那时,自己也在想,这么多个APP相互发信息,数据量也大,对整机性能有影响么?会不会存在丢失和内存问题。一脸茫然,网上也不会有类似信息告诉总结这种情况,本文也不会总结这个答案,因为看完之后心中自然有数了。

在AMS中持有集合用于存储所有的广播,应用程序可以从向其注册和解注册广播。当应用发送广播时,AMS检查相关权限和特殊的Intent。然后再根据对应IntentFilter匹配到一个或多个Receiver,在应用进程回调其onReceive函数。

阅读源码本身就是一份苦活,不可能一次就读懂,或者了解透的。只有反复的阅读,输入与输出,才会越来越轻松。所以个人建议,先粗读,了解个大概的思路就行。收藏或点赞,等自己ready,再好好结合源码阅读。一定要Fuck Code!

广播的注册

我们常在ActivityService、甚至Application中调用registerReceiver函数来注册动态广播,该函数其实来自它们共同的父类ContextWrapper中。ContextWrapperContext的子类,我们会在介绍Context的文章介绍它们的关系。

public Intent registerReceiver(
    BroadcastReceiver receiver, IntentFilter filter) {
    return mBase.registerReceiver(receiver, filter);
}

这里Context类型的mBase,在Activity的创建过程实际被赋值为ContextImpl实例。

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    return registerReceiver(receiver, filter, null, null);
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
    String broadcastPermission, Handler scheduler) {
	return registerReceiverInternal(receiver, getUserId(),
        	filter, broadcastPermission, scheduler, getOuterContext(), 0);
}

经过registerReceiver重载函数,调用了registerReceiverInternal函数。

    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        //分析一
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
        	分析二:
            final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
                    mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
                    filter, broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

分析一:

传递进来的BroadcastReceiver不为nullLoadedApk类型的mPackageInfo只要应用进程启动,该属性就会被赋值,context这里指向Activityschedulernull,赋值为主线程的H类型mH对象。分析一,主要通过上面的变量来获得IIntentReceiver类型rd对象。

getReceiverDispatcher函数先从缓存检测是否有相同类型的BroadcastReceiver对应的ReceiverDispatcher。没有的话,则新建并缓存起来。 一个context对应多个BroadcastReceiver,而一个BroadcastReceiver对应用一个ReceiverDispatcher

ReceiverDispatcherLoadedDispatcher的静态内部类,其内部还有一个AIDL类型本地实现静态类InnerReceiver。在ReceiverDispatcher的构造函数中会创建InnerReceiver的实例。

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
        Context context, Handler handler,
        Instrumentation instrumentation, boolean registered) {
    synchronized (mReceivers) {
        LoadedApk.ReceiverDispatcher rd = null;
        ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
        if (registered) {
            map = mReceivers.get(context);
            if (map != null) {
                rd = map.get(r);
            }
        }
        if (rd == null) {
            rd = new ReceiverDispatcher(r, context, handler,
                    instrumentation, registered);
            if (registered) {
                if (map == null) {
                    map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
                    mReceivers.put(context, map);
                }
                map.put(r, rd);
            }
        } else {
            rd.validate(context, handler);
        }
        rd.mForgotten = false;
        return rd.getIIntentReceiver();
    }
}

回到registerReceiverInternal函数的分析二,调用了AMSregisterReceiverWithFeature函数。

该函数是Broadcast整个注册过程结束的地方,根据新注册的BroadcastReceiver,处理粘性广播的发送和当前注册Receiver的添加。

分析一:

粘性广播存储在AMS的SparseArray<ArrayMap<String, ArrayList<Intent>>>类型的 mStickyBroadcasts中。SparseArraykeyuserId,而ArrayMapkeyaction,valueIntent。即我们可以通过用户id在mStickyBroadcasts找到当前进程对应所有粘性广播(和针对所有进程的粘性广播),然后根据对应的action找到对应的Intent。这里将他们收集到stickyIntents集合中。

分析二:

所有广播的接收者BroacastReceiver存储在AMSHashMap<IBinder, ReceiverList>类型的mRegisteredReceivers中。这里的IBinder类型就是应用进程前面创建的InnerReceiver类实例在AMS的引用。因为广播接收者BroadcastReceiver对应一个或多个Broadcast,所以这里通过继承自ArrayList<BroadcastFilter>ReceiverList来表达这种关系。通过BroadcastFilter来表示当前接收者感兴趣的广播。

分析三:

对匹配到的粘性Intent进入广播队列广播。

    public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
            String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
            String permission, int userId, int flags) {
        enforceNotIsolatedCaller("registerReceiver");
		//粘性Intent
		ArrayList<Intent> stickyIntents = null;
        ProcessRecord callerApp = null;
        final boolean visibleToInstantApps
                = (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
        int callingUid;
        int callingPid;
        boolean instantApp;
        synchronized(this) {
            if (caller != null) {
            	//获得当前引用进程的ProcessRecord
                callerApp = getRecordForAppLocked(caller);
               	...
                callingUid = callerApp.info.uid;
                callingPid = callerApp.pid;
            } else {
                callerPackage = null;
                callingUid = Binder.getCallingUid();
                callingPid = Binder.getCallingPid();
            }
			//是否快应用(类似小程序)
            instantApp = isInstantApp(callerApp, callerPackage, callingUid);
            userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                    ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
			//分析一:当前注册广播中感兴趣的action列表
            Iterator<String> actions = filter.actionsIterator();
            if (actions == null) {
                ArrayList<String> noAction = new ArrayList<String>(1);
                noAction.add(null);
                actions = noAction.iterator();
            }
			//从历史粘性广播中查找与当前注册的action一致的intent
			//添加到stickyIntents
            // Collect stickies of users
            int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
            while (actions.hasNext()) {
                String action = actions.next();
                for (int id : userIds) {
                    ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
                    if (stickies != null) {
                        ArrayList<Intent> intents = stickies.get(action);
                        if (intents != null) {
                            if (stickyIntents == null) {
                                stickyIntents = new ArrayList<Intent>();
                            }
                            stickyIntents.addAll(intents);
                        }
                    }
                }
            }
        }
		//处理content类型的Intent
        ArrayList<Intent> allSticky = null;
        if (stickyIntents != null) {
            final ContentResolver resolver = mContext.getContentResolver();
            // Look for any matching sticky broadcasts...
            for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                Intent intent = stickyIntents.get(i);
                // Don't provided intents that aren't available to instant apps.
                if (instantApp &&
                        (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                    continue;
                }
                //当前注册广播IntentFilter是否与action一致的intent的匹配
                //处理content类型
                if (filter.match(resolver, intent, true, TAG) >= 0) {
                    if (allSticky == null) {
                        allSticky = new ArrayList<Intent>();
                    }
                    allSticky.add(intent);
                }
            }
        }
        //receiver为null,直接返回null或者第一个粘性intent
        Intent sticky = allSticky != null ? allSticky.get(0) : null;
        if (receiver == null) {
            return sticky;
        }
        synchronized (this) {
            ...
            //分析二:
			//从缓存或新建ReceiverList对象,与Receiver绑定
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                        throw new IllegalStateException("Too many receivers, total of "
                                + totalReceiversForApp + ", registered for pid: "
                                + rl.pid + ", callerPackage: " + callerPackage);
                    }
					//添加到ProcessRecord记录中
                    rl.app.receivers.add(rl);
                } else {
                    try {
                        receiver.asBinder().linkToDeath(rl, 0);
                    } catch (RemoteException e) {
                        return sticky;
                    }
                    rl.linkedToDeath = true;
                }
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
            ...
			//新建BroadcastFilter,并添加到BroadcastList
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            if (rl.containsFilter(filter)) {
                ...
            } else {
                rl.add(bf);
                //添加到接收者解析器
                mReceiverResolver.addFilter(bf);
            }
            // Enqueue broadcasts for all existing stickies that match
            // this filter.
            //分析三:对匹配到action的粘性广播进行广播
            if (allSticky != null) {
                ArrayList receivers = new ArrayList();
                receivers.add(bf);
                final int stickyCount = allSticky.size();
                for (int i = 0; i < stickyCount; i++) {
                    Intent intent = allSticky.get(i);
                    BroadcastQueue queue = broadcastQueueForIntent(intent);
                    BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                            null, null, -1, -1, false, null, null, OP_NONE, null, receivers,
                            null, 0, null, null, false, true, true, -1, false,
                            false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
                    queue.enqueueParallelBroadcastLocked(r);
                    queue.scheduleBroadcastsLocked();
                }
            }
            return sticky;
        }
    }

广播的解注册

回到ContextWrapperunregisterReceiver函数。

#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函数。其中LoadedApkforgetReceiverDispatcher函数,主要是从mReceivers获取IIntentReceiver的实例,并将receiver对应的内容从缓存移除。

AMS的unregisterReceiver函数。主要是将注册过程添加到mRegisteredReceiversProcessProcess.Receivers、mReceiverResolver中对应的内容移除。并终止正在发送的广播。

   public void unregisterReceiver(IIntentReceiver receiver) {
		...
        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doTrim = false;
            synchronized(this) {
            	//获得当前对应的ReceiverList
                ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
                if (rl != null) {
					//默认情况为null,看看广播发送是否会赋值
					//从处理逻辑来看,就是广播内容
                    final BroadcastRecord r = rl.curBroadcast;
                    if (r != null &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));
    }
}

广播的发送

定位到ContextWrappersendBroadcast函数。

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函数。内部又调用了broadcastIntentLocked函数。是所有Intent处理的地方,很长很长。有对特殊类型的Intent处理,例如Intent.ACTION_PACKAGE_REMOVEDIntent.ACTION_TIME_CHANGED。该函数主要将有序和无序广播接收者(匹配Intent)添加到receivers列表,并创建BroadcastRecord对象r,持有receivers列表。并根据intent获得对应的广播队列queue,将r添加到queue中,执行queue.scheduleBroadcastsLocked函数。

#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);
        //将所有数据都封装到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数组列表中
            queue.enqueueParallelBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }
    ...
    return ActivityManager.BROADCAST_SUCCESS;
}

enqueueParallelBroadcastLocked函数将BroadcastRecord对象r添加到ArrayList类型的mParallelBroadcasts,后续执行队列事务会从其中取出。

scheduleBroadcastsLocked函数。调用BroadcastHandler类型的mHandler发送一个BROADCAST_INTENT_MSG消息。

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

BroadcastHandlerhandleMessage函数。执行了processNextBroadcast函数。

#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函数内容太长了,主要是将粘性广播和无序广播发送给接收者。这里只看函数前半部分对无序广播的处理。其中无序广播是从mParallelBroadcasts取出所有广播,并遍历每个广播的过滤器filter,将广播和广播filter传递给deliverToRegisteredReceiverLocked函数

#BroadcastQueue xxm
if (fromMsg) {
    mBroadcastsScheduled = false;
}
//遍历无序广播数组
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函数。主要进行权限检查。

#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函数。如果接收者所在的进程已经启动,直接调用 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);
    }
}

如果进程已经启动,则调用ApplicationThreadscheduleRegisteredReceiver函数。

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函数。

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函数

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函数中分析1将相关数据封装成内部类Args类型的args,然后在分析2通过Handler类型的mActivityThread执行getRunnable返回的Runable对象的run函数。这时切换到应用进程的主线程。

Args.getRunnable函数回调了我们注册广播是复写的onReceiver函数。

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);
            ...
      }
}

总结

大道至简,所谓注册就是在每个地方维持一个集合,实现所谓的增删改查,根据业务需求增加不同逻辑,例如权限检查,接收者所在进程的状态。

以上就是详解Android广播Broadcast的启动流程的详细内容,更多关于Android Broadcast启动流程的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android BroadcastReceiver广播简单使用

    本文实例为大家分享了Android BroadcastReceiver广播使用的具体代码,供大家参考,具体内容如下 静态的BroadcastReceiver 主要代码 public class MyReceiver extends BroadcastReceiver { @Override //接受广播时回调 public void onReceive(Context context, Intent intent) { //接收广播 if(intent != null){ //接收到是什么广播

  • Android四大组件之广播BroadcastReceiver详解

    定义 BroadcastReceiver,"广播接收者"的意思,顾名思义,它就是用来接收来自系统和应用中的广播.在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能:当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作:当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度等等.Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现

  • Android 使用registerReceiver注册BroadcastReceiver案例详解

    android.context.ContextWrapper.registerReceiver public Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter) Register a BroadcastReceiver to be run in the main activity thread. The receiver will be called with any broadcast Intent

  • Android四大组件之BroadcastReceiver详解

    BroadcastReceiver(广播接收器),在Android开发中,BroadcastReceiver的应用场景非常多,属于Android四大组件之一. Android 广播分为两个角色:广播发送者.广播接收者 一. 作用 用于监听 / 接收 应用发出的广播消息,并做出响应 应用场景: 不同组件之间通信(包括应用内 / 不同应用之间) 与 Android 系统在特定情况下的通信(如当电话呼入时.网络可用时) 多线程通信 二.实现原理 Android中的广播使用了设计模式中的观察者模式:基于

  • Android 广播接收器BroadcastReceiver详解

    目录 一.什么是BroadcastReceiver 1.1.作用 1.2.实现原理 二.创建广播接收器 三.注册广播接收器 3.1.静态注册 注册 发送通知 3.2.动态注册 四.系统广播 总结 一.什么是BroadcastReceiver BroadcastReceiver 是安卓系统中四大组件之一,在Android开发中,BroadcastReceiver的应用场景非常多,Android 广播分为两个角色:广播发送者.广播接收者. 1.1.作用 广播接收器用于响应来自其他应用程序或者系统的广

  • Android Broadcast 和 BroadcastReceiver的权限限制方式

    在Android应用开发中,有时会遇到以下两种情况, 1. 一些敏感的广播并不想让第三方的应用收到 : 2. 要限制自己的Receiver接收某广播来源,避免被恶意的同样的ACTION的广播所干扰. 在这些场景下就需要用到广播的权限限制. 第一种场景: 谁有权收我的广播? 在这种情况下,可以在自己应用发广播时添加参数声明Receiver所需的权限. 首先,在Androidmanifest.xml中定义新的权限RECV_XXX,例如: <permission android:name = "

  • Android使用BroadcastReceiver监听网络连接状态的改变

    只需要实现下面2段代码即可实现对网络连接状态的监听,千万别忘了在Manifest.xml里面添加网络访问权限哦. 1.定义广播接收器 NetState.java package huaxa.it.map.net; import huaxa.it.map.demo.MapDemo; import com.baidu.mapapi.map.MapView; import android.content.BroadcastReceiver; import android.content.Context

  • 详解Android广播Broadcast的启动流程

    目录 正文 广播的注册 广播的解注册 广播的发送 总结 正文 本文整体阅读下来相对Activity和Service的启动流程较容易,比较贴近我们日常代码开发习惯.我们曾经有个整机项目,多个APP跨进程交互,本来想采用AIDL进行的,但最终考虑到项目工期和其他同事的能力,最终在采用广播方式进行IPC. 那时,自己也在想,这么多个APP相互发信息,数据量也大,对整机性能有影响么?会不会存在丢失和内存问题.一脸茫然,网上也不会有类似信息告诉总结这种情况,本文也不会总结这个答案,因为看完之后心中自然有数

  • 详解Android性能优化之启动优化

    1.为什么要进行启动优化 网上流行一种说法,就是8秒定律,意思是说,如果用户在打开一个页面,在8秒的时间内还没有打开,那么用户大概的会放弃掉,意味着一个用户的流失.从这里就可以看出,启动优化的重要性了. 2.启动的分类 2.1 冷启动 先来看看冷启动的流程图 从图中可以看出,APP启动的过程是:ActivityManagerProxy 通过IPC来调用AMS(ActivityManagerService),AMS通过IPC启动一个APP进程,ApplicationThread通过反射来创建App

  • 详解Android壁纸服务的启动过程

    壁纸基础 android中的壁纸分为动态壁纸和静态壁纸两种,两种类型的壁纸都以Service的类型运行在系统后台. 静态壁纸:仅以图片的形式进行展示对于静态壁纸,可以使用WallpaperManager中的getDrawable()等接口获取到当前的bitmap图像. 动态壁纸:显示的内容为动态的内容,同时可以对用户的操作做出响应对于动态壁纸的实时图像,是没办法通过android中原生的接口获取到,需要获取到动态壁纸的图像得自己修改源码. 壁纸实现时涉及的几个主要的类: WallpaperSer

  • 详解Android中App的启动界面Splash的编写方法

    一.Splash界面的作用 用来展现产品的Logo 应用程序初始化的操作 检查应用程序的版本 检查当前应用程序是否合法注册 二.界面的xml定义 写一个布局背景设置为产品的logo图片,再添加一个textview显示版本号. <TextView android:id="@+id/tv_splash_version" android:layout_width="wrap_content" android:layout_height="wrap_cont

  • 详解Android Activity的启动流程

    前言 activity启动的流程分为两部分:一是在activity中通过startActivity(Intent intent)方法启动一个Activity:二是我们在桌面通过点击应用图标启动一个App然后显示Activity:第二种方式相较于第一种方式更加全面,所以本文会以第二种流程来分析. 简要 我们手机的桌面是一个叫做Launcher的Activity,它罗列了手机中的应用图标,图标中包含安装apk时解析的应用默认启动页等信息.在点击应用图标时,即将要启动的App和Launcher.AMS

  • Android 应用程序的启动流程示例详解

    目录 应用进程的启动流程 1.ActivityStackSupervisor.startSpecificActivity 2.ATMS.startProcessAsync 3.LocalService.startProcess 4.startProcessLocked函数 5.ProcessList.startProcessLocked 6.ProcessList.startProcessLocked重载 7.ProcessList.startProcess 8.ZygoteState.star

  • 详解Android.activity销毁流程的工作原理

    继续我们的源码解析,上一篇文章我们介绍了Activity的启动流程,一个典型的场景就是Activity a 启动了一个Activity b,他们的生命周期回调方法是: onPause(a) –> onCreate(b) –> onStart(b) –> onResume(b) –> onStop(a) 而我们根据源码也验证了这样的生命周期调用序列,那么Activity的销毁流程呢?它的生命周期的调用顺序又是这样的呢? 这里我们我做一个简单的demo,让一个Activity a启动A

  • 详解Android中的ActivityThread和APP启动过程

    ActiviryThread ActivityThread的初始化 ActivityThread即Android的主线程,也就是UI线程,ActivityThread的main方法是一个APP的真正入口,MainLooper在它的main方法中被创建. //ActivityThread的main方法 public static void main(String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread = ne

  • 详解Android启动第一帧

    目录 1.第一帧什么时候开始调度 2.第一帧 3.第一次绘制 ViewTreeObserver ViewTreeObserver.addOnDrawListener() ViewTreeObserver.removeOnDrawListener() FloatingTreeObserver DecorView 四.锁窗特性 Window.Callback.onContentChanged() 五.利用 Window.onDecorViewReady() Handler.postAtFrontOf

  • Android 详解沉浸式状态栏的实现流程

    目录 去掉标题栏 效果 引入依赖 沉浸状态栏颜色 沉浸状态栏图片 Android-沉浸式状态栏 我们的征程是星辰大海,而非人间烟尘 去掉标题栏 首先去掉对应主题下面的Android自带的ActionBar,只需要在对应主题下面加NoActionBar 效果 引入依赖 implementation 'com.jaeger.statusbarutil:library:1.5.1' 沉浸状态栏颜色 沉浸式状态栏,既可以把颜色实现沉浸,又可以把图片实现沉浸. 未设置颜色沉浸的状态: 逻辑代码: Stat

随机推荐