前言
咱们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册、接收和发送过程。建议阅读此文前请先阅读Android深刻理解四大组件系列的文章,知识重复的部分,本文再也不赘述。html
1.广播的注册过程
BroadcastReceiver的注册分为两种,分别是静态注册和动态注册,静态注册在应用安装时由PackageManagerService来完成注册过程,关于这一过程,我会在后续的介绍PackageManagerService文章中详细介绍。这里只介绍BroadcastReceiver的动态注册。
要想动态注册BroadcastReceiver,须要调用registerReceiver方法,它的实如今ContextWrapper中,代码以下所示。java
frameworks/base/core/java/android/content/ContextWrapper.javaandroid


@Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
这里mBase具体指向就是ContextImpl,不明白的请查看Android深刻四大组件(二)Service的启动过程这篇文章。ContextImpl的registerReceiver方法有不少重载的方法最终会调用registerReceiverInternal方法:
frameworks/base/core/java/android/app/ContextImpl.javaapp


private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) {//1 if (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 = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId);//4 if (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.InnerReceiver,以下所示。async
frameworks/base/core/java/android/app/LoadedApk.javaide


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处调用了ActivityManagerProxy(AMP)的registerReceiver方法,最终会调用AMS的registerReceiver方法,并将rd传就去。不明白的同窗请查看Android深刻四大组件(一)应用程序启动过程(前篇),这里再也不赘述。
查看AMS的registerReceiver方法,以下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javaoop


public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ... synchronized(this) { ... Iterator<String> actions = filter.actionsIterator();//1 ... // 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);//2 } } } } } ArrayList<Intent> allSticky = null; if (stickyIntents != null) { final ContentResolver resolver = mContext.getContentResolver(); for (int i = 0, N = stickyIntents.size(); i < N; i++) { Intent intent = stickyIntents.get(i); if (filter.match(resolver, intent, true, TAG) >= 0) { if (allSticky == null) { allSticky = new ArrayList<Intent>(); } allSticky.add(intent);//3 } } } ... }
注释1处根据传入的IntentFilter类型的filter的获得actions列表,根据actions列表和userIds(userIds能够理解为应用程序的uid)获得全部的粘性广播的intent,并在注释2处传入到stickyIntents中,在注释3处将这些粘性广播的intent存入到allSticky列表中,从这里能够看出粘性广播是存储在AMS中的。
接着查看AMS的registerReceiver方法的剩余内容:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapost


public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ... synchronized (this) { ... ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());//1 if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver);//2 if (rl.app != null) { rl.app.receivers.add(rl); } ... } ... BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId);//3 rl.add(bf);//4 if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf);//5 ... return sticky; } }
注释1处获取ReceiverList列表,若是为空则在注释2处建立,ReceiverList继承自ArrayList,用来存储广播接收者。在注释3处建立BroadcastFilter并传入此前建立的ReceiverList,BroadcastFilter用来描述注册的广播接收者,并在注释4经过add方法将自身添加到ReceiverList中。注释5处将BroadcastFilter添加到mReceiverResolver中,这样当AMS接收到广播时就能够从mReceiverResolver中找到对应的广播接收者了。下面给出广播的注册过程的时序图。学习
2.广播的发送和接收过程
ContextImpl到AMS的调用过程
广播能够发送多种类型,包括无序广播(普通广播)、有序广播和粘性广播,这里以无序广播为例,来说解广播的发送过程。
要发送无序广播须要调用sendBroadcast方法,它的实现一样在ContextWrapper中:
frameworks/base/core/java/android/content/ContextWrapper.java


@Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); }
接着来看ContextImpl中的sendBroadcast方法,以下所示。
frameworks/base/core/java/android/app/ContextImpl.java


@Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManagerNative.getDefault().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);//1 ... /** * 2 */ 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; } }
咱们来查看注释1处的verifyBroadcastLocked方法:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java


final Intent verifyBroadcastLocked(Intent intent) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) {//1 throw new IllegalArgumentException("File descriptors passed in Intent"); } int flags = intent.getFlags();//2 if (!mProcessesReady) { if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {//3 } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {//4 Slog.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"); } return intent; }
verifyBroadcastLocked方法主要是验证广播是否合法,在注释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); /** * 1 */ BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); ... boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); if (!replaced) { queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked();//2 } } ... } return Act
这里省略了不少代码,前面的工做主要是将动态注册的广播接收者和静态注册的广播接收者按照优先级高低存储在不一样的列表中,再将这两个列表合并到receivers列表中,这样receivers列表包含了全部的广播接收者(无序广播和有序广播)。在注释1处建立BroadcastRecord对象并将receivers传进去,在注释2处调用BroadcastQueue的scheduleBroadcastsLocked方法。
这里先给出ContextImpl到AMS的调用过程的时序图。
AMS到BroadcastReceiver的调用过程
BroadcastQueue的scheduleBroadcastsLocked方法的代码以下所示。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java


public void scheduleBroadcastsLocked() { ... mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));//1 mBroadcastsScheduled = 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); } @Override public 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; ... } } }
在handleMessage方法中调用了processNextBroadcast方法,processNextBroadcast方法对无序广播和有序广播分别进行处理,旨在将广播发送给广播接收者,下面给出processNextBroadcast方法中对无序广播的处理部分。
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java


final void processNextBroadcast(boolean fromMsg) { ... if (fromMsg) { mBroadcastsScheduled = false;//1 } // First, deliver any non-serialized broadcasts right away. 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 } ... } }
从前面的代码咱们得知fromMsg的值为true,所以注释1处会将mBroadcastsScheduled 设置为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) { ... } 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) { ... } }
这里省去了大部分的代码,这些代码是用来检查广播发送者和广播接收者的权限。若是经过了权限的检查,则会调用注释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) {//1 if (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 } } ... } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);/ } }
注释1和2处的代码表示若是广播接收者所在的应用程序进程存在而且正在运行,则执行注释3处的代码,表示用广播接收者所在的应用程序进程来接收广播,这里app.thread指的是ApplicationThread,咱们来查看ApplicationThread的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);//1 }
注释1处调用了IIntentReceiver类型的对象receiver的performReceive方法,这里实现receiver的类为LoadedApk.ReceiverDispatcher.InnerReceiver,代码以下所示。
frameworks/base/core/java/android/app/LoadedApk.java


static final class ReceiverDispatcher { final static class InnerReceiver extends IIntentReceiver.Stub { ... InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null; } @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final LoadedApk.ReceiverDispatcher rd; ... if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);//1 } else { ... } ... }
在注释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);//1 ... if (intent == null || !mActivityThread.post(args)) {//2 if (mRegistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } }
在注释1处将广播的intent等信息封装为Args对象,并在注释2处调用mActivityThread的post方法并传入了Args对象。这个mActivityThread是一个Handler对象,具体指向的就是H,注释2处的代码就是将Args对象经过H发送到主线程的消息队列中。Args继承自Runnable,这个消息最终会在Args的run方法执行,Args的run方法以下所示。
frameworks/base/core/java/android/app/LoadedApk.java


public void run() { ... try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent);//1 } catch (Exception e) { ... } ... }
在注释1处执行了广播接收者的onReceive方法,这样注册的广播接收者就收到了广播并获得了intent。
广播的注册、发送和接收过程就讲到这,最后给出剩余部分的调用时序图。