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

广播作为四大组件之 ,使用频率远没有 Activity 高,但是广播的工作过程还是十分有必要了解的。本节主要从三个方面讲解广播工作过程,分别是广播的注册、发送和接收。本文基于Android8.1.0系统分析广播的注册、发送和接收过程。

1. 广播的注册过程

       广播的注册通俗来讲就是广播接受者注册自己感兴趣的广播,广播的注册分为两种形式,分别是静态注册和动态注册,静态注册在应用安装时由PackageManagerService来完成注册过程,关于这一过程本文先不做介绍,本文主要分析广播的动态注册过程。

想要动态注册广播,需要调用registerReceiver方法,它在ContextWrapper中实现,代码如下所示:

frameworks/base/core/java/android/content/ContextWrapper.java

    @Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return mBase.registerReceiver(receiver, filter);}
这里 mBase 具体指向就是 ContextImpl  ,ContextImpl  的 registerReceiver  方法 有很多重载的方法,但是最终都会调用 registerReceiverInternal方法,代码如下所示:
frameworks/base/core/java/android/app/ContextImpl.java

    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) { // ... 1if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler,mMainThread.getInstrumentation(), true); // ... 2} else {if (scheduler == null) {scheduler = mMainThread.getHandler();}rd = new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true).getIIntentReceiver(); // ... 3}}try {final Intent intent = ActivityManager.getService().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName, rd, filter,broadcastPermission, userId, flags); // ... 4if (intent != null) {intent.setExtrasClassLoader(getClassLoader());intent.prepareToEnterProcess();}return intent;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}
       在注释1 处判断如果 LoadedApk   类型的 mPackageInfo  不 等于 null ,并且 context 不等与 null 就调用注释2 处的代码,通过 mPackageinfo 的 getReceiverDispatcher 方法 获取 rd 对 象,否则就调用注释3处的代码来创建 rd 对象。注释2 和注释3处 的代码的 目的都是要获取 IIntentReceiver 类型的 rd 对象, IIntentReceiver 是一个  Binder 接口,用于广播的跨进程的通 信,它在 LoadedApk.ReceiverDispatcher .IntentReceiver 中 实现,代码如下所示:
frameworks/base/core/java/android/app/LoadedApk.java
static final class ReceiverDispatcher {final static class InnerReceiver extends 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;}...}...      }
       回到 registerReceiverInternal 方法 , 在注释4 处调用了 I Activity Manager 的  registerReceiver 方法,最终会调用  AMS 的 registerReceiver 方法,并将 llntentReceiver 类型的  rd 传进去, 这里之所以不直接传入 BroadcastReceiver 而是 传入 llntentReceiver , 是 因为注册 广播是一个 跨进程过程, 需要具有跨进程的通信功能的 IlntentReceiver 。接下来分析 AMS 的 register Receiver 方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,IIntentReceiver receiver, IntentFilter filter, String permission, int userId,int flags) {...ArrayList<Intent> stickyIntents = null;ProcessRecord callerApp = null;...synchronized(this) {if (caller != null) {callerApp = getRecordForAppLocked(caller); // ... 1...} else {...}...  Iterator<String> actions = filter.actionsIterator(); // ... 2if (actions == null) {ArrayList<String> noAction = new ArrayList<String>(1);noAction.add(null);actions = noAction.iterator();}// Collect stickies of usersint[] 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); // ... 3}}}}}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); // ... 4}}}// The first sticky in the list is returned directly back to the client.Intent sticky = allSticky != null ? allSticky.get(0) : null;if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Register receiver " + filter + ": " + sticky);if (receiver == null) {return sticky;}synchronized (this) {... ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); // ... 5if (rl == null) {rl = new ReceiverList(this, callerApp, callingPid, callingUid,userId, receiver); // ... 6...} ...BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId, instantApp, visibleToInstantApps); // ... 7rl.add(bf); // ... 8if (!bf.debugCheck()) {Slog.w(TAG, "==> For Dynamic broadcast");}mReceiverResolver.addFilter(bf); // ... 9...return sticky;}}
       在注释1处通过 getRecordForAppLocked 方法得到 ProcessRecord 类型的 callerApp   对象, 它用于描述请求 AMS 注册广播接收者的 Activity 所在的应用程序进程。在注释2 处根据传人的 IntentFilter 类型 filter 得到 actions 列表,根据 actions 列表和 userlds (userIds   可以理解为应用程序的uid )得到所有的粘性广播的 intent ,并在注释3 处传入到 sticky Intents 中。接下来从 sticky Intents 中找到匹配传入的参数 filter 的粘性广播的 intent ,在注释4 处将这些 intent 存入到 allSticky  列表中,从这里可以看出粘性广播是存储在 AMS 中的。
       在注释5 处获取 ReceiverList 列表 ,如果为空则 在注释6 处创建 ReceiverList 继 承自  ArrayList  ,用来存储广播接收 者。在注释 7 处创建 BroadcastFilter 并传入此前创建的 ReceiverList , BroadcastFilter 用来描 述注 册的广 播接 者,并在注释8 处通过 add 将自身 添加到 ReceiverList 中 。在注释9处将  BroadcastFilter 加到 ReceiverResolver  类型 mReceiverResolver  中,这 样当 A MS 收到 广播时 就可 以从 mReceiverResolver  中找到 对应的 广播接者 了,从而达到 了注册 广播 的目的。

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

广播的发送和接收过程分为两个部分来进行讲解,分别是 Contextlmpl 到 AMS 的调用过程和 AMS 到 BroadcastReceiver 的调用过程。

2.1 ContextImpl到AMS的调用过程

       广播 可以发送多种 类型, 括无序广播(普通广播) 、有序广播 和粘性 广播,  这里以无序广播 为例来讲解广播的 发送过 程。要发送无序广播需要 调用 sendBroadcase  方法 ,它在 ContextWrapper 中实现,代码如下所示:
frameworks/base/core/java/android/content/ContextWrapper.java
    public void sendBroadcast(Intent intent) {mBase.sendBroadcast(intent);}

在“解析Service的启动过程”一文章我们分析过,mBase具体指向就是ContextImpl,接下来查看ContextImpl的sendBroadcast方法,代码如下所示:

frameworks/base/core/java/android/app/Contextlmpl.java

    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()); // ... 1} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

在注释1处最终会调用AMS的broadcastIntent方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    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); // ... 1final ProcessRecord callerApp = getRecordForAppLocked(caller);final int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();int res = broadcastIntentLocked(callerApp,callerApp != null ? callerApp.info.packageName : null,intent, resolvedType, resultTo, resultCode, resultData, resultExtras,requiredPermissions, appOp, bOptions, serialized, sticky,callingPid, callingUid, userId); // ... 2Binder.restoreCallingIdentity(origId);return res;}}

在注释1处,首先验证广播是否合法,我们先分析verifyBroadcastLocked方法,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    final Intent verifyBroadcastLocked(Intent intent) {// Refuse possible leaked file descriptorsif (intent != null && intent.hasFileDescriptors() == true) { // ... 1throw new IllegalArgumentException("File descriptors passed in Intent");}int flags = intent.getFlags(); // ... 2if (!mProcessesReady) {// if the caller really truly claims to know what they're doing, go// ahead and allow the broadcast without launching any receiversif ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) { // ... 3// This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.} else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { // ... 4Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent+ " before boot completion");throw new IllegalStateException("Cannot broadcast before boot completed");}}if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {throw new IllegalArgumentException("Can't use FLAG_RECEIVER_BOOT_UPGRADE here");}if ((flags & Intent.FLAG_RECEIVER_FROM_SHELL) != 0) {switch (Binder.getCallingUid()) {case ROOT_UID:case SHELL_UID:break;default:Slog.w(TAG, "Removing FLAG_RECEIVER_FROM_SHELL because caller is UID "+ Binder.getCallingUid());intent.removeFlags(Intent.FLAG_RECEIVER_FROM_SHELL);break;}}return intent;}
        在注释1处验证  intent 是否 不为 null 且有文件描述符。 注释2处 获得 intent 中的 flag  。注释3 处如果 系统正 在启 动过程中, 判断如果flag 设置为 FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT(启动检查时 只接受 动态注册的 广播 接收 者) 则不做处 理, 如 果不是则在注释4 处判断如果 flag 没有设置为 FLAG_RECEIVER_REGISTERED_ONLY  ( 只接受 动态注 册的广播接收者)则抛 出异 常。 我们再回到 broadcastIntent  方法,在注释2处调 用了 broadcastIntentLocked 方法 , 代码如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    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) {...if ((receivers != null && receivers.size() > 0)|| resultTo != null) {BroadcastQueue queue = broadcastQueueForIntent(intent);BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,resultData, resultExtras, ordered, sticky, false, userId); // ... 1if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r+ ": prev had " + queue.mOrderedBroadcasts.size());if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,"Enqueueing broadcast " + r.intent.getAction());final BroadcastRecord oldRecord =replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;if (oldRecord != null) {// Replaced, fire the result-to receiver.if (oldRecord.resultTo != null) {final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);try {oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,oldRecord.intent,Activity.RESULT_CANCELED, null, null,false, false, oldRecord.userId);} catch (RemoteException e) {Slog.w(TAG, "Failure ["+ queue.mQueueName + "] sending broadcast result of "+ intent, e);}}} else {queue.enqueueOrderedBroadcastLocked(r);queue.scheduleBroadcastsLocked(); // ... 2}} else {// There was nobody interested in the broadcast, but we still want to record// that it happened.if (intent.getComponent() == null && intent.getPackage() == null&& (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {// This was an implicit broadcast... let's record it for posterity.addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);}}return ActivityManager.BROADCAST_SUCCESS;
}

这里省略了很多代码,前面的工作主要是将动态注册的广播接收者和静态注册的广播接受者按照优先级高低不同存储在不同的列表中,再将这两个列表合并到receivers列表中,这样receivers列表包含了所有广播接受者(无序广播和有序广播)。在注释1处创建BroadcastRecord对象并将receivers传进去,在注释2处调用BroadcastQueue的scheduleBroadcastsLocked方法。

2.2 AMS到BroadcastReceiver的调用过程

       BroadcastQueue 的  scheduleBroadcastsLocked 方法 的代码如下所示:
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
    public void scheduleBroadcastsLocked() {if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["+ mQueueName + "]: current="+ mBroadcastsScheduled);if (mBroadcastsScheduled) {return;}mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); // ... 1mBroadcastsScheduled = true;}
       在注释1 处向 BroadcastHandler  类型的  mHandler 对象发送了 BROADCAST_INTENT_MSG 类型 的消息,这个消息 在 BroadcastHandler 的  handleMessage 方法 中进行处理 ,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

    private final class BroadcastHandler extends Handler {public BroadcastHandler(Looper looper) {super(looper, null, true);}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case BROADCAST_INTENT_MSG: {if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");processNextBroadcast(true);} break;case BROADCAST_TIMEOUT_MSG: {synchronized (mService) {broadcastTimeoutLocked(true);}} break;}}}
       在 handleMessage  方法 中调用了 processNextBroadcast 方法 ,方法对无序 广播和有序广 播分 别进行处理,旨在 将广播发送给广播接收者 ,下面给出 processNextBroadcast 方法中对 无序广播 的处理 部分,代码如下所示:

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

final void processNextBroadcast(boolean fromMsg) {synchronized(mService) {...if (fromMsg) {// 已经处理了BROADCAST_INTENT_MSG类型的消息mBroadcastsScheduled = false; // ... 1}// First, deliver any non-serialized broadcasts right away.// 遍历存储无序广播的mParallelBroadcasts列表while (mParallelBroadcasts.size() > 0) { // ... 2// 获取无序广播r = mParallelBroadcasts.remove(0); // ... 3...for (int i=0; i<N; i++) {Object target = r.receivers.get(i);if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,"Delivering non-ordered on [" + mQueueName + "] to registered "+ target + ": " + r);deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);// ... 4}...}...}}
       从前面 BroadcastHandler 方法 中我们 得知传入的 参数 fr omMsg 的值为 true ,因此在注释1 处将 rnBroadcastsScheduled 设置为  flase ,表示对于此前发来的 BROADCAST_ INTENT_ MSG 类型的消息已经处理了。注释2 处的 mParallelBroadcasts 列 表用来存 储无序广播,通过 while 循环将 mParallelBroadcasts 中的无序广播发送给对应的广播接收者。  在注释3处获取 每一 个 mParallelBroadcasts 中存储的 BroadcastRecord 类 型的 r  对象。在注释4 处将这些 r 对象描述的广播发送给对应的广播接收者, deliverToRegisteredReceiverLocked  方法代码 如下所示:

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,BroadcastFilter filter, boolean ordered, int index) {...try {if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,"Delivering to " + filter + " : " + r);if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {// Skip delivery if full backup in progress// If it's an ordered broadcast, we need to continue to the next receiver.if (ordered) {skipReceiverLocked(r);}} else {performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,new Intent(r.intent), r.resultCode, r.resultData,r.resultExtras, r.ordered, r.initialSticky, r.userId); // ... 1}if (ordered) {r.state = BroadcastRecord.CALL_DONE_RECEIVE;}} catch (RemoteException e) {Slog.w(TAG, "Failure sending broadcast " + r.intent, e);if (ordered) {r.receiver = null;r.curFilter = null;filter.receiverList.curBroadcast = null;if (filter.receiverList.app != null) {filter.receiverList.app.curReceivers.remove(r);}}}}
       这里省去了大部分的代码,这些代码是用来检查广播发送者和广播接收者的权限的。 如果通过了权限的检查, 则 会调用注释 1 处的 performReceiveLocked 方法,代码如下所示:
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,Intent intent, int resultCode, String data, Bundle extras,boolean ordered, boolean sticky, int sendingUser) throws RemoteException {// Send the intent to the receiver asynchronously using one-way binder calls.if (app != null) { // ... 1if (app.thread != null) { // ... 2// If we have an app thread, do the call through that so it is// correctly ordered with other one-way calls.try {app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState); // ... 3// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting// DeadObjectException when the process isn't actually dead.//} catch (DeadObjectException ex) {// Failed to call into the process.  It's dying so just let it die and move on.//    throw ex;} catch (RemoteException ex) {// Failed to call into the process. It's either dying or wedged. Kill it gently.synchronized (mService) {Slog.w(TAG, "Can't deliver broadcast to " + app.processName+ " (pid " + app.pid + "). Crashing it.");app.scheduleCrash("can't deliver broadcast");}throw ex;}} else {// Application has died. Receiver doesn't exist.throw new RemoteException("app.thread must not be null");}} else {receiver.performReceive(intent, resultCode, data, extras, ordered,sticky, sendingUser);}}
       在注释1和 注释2 处的代 码表示如 果广播接 者所在的应用 程序进程存在并且正在运行, 则执 行注释3 处的代 码,表示用广播接收者所在的 应用程序进程来接收 广播,这里 app.thread  指的是  ApplicationThread ,下面 来查看 Applic ationThread的 scheduleRegisteredReceiver 方法, 代码如 下所示:

frameworks/base/core/java/android/app/ActivityThread.java
        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);}
       在 scheduleRegisteredReceiver 方法中 调用了 IIntentReceiver    类型 的对象 receiver的performReceive方发,IIntentReceiver   在前面提到过,用于广播的跨进程 的通信,  它的 具体实 现为 LoadedApk.ReceiverDispatcher.lnnerReceiver ,代码如下所示:

frameworks/base/core/java/android/app/LoadedApk.java
    static final class ReceiverDispatcher {final static class InnerReceiver extends 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;}@Overridepublic void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser) {final LoadedApk.ReceiverDispatcher rd;if (intent == null) {Log.wtf(TAG, "Null intent received");rd = null;} else {rd = mDispatcher.get();}if (ActivityThread.DEBUG_BROADCAST) {int seq = intent.getIntExtra("seq", -1);Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));}if (rd != null) {rd.performReceive(intent, resultCode, data, extras,ordered, sticky, sendingUser); // ... 1} else {// The activity manager dispatched a broadcast to a registered// receiver in this process, but before it could be delivered the// receiver was unregistered.  Acknowledge the broadcast on its// behalf so that the system's broadcast sequence can continue.if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,"Finishing broadcast to unregistered receiver");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();}}}...      }}
       IlntentReceiver  使用了 AIDL  来实 现进程间 通信。 lnnerReceiver 继承自 lnnerReceiver .Stub ,是 Binder 通信 的服 务器 端, IlntentReceiver 则是 Binder 通信的客 户端、 InnerReceiver 在 本地的代理,它的具 体的实 就是 InnerReceiver 。在  lnnerReceiver 的 performReceive 方法 的注释1 处调用了 ReceiverDispatcher 类型的 rd 对象的 performReceive 方法 ,代码如下所示:
frameworks/base/core/java/android/app/LoadedApk.java
        public void performReceive(Intent intent, int resultCode, String data,Bundle extras, boolean ordered, boolean sticky, int sendingUser) {final Args args = new Args(intent, resultCode, data, extras, ordered,sticky, sendingUser); // ... 1if (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);}}if (intent == null || !mActivityThread.post(args.getRunnable())) { // ... 2if (mRegistered && ordered) {IActivityManager mgr = ActivityManager.getService();if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,"Finishing sync broadcast to " + mReceiver);args.sendFinished(mgr);}}}
       在注释1 处将广播  intent 等信 息封装为  Args 对象,  在注释2 处调用 mActi vi tyThread 的  post 方法并 传入了  Args 对 象。这个 mActivityThread    是一个  Handler 对象,具体 指向的就是 H ,注释2处的代码就 是将 Args 对象的  getRunna ble 方法 通过 H  发送 到 线程 的消息列中, Args 的 getRunnable  方法 如下所示:

frameworks/base/core/java/android/app/LoadedApk.java

final class Args extends BroadcastReceiver.PendingResult {...public final Runnable getRunnable() {return () -> {final BroadcastReceiver receiver = mReceiver;...try {ClassLoader cl = mReceiver.getClass().getClassLoader();intent.setExtrasClassLoader(cl);intent.prepareToEnterProcess();setExtrasClassLoader(cl);receiver.setPendingResult(this);receiver.onReceive(mContext, intent); // ... 1} catch (Exception e) {if (mRegistered && ordered) {if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,"Finishing failed broadcast to " + mReceiver);sendFinished(mgr);}if (mInstrumentation == null ||!mInstrumentation.onException(mReceiver, e)) {Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);throw new RuntimeException("Error receiving broadcast " + intent+ " in " + mReceiver, e);}}if (receiver.getPendingResult() != null) {finish();}Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);};}}
       在注释1 处执行了 BroadcastReceiver 类型的 receiver 对象的 onReceive 方法 ,这样 注册 的广播接收 者就 收到了广 播并得到了 intent。

解析BroadcastReceiver的注册、发送与接收过程相关推荐

  1. Android筑基——BroadcastReceiver 的动态注册、发送和接收过程(基于api21)

    目录 1. 前言 2. 正文 2.1 广播接收者的动态注册 2.1.1 ContextWrapper.registerReceiver() 方法 2.1.2 ContextImpl.registerR ...

  2. Android深入四大组件(八)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册.接收和发送过程.建议阅读此文前请先阅读Android深入理解四大组件系列的文章,知识重复的部分, ...

  3. Android-Framework学习笔记(九)—— Broadcast的注册、发送和接收过程

    系列文章 Android-Framework学习笔记(一)-- Android系统架构 Android-Framework学习笔记(二)-- Zygote进程启动过程 Android-Framewor ...

  4. Boardcast Receiver 源码分析:广播的动态注册、发送和接收过程

    文章目录 动态注册过程 ContextWrapper#registerReceiver(以下代码基于API26) ContextImpl#registerReceiver ContextImpl#re ...

  5. 邮件的发送和接收过程——STMP、POP、IMAP、MIME

    电子邮件发送协议 是一种基于" 推 "的协议,主要包括 SMTP : 邮件接收协议 则是一种基于" 拉 "的协议,主要包括 POP协议 和 IMAP协议 ,在正 ...

  6. Broadcast的注册、发送和接收过程

    上层接口调用registerReceiver frameworks\base\core\java\android\content\ContextWrapper.java @Overridepublic ...

  7. 邮件的发送和接收过程-----简单邮件传输协议(SMTP)和邮件读取协议!!!

    图中就是电子邮件的系统结构 以用户A向用户B发送邮件为例 用户A向用户B发送邮件,首先用户A利用由用户代理撰写邮件,包括填写收件人邮箱地址等,然后基于SMTP将邮件发送到其注册的邮箱服务器A的外出邮件 ...

  8. 数据在网络中的发送和接收过程--简略版(TCP/IP五层结构)

    在应用层上设备A想给IP地址为P的设备B发送信息:(假定已知B的IP) 数据信息从应用层而来,在传输层指定特定的端口号,再将这些数据放到TCP报文或者UDP报文内. 若使用UDP,不论从应用层来的数据 ...

  9. 电子邮件发送和接收过程 一一 SMTP、POP3、IMAP

    电子邮件发送协议主要是SMTP,收件协议主要是POP3和IMAP: SMTP 的全称是"Simple Mail Transfer Protocol",即简单邮件传输协议.它是一组用 ...

最新文章

  1. SQL Server统计信息:问题和解决方式
  2. 使用WKWebView替换UIWebView
  3. java中的Calendar
  4. [转]你打算如何提升自己?
  5. 影场与属性访问器界面
  6. 【LeetCode笔记】581. 最短无序连续子数组(Java、数组)
  7. 微信APP支付(基于Java实现微信APP支付)
  8. Java解析excel表格
  9. C#枚举中使用Flags特性
  10. VS2013环境下GSL数学库的使用说明(亲测)
  11. C11 多线程初学1
  12. matlab 小波变换程序,matlab 小波变换
  13. java 万年历绪论_基于安卓Android的万年历的设计与开发(含录像)
  14. 对短信验证码发送次数的限制
  15. MessageBox confirm弹框确认和取消按钮的使用-回调
  16. 【计算机网络】计网学习——总览(超多图+超详解)
  17. Linux ---动态监控
  18. TVbox带会员带推广版本
  19. html保存至心愿单按钮,王者荣耀添加心愿单有什么用 心愿单怎么实现
  20. 初中使用计算机教学反思,初中信息技术课堂教学反思随笔

热门文章

  1. 计算机知识竞赛口号,知识竞赛口号霸气押韵
  2. 细节决定成败!耗时两个礼拜,8000字安卓面试长文,全套教学资料
  3. 张一鸣带领5万人,做出多款头部产品的秘密是什么?
  4. 全国大学生交通科技大赛交科赛交通运输科技大赛智能交通创新技术应用大赛国家三等奖论文文字作品资料经验分享
  5. 【日期】找找哪些日期是星期几
  6. 怎么样在Excel单元格里批量加小数点和单位?
  7. ESP-01 8266转接板改造
  8. 重磅分享:微软面试100题2010年版全部答案完整亮相
  9. FTP(File Transfer Protocol,文件传输协议)
  10. 完成英语第一阶段的学习,明天开始第二阶段