BroadcastReceiver广播的注册、发送和接收过程分析

1. 简介

广播作为Android的四大组件之一,能够实现组件之间的通信。广播过程主要就是注册、发送和接收过程。广播使用了设计模式中的观察者模式:基于消息的发布 / 订阅事件模型,消息的生产者发布事件,而使用者订阅感兴趣的事件。因此,广播能够实现组件间的松耦合,即广播的发送者和接收者事先是可以不用知道对方存在的。接下来,我们来研究一下广播的注册、发送和接收过程的源码。

本文源码基于android 27

2.广播的注册过程

我们都知道,广播的注册分成两种:静态注册动态注册。静态注册通过在AndroidManifest.xml中注册广播接收者,应用安装时PackageManagerService通过解析AndroidManifest.xml来完成这个过程,由于涉及到PackageManagerService,这里暂且不表,后面再去分析PackageManagerService。我们这里来看下动态注册的过程,要实现动态注册需要调用registerReceiver()方法,其具体实现位于ContextWrapper类中。

2.1 ContextWrapper的registerReceiver

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

上面的mBase实际上是ContextImplContext类是个抽象类,ContextImpl类是Context类的具体实现,而ContextWrapper类是个装饰者的角色,这里涉及了装饰者模式,对装饰者模式有兴趣的可以看下这篇文章:装饰者模式
mBase是在Activity启动时被赋值的,这里就不祥说了。
我们来看下ContextImpl类的实现:

2.2 ContextImpl的registerReceiver

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }

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

最终会调用registerReceiverInternal()

2.3 ContextImpl的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();
                }
                //mPackageInfo的类型为LoadedApk类
                //如果mPackageInfo和context都不为空,则从mPackageInfo中获取IIntentReceiver对象
                //mPackageInfo.getReceiverDispatcher()最终还是通过LoadedApk.ReceiverDispatcher.getIIntentReceiver()来获取IIntentReceiver对象
                //详见下一小节的代码分析
                rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);
            } else {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //如果mPackageInfo或context为空,则新创建一个ReceiverDispatcher对象并获取IIntentReceiver
                //IIntentReceiver的具体实现是在LoadedApk.ReceiverDispatcher.InnerReceiver中
                rd = new LoadedApk.ReceiverDispatcher(
                        receiver, context, scheduler, null, true).getIIntentReceiver();
            }
        }
        try {
            //ActivityManager.getService()获取到的就是AMS,所以最终会调用到AMS的registerReceiver()方法
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

从上面的代码可以看到,首先会获取到一个名为rdIIntentReceiver对象。如果mPackageInfocontext都不为空,则从mPackageInfo.getReceiverDispatcher()中获取;否则从LoadedApk.ReceiverDispatcher.InnerReceiver()中获取。

最后会将这个IIntentReceiver对象传递到AMS中去注册。

我们先来看看mPackageInfo.getReceiverDispatcher(),其具体实现是在LoadedApk类中:

2.4 LoadedApk的getReceiverDispatcher

    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;
            //最终还是通过LoadedApk.ReceiverDispatcher.getIIntentReceiver()来返回IIntentReceiver对象
            return rd.getIIntentReceiver();
        }
    }

我们再来看看过LoadedApk.ReceiverDispatcher

2.5 LoadedApk的ReceiverDispatcher类


    static final class ReceiverDispatcher {
        //InnerReceiver类是ReceiverDispatcher类的静态内部类
        final static class InnerReceiver extends IIntentReceiver.Stub {//继承自IIntentReceiver.Stub
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
            final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }
            //...
        }
        
        //...
        
        ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                Handler activityThread, Instrumentation instrumentation,
                boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            }
            //创建InnerReceiver对象
            mIIntentReceiver = new InnerReceiver(this, !registered);
            //保存BroadcastReceiver对象
            mReceiver = receiver;
            mContext = context;
            mActivityThread = activityThread;
            mInstrumentation = instrumentation;
            mRegistered = registered;
            mLocation = new IntentReceiverLeaked(null);
            mLocation.fillInStackTrace();
        }
        
        //获取IIntentReceiver对象,即内部类InnerReceiver
        IIntentReceiver getIIntentReceiver() {
            return mIIntentReceiver;
        }
    }

从上面可以看到,IIntentReceiver接口的具体实现是ReceiverDispatcher.InnerReceiver。实际上IIntentReceiver是一个Binder接口,可以用来进行跨进程的通信,这里主要是用来进行广播分发。

而广播的分发过程是在AMS中进行的,AMS所在的进程与BroadcastReceiver所在的进程是不同的,同时BroadcastReceiver作为一个系统组件,其不具备跨进程通信的能力,因此需要IIntentReceiver作为载体传递到AMS中去。

然后,我们来看下AMS中的广播注册过程:

2.6 ActivityManagerService的registerReceiver

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
            IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
            int flags) {
            
        //省略一大堆代码...

        synchronized (this) {
        
            //...

            //ReceiverList继承自ArrayList,用来存储广播接收者。
            ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
            if (rl == null) {
                //如果ReceiverList为空,就新创建一个
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {//rl.app表示宿主进程,一般就是Activity所在的进程
                    //将ReceiverList添加到receivers中
                    //宿主进程里面有一个列表receivers,专门用来保存这个进程注册的广播接收者。
                    rl.app.receivers.add(rl);
                } 
                
                //...
                
                //将ReceiverList保存到AMS的mRegisteredReceivers中
                //为了方便在收到广播时,快速找到对应的广播接收者
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
            //...
            
            //创建BroadcastFilter并传入ReceiverList
            BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
            //将BroadcastFilter添加到ReceiverList中,即把ReceiverList和IntentFilter关联起来
            rl.add(bf);
            if (!bf.debugCheck()) {
                Slog.w(TAG, "==> For Dynamic broadcast");
            }
            //将BroadcastFilter添加到mReceiverResolver中
            mReceiverResolver.addFilter(bf);

           //...

            return sticky;
        }
    }

从上面的分析可以看到,AMS先把广播接收者封装成一个ReceiverList对象,然后把ReceiverList分别添加到rl.app.receiversmRegisteredReceivers中去。最后会创建一个BroadcastFilter对象并把ReceiverListIntentFilter关联起来,保存到mReceiverResolver中去,这样当AMS接收到广播时就可以从mReceiverResolver中找到对应的广播接收者了。

2.7 时序图

最后来张注册广播的时序图:


广播注册时序图.png

2.8 小结

整个注册过程的目的就是将广播接收者receiver和要接收的广播类型IntentFilter保存在AMS中,方便后面收到广播时能够进行相应的处理。

3.广播的发送和接收过程

广播的发送和接收过程我们这里分为三部分来讲解:

  1. 从发送者到AMS
  2. AMSApplicationThread
  3. ApplicationThread到接收者

为什么这么分呢,因为这中间涉及到两次跨进程的通信,哈哈~

3.1 从发送者到AMS

首先从广播的发送说起,广播可以发送不同的类型,如普通广播、有序广播等,这里以普通广播为例来分析其发送过程。
发送普通广播需要调用sendBroadcast方法,其实现同样在ContextWrapper中:

3.1.1 ContextWrapper的sendBroadcast

    @Override
    public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }

因为ActivityService类都继承了ContextWrapper类,所以ActivityService都可以注册和发送广播。

跟广播注册一样,ContextWrappersendBroadcast()方法还是调用到ContextImplsendBroadcast()方法。

3.1.2 ContextImpl的sendBroadcast

    @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

最后还是交到AMS中去处理。

3.1.3 时序图

从发送者到AMS这一步还是很简单的,没做什么复杂的逻辑,我们看下时序图:

广播发送、接收时序图-1.从发送者到AMS.png

3.2 从AMS到ApplicationThread

接下来,我们看下第二部分,首先从ActivityManagerServicebroadcastIntent()方法开始:

3.2.1 ActivityManagerService的broadcastIntent

    public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            //验证广播的合法性
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            //调用broadcastIntentLocked
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

AMS中首先会检验广播的合法性,若合法就继续调用broadcastIntentLocked()

3.2.2 ActivityManagerService的broadcastIntentLocked

    final int broadcastIntentLocked(ProcessRecord callerApp,
            String callerPackage, 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 userId) {
            
        //省略一大堆代码...
        
        List receivers = null;
        List<BroadcastFilter> registeredReceivers = null;

        if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
            //获取与这个广播匹配的静态BroadcastReceiver列表
            receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
        }
        if (intent.getComponent() == null) {
            if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
                //...
            } else {
                //获取与这个广播匹配的动态BroadcastReceiver列表
                //可以查看前面的注册过程分析,动态注册时就是把相关信息(BroadcastFilter对象)保存在mReceiverResolver
                //queryIntent函数将这个BroadcastFilter实例取回来
                //由于注册一个广播类型的接收者可能有多个,所以这里把所有符合条件的的BroadcastFilter实例放在一个List中
                registeredReceivers = mReceiverResolver.queryIntent(intent,
                        resolvedType, false /*defaultOnly*/, userId);
            }
        }
        
        //...
        
        //这里只是无序的动态广播的处理过程
        if (!ordered && NR > 0) {
        
            //...
            
            //获得一个广播队列
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            //创建一个广播记录BroadcastRecord,
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);
 
            final boolean replaced = replacePending  && (queue.replaceParallelBroadcastLocked(r) != null);

            if (!replaced) {
                //广播记录入队
                queue.enqueueParallelBroadcastLocked(r);
                //广播交给队列去处理
                queue.scheduleBroadcastsLocked();
            }
            
            //...
        }
        //这里会对有序广播,静态广播等进行处理,跟无序的动态广播差不多,这里就省略了。
    }

可以看到,AMS先找出能匹配的广播,然后将这些广播放到一个队列中去处理。
我们先来看下queue.enqueueParallelBroadcastLocked(r)

3.2.3 BroadcastQueue的enqueueParallelBroadcastLocked

    final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();

    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        mParallelBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }

实际上就是将广播记录添加到一个ArrayList中去,后面会从mParallelBroadcasts这个对象中取出广播记录。
再来看看scheduleBroadcastsLocked()

3.2.4 BroadcastQueue的scheduleBroadcastsLocked

    public void scheduleBroadcastsLocked() {
        //...

        if (mBroadcastsScheduled) {
            return;
        }
        //发送一个BROADCAST_INTENT_MSG信息
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

这里的mBroadcastsScheduled表示AMS当前是不是正在处理其它广播,如果是的话,就先返回不处理了,这样可以保证所有广播是串行处理的。

注意这里处理广播的方式,当AMS收到一个广播时,AMS只是把广播放到一个队列中去而已,不会关注这个广播是否及时处理到。所以,广播的发送和处理实际上是异步进行的。

同时可以看到,这里只是用mHandler发送了个信息而已,我们看看mHandler是怎么处理信息的。

3.2.5 BroadcastHandler的handleMessage

    private final class BroadcastHandler extends Handler {
        public BroadcastHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    //处理BROADCAST_INTENT_MSG信息
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

再去看下processNextBroadcast()

3.2.6 BroadcastHandler的processNextBroadcast

    final void processNextBroadcast(boolean fromMsg) {
        synchronized(mService) {
        
            //...
            //无序广播的处理
            while (mParallelBroadcasts.size() > 0) {
                //前面存到mParallelBroadcasts的BroadcastRecord在这里取出来
                r = mParallelBroadcasts.remove(0);
                
                //...

                //广播大小
                final int N = r.receivers.size();
                
                //遍历所有匹配的广播
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    //调用deliverToRegisteredReceiverLocked()进一步去处理
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }

这里会遍历所有匹配的广播,然后调用deliverToRegisteredReceiverLocked()去处理。

3.2.7 BroadcastHandler的deliverToRegisteredReceiverLocked

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered, int index) {
        boolean skip = false;
        //检查发送者的权限
        if (filter.requiredPermission != null) {
            //...
        }
        //检查接收者的权限
        if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) {
           //...
        }
        
        //...
        
        try {
            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                if (ordered) {
                    skipReceiverLocked(r);
                }
            } else {
                //调用performReceiveLocked()进行下一部的处理
                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);
            }
            if (ordered) {
                r.state = BroadcastRecord.CALL_DONE_RECEIVE;
            }
        }

首先会检查发送者和接收者的权限,然后就是调用performReceiveLocked()

3.2.8 BroadcastHandler的performReceiveLocked

    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) {
                //
                app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                //...
            }
        }
    }

这里app.thread指的就是ApplicationThread,至此,就到了ApplicationThread了。

3.2.9 时序图

第二部分的逻辑还是比较多的,我们看下其时序图:


广播发送、接收时序图-2.从AMS到ApplicationThread.png

3.2.10 小结

这一步中,AMS首先根据intent查找出匹配的广播接收者,然后把这些广播接收者放到一个消息队列中。同时AMS会在消息循环中处理这些广播,并把广播交到ApplicationThread中去处理。

3.3 从ApplicationThread到接收者

最后,就是来到ApplicationThread,我们来看下其scheduleRegisteredReceiver()实现:

3.3.1 ApplicationThread的scheduleRegisteredReceiver

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

这里的receiver其类型为IIntentReceiver,具体实现在LoadedApk.ReceiverDispatcher.InnerReceiver,前面注册时已经见过这玩意了。我们还是进去看看。

3.3.2 LoadedApk.ReceiverDispatcher.InnerReceiver

    static final class ReceiverDispatcher {

        final static class InnerReceiver extends IIntentReceiver.Stub {
        
            final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
          
            //...
            
            @Override
            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);
                } 
                
                //...
            }
        }

这里面只是简单的调用LoadedApk.ReceiverDispatcher类的performReceive()

3.3.3 LoadedApk.ReceiverDispatcher的performReceive

        public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            //将广播的intent等信息封装为Args对象
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            //这里的mActivityThread是一个Handler对象,具体指向的就是H
            //所以实际就是调用Args的getRunnable()方法并通过H发送到主线程的消息队列中去处理
            //因此,ReceiverDispatcher不等这个广播被处理完就返回了
            //这里也体现了广播的发送和处理是异步进行的
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

从上面可以看到,广播接收者最终是运行在UI线程中的,所以,onReceive()方法中不能执行太耗时的操作,否则将引起ANR。
我们再来看看ArgsgetRunnable()的实现。

3.3.4 LoadedApk.ReceiverDispatcher.Args的getRunnable

            public final Runnable getRunnable() {
                return () -> {
                    
                    //...
                    
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        //调用广播的onReceive()方法啦
                        receiver.onReceive(mContext, intent);
                    } 
                    //...
            }
        }

最终,这里会调用广播的onReceive()方法,至此,广播从发送到接收的过程就完成了。

3.3.5 时序图

来看下相应的时序图:


广播发送、接收时序图-3.从ApplicationThread到接收者.png

3.3.6 小结

这一步中,ApplicationThread交到广播分发器ReceiverDispatcher中来处理,ReceiverDispatcher的内部类Args在主线程消息循环中处理这个广播,最终将这个广播分发到所注册的BroadcastReceiver实例的onReceive()函数进行处理。

最后来张总的广播发送、接收过程时序图:


广播发送、接收时序图-完整版.png

4. 总结

使用广播时,都需要先注册,可以采用静态注册或动态注册来完成。动态注册的本质就是把广播接收者receiver和要接收的广播类型filter保存在AMS中去。发送广播时通过binder机制把广播发送到AMS中去,AMS根据发送过来的条件(IntentFilter/Permission等)在已注册的广播接收者中找出相匹配的。然后将这些匹配的广播接收者放到一个消息队列中去,消息循环队列拿到广播后会交给广播分发器ReceiverDispatcher,广播分发器最终会把广播放到主线程的消息队列中去处理,最后回调BroadcastReceiver中的onReceive()方法。

可以看到,在Android的广播机制中,AMS扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,由此可以知道AMS是多么的重要,当然并不单单是这一点啦。另外,AMS并不会等待广播接收器处理这些广播就返回了,因此,广播的发送和处理是异步的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容