BroadcastReceiver的工作过程
来源:互联网 发布:视频剪辑配音软件 编辑:程序博客网 时间:2024/05/22 03:41
BroadcastReceiver的工作过程
本篇博客不介绍BroadcastReceiver的具体使用,只对广播的注册过程和发送接收过程进行源码分析。
介绍一下几个重要的概念:
1.Context:http://blog.csdn.net/qinjuning/article/details/7310620
2.ActivityThread、ApplicationThread:http://blog.csdn.net/myarrow/article/details/14223493
广播的注册过程
广播分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,是由PMS来完成整个注册过程的,其他三大组件都是在应用安装时由PMS解析并注册的。这里只分析广播的动态注册。
动态注册的过程从ContextWrapper的registerReceiver()方法开始。
@Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
mBase就是ContextImpl。
@Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); }
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) { 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 { return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); } catch (RemoteException e) { return null; } }
分析:系统首先从mPackageInfo获取IItentReceiver(Binder接口,具体实现是LoadedApk.RecevierDispatcher.InnerRecevier)对象,然后再采用跨进程的方式向AMS发送广播注册的请求。RecevierDispatcher内部保存了BroadcastRecevier和InnerRecevier,这样当接收广播时,RecevierDispatcher可以方便的调用BroadcastRecevier的onReceive方法,和Service的实现原理类似。
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; return rd.getIIntentReceiver(); } }
显然,getReceiverDispatcher方法重新创建了一个ReceiverDispatcher对象并将其保存的InnerReceiver对象作为返回值返回,其中InnerReceiver对象和BroadcastReceiver都是在ReceiverDispatcher的构造方法中被保存下来。
由于注册广播的真正实现过程在AMS中,看一下源码。
AMS#registerReceiver
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ........... mRegisteredReceivers.put(receiver.asBinder(), rl); } else if (rl.uid != callingUid) { throw new IllegalArgumentException( "Receiver requested to register for uid " + callingUid + " was previously registered for uid " + rl.uid); } else if (rl.pid != callingPid) { throw new IllegalArgumentException( "Receiver requested to register for pid " + callingPid + " was previously registered for pid " + rl.pid); } else if (rl.userId != userId) { throw new IllegalArgumentException( "Receiver requested to register for user " + userId + " was previously registered for user " + rl.userId); } 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); ........ }
上面截取了部分关键代码分析:把远程的InnerReceiver对象以及IntentFilter对象储存起来。这样整个广播的注册过程就完成了。
广播的发送和接受过程
当通过send方法来发送广播时,AMS会查找出匹配的广播接受者并将广播的发送给它们处理。
先从发送分析。ContextWrapper的sendBroadcast方法把事情交给ContextImpl去处理。
@Override public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, getUserId()); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } }
它直接向AMS发起了一个异步请求用于发送广播。
AMS#broadcastIntent
public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options, 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(); int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, null, serialized, sticky, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } }
broadcastIntent调用了broadcastIntentLocked方法,在broadcastIntentLocked的内部根据intent-filter查找出匹配的广播接受者并经过一系列的条件过滤,最终将满足条件的广播接受者添加到BroadcastQueue中,接着BroadcastQueue就会将广播发送给相应的广播接受者。源码如下
int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { // If we are not serializing this broadcast, then send the // registered receivers separately so they don't wait for the // components to be launched. final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r); final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r); if (!replaced) { queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } registeredReceivers = null; NR = 0;
BroadcastQueue中广播的发送过程的实现:
BroadcastQueue#scheduleBroadcastsLocked
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)); mBroadcastsScheduled = true; }
并没有立即发送广播而是发送了BROADCAST_INTENT_MSG消息,BroadcastQueue收到消息后调用processNextBroadcast方法。
对普通广播的处理如下:
// First, deliver any non-serialized broadcasts right away. while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast [" + mQueueName + "] " + r); 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); } addBroadcastToHistoryLocked(r); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast [" + mQueueName + "] " + r); }
无序广播存储在mParallelBroadcasts中,系统遍历mParallelBroadcasts并将其中的广播通过deliverToRegisteredReceiverLocked发送接受者。
deliverToRegisteredReceiverLocked方法负责将一个广播发送给一个特定的接受者,它内部调用了performReceiveLocked方法具体实现发送过程。
private static 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) { if (app.thread != null) { // If we have an app thread, do the call through that so it is // correctly ordered with other one-way calls. app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); } 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); } }
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); }
InnerRecevier的performReceive方法会调用LoadedApk.ReceiverDispatcher的performRecieve方法。
LoadedApk.ReceiverDispatcher#performRecieve
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq + " to " + mReceiver); } Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); if (!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); } } }
创建一个Args对象并通过mActivityThread的post方法来执行Args中的逻辑,而Args实现了Runnable接口。mActivityThread就是ActivityThread的Handler H。
final BroadcastReceiver receiver = mReceiver;receiver.setPendingResult(this);receiver.onReceive(mContext, intent);
这时BroadcastReceiver的onReceive方法被执行了,也就是说应用已经接收到广播了,同时onReceive方法是在广播接收者的主线程中被调用的。
- BroadcastReceiver的工作过程
- 四大组件BroadcastReceiver的工作过程
- BroadcastReceiver工作过程
- (十九)四大组件的工作过程-BroadcastReceiver
- BroadcastReceiver工作流程
- Android BroadcastReceiver的工作流程源码分析(8.0)
- Velocity的工作过程
- pppoe的工作过程
- Hibernate的工作过程
- UPnP的工作过程
- ping的工作过程
- 每天的工作过程
- pppoe的工作过程
- SSH 的工作过程
- 编译器的工作过程
- 编译器的工作过程
- GCC的工作过程
- 编译器的工作过程
- MyBatis中Like语句使用
- 获取MainFest中MetaData对应的key节点数据
- 2015年11月Xcode7.1(7B91b)打包发布苹果iOS应用指南
- caffe 如何训练自己的数据图片
- 在搜索领域,我是他们的老师,谷歌抄袭百度的技术
- BroadcastReceiver的工作过程
- 服务器上图片的存储
- qt的Qt::ConnectionType详细以及信号参数传递
- 【剑指offer-Java版】39二叉树的深度
- AsyncTask doInBackgroud not running
- java项目打包成exe文件
- 如何实时查看mysql当前连接数?
- Xcode真机测试could not find developer disk image解决方法
- QtPropertyBrowser2.6在Qt Creator中的编译部署