《Android中级工程师》BroadcastReceive工作流程
2017-11-27 17:11
351 查看
前言
关于BroadcastReceive的使用已经了解了很多,但是使用都是应用层的,我们需要了解frameworks层是如何实现的,才能更深层次理解它的工作原理。关于广播的种类,我们知道大体有三类:
普通广播:通过Context.sendBroadcast()发送,可并行处理
有序广播:通过Context.sendOrderedBroadcast()发送,串行处理
Sticky广播:通过Context.sendStickyBroadcast()发送
这三种广播类型虽然具有不同的特性,但是它们的工作过程都是类似的,所以我们只分析普通广播即可。
关于广播的注册方式,我们知道有两种:
静态注册:通过在AndroidManifest.xml文件声明来注册,类似于Activity和Service
动态注册:通过代码registerReceiver()来注册,这种方式需要在合适的时机进行解注册unregisterReceiver()
这两种方式都能够完成注册广播的功能,其中静态广播的注册是在应用安装时由系统自动通过PackageManagerService(PMS)来完成。所以这里我们为了更好分析它的工程,采用动态注册的方式来研究。
一、时序图
二、 注册过程追踪
1. ContextWrapper.registerReceiver()
public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); }
很熟悉,和Service很相似,参考《Android中级工程师》Service启动流程
2. ContextImpl.registerReceiver()
public Intent registerReceiver(//省略参数) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); }
3. ContextImpl.registerReceiverInternal()
private Intent registerReceiverInternal(//省略参数) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { //获取主线程 scheduler = mMainThread.getHandler(); } //获取IIntentReceiver对象 rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { //省略部分代码 } } try { //跨进程调用AMS的registerReceiver() final Intent intent = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
这里我们看到了一个熟悉的方法,通过getReceiverDispatcher()获取IIntentReceiver对象,具体实现是LoadedApk.ReceiverDispatcher.InnerReceiver,这是一个Binder接口,为了跨进程时进行传输。ReceiverDispatcher内部以键值对的形式保存了BroadcastReceiver和InnerReceiver,所以当接收到广播时,可以很方便的调用BroadcastReceiver的onReceiver()方法。然后注册广播的任务就跨进程的交给了AMS去完成。
4. ActivityManagerService.registerReceiver()
public Intent registerReceiver(//省略参数) { enforceNotIsolatedCaller("registerReceiver"); ArrayList<Intent> stickyIntents = null; ProcessRecord callerApp = null; int callingUid; int callingPid; //查询调用者的进程信息 synchronized(this) { if (caller != null) { callerApp = getRecordForAppLocked(caller); //省略部分代码 } callingUid = callerApp.info.uid; callingPid = callerApp.pid; } else { callerPackage = null; callingUid = Binder.getCallingUid(); callingPid = Binder.getCallingPid(); } userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage); //获取IntentFilter中的actions,需要监听的广播action Iterator<String> actions = filter.actionsIterator(); if (actions == null) { ArrayList<String> noAction = new ArrayList<String>(1); noAction.add(null); actions = noAction.iterator(); } //收集调用者的sticky Intent,保存在列表当中 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); 4000 } } } } } //查询匹配的sticky广播,查询成功的添加到allSticky列表中 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); } } } //当IIntentReceiver为空,则直接返回第一个sticky Intent, 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) { if (callerApp != null && (callerApp.thread == null || callerApp.thread.asBinder() != caller.asBinder())) { // 调用者已经被杀死了 return null; } ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { //对于没有注册的广播,则创建接收者队列 rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); if (rl.app != null) { 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 bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); //所有匹配该filter的sticky广播执行入队操作 //如果没有使用sendStickyBroadcast,则allSticky=null。 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); //根据intent返回前台或后台广播队列 BroadcastQueue queue = broadcastQueueForIntent(intent); //创建BroadcastRecord BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers, null, 0, null, null, false, true, true, -1); //该广播加入到并行广播队列 queue.enqueueParallelBroadcastLocked(r); //调度广播,发送BROADCAST_INTENT_MSG消息,触发处理下一个广播。 queue.scheduleBroadcastsLocked(); } } return sticky; } }
mRegisteredReceivers是HashMap结构的,它以receiver IBinder为key, ReceiverList为value为HashMap来记录着所有已注册的广播,这样整个广播的注册过程就完成了。
在BroadcastQueue中有两个广播队列mParallelBroadcasts,mOrderedBroadcasts,数据类型都为ArrayList:
mParallelBroadcasts:并行广播队列,可以立刻执行,而无需等待另一个广播运行完成,该队列只允许动态已注册的广播,从而避免发生同时拉起大量进程来执行广播,前台的和后台的广播分别位于独立的队列。
mOrderedBroadcasts:有序广播队列,同一时间只允许执行一个广播,该队列顶部的广播便是活动广播,其他广播必须等待该广播结束才能运行,也是独立区别前台的和后台的广播。
三、广播注册总结
注册过程:获取IIntentReceiver对象,其实现类为LoadedApk.ReceiverDispatcher.InnerReceiver,并且将BroadcastReceiver和InnerReceiver保存到ReceiverDispatcher中;
通过ActivityManagerService将获得的InnerReceiver和调用者进程ApplicationThread,以跨进程的方式注册到SystemServer中;
在ActivityManagerService注册时,为当前InnerReceiver创建接受者队列ReceiverList,并且将ReceiverList添加到已注册广播列表mRegisteredReceivers中;
根据当前的filter创建广播过滤者BroadcastFilter,并添加到接受者队列ReceiverList中。
当注册的是Sticky广播时,还会创建BroadcastRecord,并添加到BroadcastQueue的mParallelBroadcasts(并行广播队列),注册后调用AMS来尽快处理该广播。
四、发送广播追踪
1. ContextWrapper.sendBroadcast()
public void sendBroadcast(Intent intent, String receiverPermission) { mBase.sendBroadcast(intent, receiverPermission); }
2. ContextImpl.sendBroadcast()
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()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
3. 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 intent = verifyBroadcastLocked(intent); final 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); Binder.restoreCallingIdentity(origId); return res; } }
这里需要注意的是这个方法的参数有两个boolean类型的,它们共同作用来决定发送的是什么广播:
类型 | serialized | sticky |
---|---|---|
sendBroadcast | false | false |
sendOrderedBroadcast | true | false |
sendStickyBroadcast | false | true |
4. ActivityManagerService.broadcastIntentLocked()
private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { //step1: 设置flag //step2: 广播权限验证 //step3: 处理系统相关广播 //step4: 增加sticky广播 //step5: 查询receivers和registeredReceivers //step6: 处理并行广播 //step7: 合并registeredReceivers到receivers //step8: 处理串行广播 return ActivityManager.BROADCAST_SUCCESS; }
这里就直接引用gityuan的分布研究了,当然由于版本的原因,有些不一样了。
4.1 设置广播flag
//此flag将导致已停止的应用无法收到此广播 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); //当没有启动完成时,不允许启动新进程 if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_NON_FULL, "broadcast", callerPackage); //确保接收此广播的用户处于运行状态,否则除非是系统升级广播或者关机广播,否则直接返回 if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) { if ((callingUid != Process.SYSTEM_UID || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) { return ActivityManager.BROADCAST_F 11ee1 AILED_USER_STOPPED; } }
这里需要注意的是,从Android3.1开始,默认情况下广播不会发送给已经停止的应用,主要是因为系统为Intent添加了两个标记位:
FLAG_EXCLUDE_STOPPED_PACKAGES:广播不会发送给已经停止的应用
FLAG_INCLUDE_STOPPED_PACKAGES:广播会发送给已经停止的应用
BroadcastReceiver的Flags还包括:
FLAG_RECEIVER_REGISTERED_ONLY //只允许已注册receiver接收广播
FLAG_RECEIVER_REPLACE_PENDING //新广播会替代相同广播
FLAG_RECEIVER_FOREGROUND //只允许前台receiver接收广播
FLAG_RECEIVER_NO_ABORT //对于有序广播,先接收到的receiver无权抛弃广播
FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT //Boot完成之前,只允许已注册receiver接收广播
FLAG_RECEIVER_BOOT_UPGRADE //升级模式下,允许系统准备就绪前可以发送广播
4.2 广播权限验证
// 是否是受保护的广播 final String action = intent.getAction(); final boolean isProtectedBroadcast; try { isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action); } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); return ActivityManager.BROADCAST_SUCCESS; } //是否由系统调用 final boolean isCallerSystem; switch (UserHandle.getAppId(callingUid)) { case Process.ROOT_UID: case Process.SYSTEM_UID: case Process.PHONE_UID: case Process.BLUETOOTH_UID: case Process.NFC_UID: isCallerSystem = true; break; default: isCallerSystem = (callerApp != null) && callerApp.persistent; break; } // 受保护的广播只能由系统调用,非系统调用的话停止调用者发送该广播 if (!isCallerSystem) { if (isProtectedBroadcast) { String msg = "Permission Denial: not allowed to send broadcast " + action + " from pid=" + callingPid + ", uid=" + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action) || AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) { //省略部分代码 } }
4.3 处理系统相关广播
if (action != null) { switch (action) { case Intent.ACTION_UID_REMOVED: //uid移除 case Intent.ACTION_PACKAGE_REMOVED: //package移除 case Intent.ACTION_PACKAGE_ADDED: //增加package case Intent.ACTION_PACKAGE_CHANGED: //package改变 case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE: //外部设备不可用 case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE: //外部设备可用 case Intent.ACTION_TIMEZONE_CHANGED: //时区改变,通知所有运行中的进程 case Intent.ACTION_TIME_CHANGED: //时间改变,通知所有运行中的进程 case Intent.ACTION_CLEAR_DNS_CACHE: //DNS缓存清空 case Proxy.PROXY_CHANGE_ACTION: //网络代理改变 } }
4.4 增加Sticky广播
if (sticky) { //sticky广播必须有BROADCAST_STICKY权限 if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid=" + callingPid + ", uid=" + callingUid + " requires " + android.Manifest.permission.BROADCAST_STICKY; Slog.w(TAG, msg); throw new SecurityException(msg); } //省略部分代码 if (userId != UserHandle.USER_ALL) { // 避免冲突 ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get( UserHandle.USER_ALL); if (stickies != null) { ArrayList<Intent> list = stickies.get(intent.getAction()); if (list != null) { int N = list.size(); int i; for (i=0; i<N; i++) { if (intent.filterEquals(list.get(i))) { throw new IllegalArgumentException( "Sticky broadcast " + intent + " for user " + userId + " conflicts with existing global broadcast"); } } } } } ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); if (stickies == null) { stickies = new ArrayMap<>(); mStickyBroadcasts.put(userId, stickies); } ArrayList<Intent> list = stickies.get(intent.getAction()); if (list == null) { list = new ArrayList<>(); stickies.put(intent.getAction(), list); } final int stickiesCount = list.size(); int i; for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i))) { //此sticky已存在,则替换掉 list.set(i, new Intent(intent)); break; } } if (i >= stickiesCount) { //添加新的intent到list中 list.add(new Intent(intent)); } }
4.5 查询reseivers和registeredReceivers
//查询谁会接收这个广播 List receivers = null; List<BroadcastFilter> registeredReceivers = null; //当允许静态接收者处理该广播,则通过PKMS根据Intent查询相应的静态receivers if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); } if (intent.getComponent() == null) { if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) { //省略部分代码 } else { //根据Intent查询动态注册的广播 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId); } }
其中receivers:记录着匹配当前intent的所有静态注册广播接收者;
registeredReceivers:记录着匹配当前的所有动态注册的广播接收者。
4.6 处理并行广播
final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { if (isCallerSystem) { checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid, isProtectedBroadcast, registeredReceivers); } //创建并行广播队列 final BroadcastQueue queue = broadcastQueueForIntent(intent); //创建BroadcastRecord对象 BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r); if (!replaced) { //将广播加入到并行队列 queue.enqueueParallelBroadcastLocked(r); //处理广播 queue.scheduleBroadcastsLocked(); } //动态注册的广播接收者处理完成,则会置空该变量 registeredReceivers = null; NR = 0; }
4.7 合并registeredReceivers到receivers
int ir = 0; if (receivers != null) { //防止应用监听该广播,在安装时直接运行,属于特殊情况 String skipPackages[] = null; if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) { Uri data = intent.getData(); if (data != null) { String pkgName = data.getSchemeSpecificPart(); if (pkgName != null) { skipPackages = new String[] { pkgName }; } } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) { skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); } //将skipPackages相关的广播接收者从receivers列表中移除 if (skipPackages != null && (skipPackages.length > 0)) { for (String skipPackage : skipPackages) { if (skipPackage != null) { int NT = receivers.size(); for (int it=0; it<NT; it++) { ResolveInfo curt = (ResolveInfo)receivers.get(it); if (curt.activityInfo.packageName.equals(skipPackage)) { receivers.remove(it); it--; NT--; } } } } } //处理动态广播,处理完后再执行将动态注册的registeredReceivers合并到receivers int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; while (it < NT && ir < NR) { //省略部分代码 } } //完成合并 while (ir < NR) { if (receivers == null) { receivers = new ArrayList(); } receivers.add(registeredReceivers.get(ir)); ir++; }
4.8 处理串行广播
//存在广播接收者 if ((receivers != null && receivers.size() > 0) || resultTo != null) { //创建广播队列 BroadcastQueue queue = broadcastQueueForIntent(intent); //创建BroadcastRecord对象 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(); } } else { if (intent.getComponent() == null && intent.getPackage() == null && (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0); } }
五、发送广播总结
发送过程:设置flags,默认情况下不会发送给已经停止的应用;
检查广播的权限,受保护的广播只能由系统调用;
处理系统广播;
处理sticky广播,存放在mStickyBroadcasts中;
分别调用scheduleBroadcastsLocked()方法来处理并行广播和串行广播。
处理发送方式:
sticky广播:
创建BroadcastRecord对象;
添加到mParallelBroadcasts队列;
执行queue.scheduleBroadcastsLocked。
并行广播:
只有动态注册的广播才会并行处理,由registeredReceivers来记录
创建BroadcastRecord对象;
将广播加入到mParallelBroadcasts队列;
执行queue.scheduleBroadcastsLocked;
串行广播:
将registeredReceivers中保存的动态注册的广播合并到receivers中。即动态静态一起处理;
创建BroadcastRecord对象;
将广播加入到mOrderedBroadcasts队列;
执行queue.scheduleBroadcastsLocked;
六、接收广播追踪
1. BroadcastQueue.scheduleBroadcastsLocked()
public void scheduleBroadcastsLocked() { if (mBroadcastsScheduled) { return; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true; }
这里并没有做实际处理,而是发送了一个BROADCAST_INTENT_MSG类型的消息,BroadcastQueue接收到消息后会调用processNextBroadcast()方法。
2. BroadcastQueue.processNextBroadcast()
final void processNextBroadcast(boolean fromMsg) { //处理普通并行广播 //处理有序串行广播 //处理下条有序广播 }
这里只分析普通并行广播的处理:
while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); //遍历mParalleBroadcasts,并将广播发送给他们的接收者 for (int i=0; i<N; i++) { Object target = r.receivers.get(i); //分发给已经注册的广播接收者 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); } //添加到历史记录 addBroadcastToHistoryLocked(r); }
3. BroadcastQueue.deliverToRegisteredReceiverLocked()
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { boolean skip = false; //权限认证 try { 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); } if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } } catch (RemoteException e) { } }
4. BroadcastQueue.performReceiveLocked()
void performReceiveLocked(//省略参数) throws RemoteException { //通过binder异步机制,向receiver发送intent if (app != null) { if (app.thread != null) { //跨进程调用ApplicationThread的scheduleRegisteredReceiver()方法 try { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); } catch (RemoteException ex) { synchronized (mService) { app.scheduleCrash("can't deliver broadcast"); } throw ex; } } else { //应用进程死亡,Receiver不存在. throw new RemoteException("app.thread must not be null"); } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } }
5. Application.scheduleRegisteredReceiver()
public void scheduleRegisteredReceiver(//省略参数) throws RemoteException { //更新进程状态 updateProcessState(processState, false); receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); }
6. InnerReceiver.performReceive()
public void performReceive(//省略参数) { if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { //省略部分代码 } }
7. ReceiverDispatcher.performReceive()
public void performReceive(//省略参数) { //创建Args对象 final Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); //通过mActivityThread的post方法来执行Args中的逻辑,这会调用Args中的run()方法 if (intent == null || !mActivityThread.post(args)) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } }
8. Args.run()
public void run() { final BroadcastReceiver receiver = mReceiver; final boolean ordered = mOrdered; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); try { //获取mReceiver的类加载器 ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); //回调receiver.onReceive()方法 receiver.onReceive(mContext, intent); } catch (Exception e) { } if (receiver.getPendingResult() != null) { finish(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); }
到这里回调了receiver.onReceive()方法之后,一条广播就完成了,当然后面会执行finish()方法,里面会执行处理下一条广播的逻辑,这里就不深究了。
七、接收广播总结
接收过程:根据广播类型,进行分类处理;
遍历广播列表,循环发送给他们的接收者;
回调receiver.onReceive()方法,完成广播处理。
广播注册、发送、接收过程分析完了,这里为了尽量简化只采用了一条普通广播的线来走这个流程,如果是把每种类型广播都分析清楚还是有点复杂的。当然我们只是想揪出一条思路,学习思维,不要深入其中无法自拔。
相关文章推荐
- BroadcastReceiver工作流程
- Nutch爬虫工作流程及文件格式详细分析
- Linux USB驱动工作流程
- 戏说Android view 工作流程《下》
- webkit Dump Render Tree 工作流程
- Linux USB驱动工作流程
- W3C工作流程
- 销售部_直营店工作流程
- 如何进入Google工作? Google的面试题,电话面试和招聘流程介绍
- struts2核心工作流程与原理
- Genesis-3D学习手册——29.场景幕后资源工作流程
- 软件测试工作流程及相关图解
- 【代码管理】GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流
- MyBatis 的工作流程
- NVIDAI和ATI显卡比较,细研GPU工作流程
- 访问控制列表工作过程和执行流程
- 《Pro Git》笔记四:分布式工作流程
- struts2工作流程
- GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流