Android BroadcastReceiver的工作流程源码分析(8.0)
来源:互联网 发布:nginx location server 编辑:程序博客网 时间:2024/06/03 20:20
一,写在前面
本篇文章会从源码角度分析广播的工作流程,具体来说是分为两部分:广播的注册,发送广播。在阅读本篇文章前,建议先了解Activity,Service相关的工作流程。本篇文章将不再分析工作流程中的重复细节,参考文章:
Android Activity的启动流程源码解析(8.0)
Android Service的启动流程源码分析(8.0)
Android Service的绑定流程源码分析(8.0)
二,广播的注册,交给ContextImpl
广播的注册分为静态注册,以及动态注册。静态注册是在xml中配置<receiver>节点,在应用程序启动后会解析xml文件,具体的注册流程是交给PackagerManagerService来处理。本篇文章主要分析广播的动态注册,也就是在Java代码中调用registerReceiver方法来注册广播,开发中具体的使用这里不再介绍。
不管是在Activity,还是Service中注册广播,都是调用ContextWrapper$registerReceiver方法。其中,ContextWrapper是Context的一个子类,在抽象类Context中定义了抽象方法registerReceiver,具体实现在子类ContextWrapper中。
查看ContextWrapper$registerReceiver源码:
@Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }第4行,变量mBase是Context类型,而Context是一个抽象类,其实mBase的具体实现类是ContextImpl。至于具体原因,可以查看文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
查看ContextImpl相关源码:
@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); } //继续查看... 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(); } 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(); } } //...code final Intent intent = ActivityManager.getService().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId, flags); //...code }第17行,ContextImpl$registerReceiver有多个重载方法,但最终都会调用ContextImpl$registerReceiverInternal方法。
第24行,mMainThread是一个ActivityThread类型的变量,它的实例化在ContextImpl的构造方法中。mMainThread.getHandler()返回一个H类型的对象,H是ActivityThread的内部类,继承了Handler。值得一提的是,在启动Activity,Service的工作流程中,都会创建一个上下文环境,也就是会创建ContextImpl对象。具体分析,见文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
第26行,变量mPackageInfo是一个LoadedApk的变量,这里是将BroadcastReceiver对象封装到ReceiverDispatcher中,并最终返回IIntentReceiver类型的对象。有意思的是,ReceiverDispatcher与绑定服务中的ServiceDispatcher比较类似,都是将组件对象进行封装,并返回一个Binder对象,用于实现组件对象在进程间的通信。
由于逻辑与绑定服务流程中的LoadedApk$ServiceDispacher类似,具体分析可参考文章 Android Service的绑定流程源码分析(8.0) 。这里rd返回IIntentReceiver类型的对象,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver,其具体结构:final static class InnerReceiver extends IIntentReceiver.Stub 。
第33行,当mPackageInfo为null时,给rd赋值,做的事情与前面讲到的第26行一样。
第40行,ActivityManager.getService()返回一个IActivityManager的代理对象,调用其registerReceiver方法会向系统服务发送一个请求,基于Binder机制,会调用ActivityManagerService$ActivityManage方法。具体分析,见文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
三,广播的注册,交给ActivityManagerService处理
查看ActivityManagerService$ActivityManage方法源码:
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId, int flags) { //...code if (callerApp != null && (callerApp.thread == null || callerApp.thread.asBinder() != caller.asBinder())) { // Original caller already died 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); } //...code BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId, instantApp, visibleToInstantApps); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); //...code }第8行,caller是一个IApplicationThread类型的变量,是一个Binder对象,具体源码见文章 Android Activity的启动流程源码解析(8.0) ,这里会检查它的对应的Binder对象。
第12行,变量mRegisteredReceivers的定义: HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>()。
key:receiver.asBinder()返回的是IIntentReceiver对象对应的Binder对象。IIntentReceiver前面已经分析过了,它封装了BroadcastReceiver对象,且是一个Binder对象。
value:ReceiverList类型的对象,它是一个存储BroadcastFilter对象的List集合。结构:class ReceiverList extends ArrayList<BroadcastFilter> implements IBinder.DeathRecipient。
第14行,创建ReceiverList对象,注意最后一个参数receiver,说明ReceiverList封装了InnerReceiver对象。
第31行,BroadcastFilter结构:class BroadcastFilter extends IntentFilter 。BroadcastFilter对象中封装了ReceiverList对象,IntentFilter对象。
第37行,mReceiverResolver是一个IntentResolver类型的变量,该类里面维护了集合,并调用addFilter方法将bf存储起来。
也就是说,注册广播的就是将InnerReceiver对象,IntentFilter对象封装在类BroadcastFilter中,并最终将BroadcastFilter对象存储在变量mReceiverResolver中。值得一提的是,在发送广播的流程中,会取出变量mReceiverResolver中存储的广播接受者相关的数据。动态注册广播的分析,到此就结束了~
四,发送广播,交给ContextImpl处理
与动态注册广播一样,发送广播实际上调用的ContextWrapper$sendBroadcast方法;
查看ContextWrapper$sendBroadcast方法源码:
@Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); }第3行,变量mBase实现类是ContextImpl,与动态注册广播一样的。
查看ContextImpl$sendBroadcast方法源码:
public void sendBroadcast(Intent intent) { //... ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); //... }
ActivityManager.getService()返回一个IActivityManager接口的代理对象,向系统服务AMS发起一个请求,会调用ActivityManagerService$broadcastIntent方法。具体细节不再分析,动态注册广播时已经提到。
五,发送广播,交给ActivityManagerService处理
查看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) { //... synchronized(this) { intent = verifyBroadcastLocked(intent); //... int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, serialized, sticky, callingPid, callingUid, userId); //... return res; } }第9行,主要对intent的flag进行检查;
第13行,查看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) { //... // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); //... registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId); //... BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, callerInstantApp, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); //... queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); //...}第10行,设置flag为FLAG_EXCLUDE_STOPPED_PACKAGES时,广播不会发送给已经停止的应用。本篇文章是基于8.0的源码,其实从Android3.1开始,发送广播会默认添加flag为FLAG_EXCLUDE_STOPPED_PACKAGES,禁止向停止应用发送广播,为了避免调用已经停止的应用。另外,若想将广播发送给已经停止的应用,也可以设置flag为FLAG_INCLUDE_STOPPED_PACKAGES。值得一提的是,应用处于停止状态意思是:应用安装后没有启动,或被手动,其他应用强行停止了。
第14行,前面分析广播注册流程,最后有提到变量mReceiverResolver,它存储了BroadcastFilter对象,也就是存放了广播接受者相关的信息。调用IntentResolver$queryIntent方法用于获取与该intent相匹配的广播接受者,返回的是一个List集合,因此变量registeredReceivers是一个List类型变量。
第21行,将变量registeredReceivers封装在BroadcastRecord对象中。
第26行,变量queue是一个BroadcastQueue类型的对象,BroadcastQueue queue = broadcastQueueForIntent(intent)。
查看BroadcastQueue$enqueueParallelBroadcastLocked方法源码:
public void enqueueParallelBroadcastLocked(BroadcastRecord r) { mParallelBroadcasts.add(r); enqueueBroadcastHelper(r); }第2行,变量mParallelBroadcasts是一个ArrayList类型的对象,用于存放BroadcastRecord对象。ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>()。后面,会取出mParallelBroadcasts集合中的数据,完成广播的接受。
继续回到ActivityManagerService$broadcastIntentLocked的第27行,调用了queue.scheduleBroadcastsLocked(),这个是重点入口。
六,广播的接收
查看BroadcastQueue相关方法源码:
public void scheduleBroadcastsLocked() {//...codemHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));//...code}//继续查看...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; //...code } } }//继续查看...final void processNextBroadcast(boolean fromMsg) { synchronized(mService) { BroadcastRecord r; //...= if (fromMsg) { mBroadcastsScheduled = false; } // 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(); //... for (int i=0; i<N; i++) { Object target = r.receivers.get(i); //... deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i); } //... } //... }}第4行,发送一个what为BROADCAST_INTENT_MSG的消息;
第19行,处理what为BROADCAST_INTENT_MSG的消息;
第22行,继续调用processNextBroadcast方法;
第44行,变量mParallelBroadcasts前面已经讲过,是一个ArrayList集合,存储了BroadcastRecord对象,而BroadcastRecord对象封装了广播接受者相关的信息;
第45行,取出index为0的BroadcastRecord对象,并将该对象删除;
第51行,r.receivers返回一个List集合,里面存放了BroadcastFilter对象。注册广播流程中已经分析过BroadcastFilter对象,它封装了广播接受者相关的信息。
第55行,对r.receivers对应的集合进行遍历,完成所有匹配的BroadcastReceiver对广播的接受。然后会调用deliverToRegisteredReceiverLocked方法,这个是一个重要入口。
查看BroadcastQueue$deliverToRegisteredReceiverLocked方法源码:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) {//...codeperformReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId);//...code}//继续查看...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) { // 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); //... } //... }//...}第21,22行,对app,app.thread进行判空检查;
第26行,app.thread返回IApplicationThread接口的代理对象,最终会调用ApplicationThread$scheduleRegisteredReceiver方法。关于ApplicationThread的描述,这里不能理解的,请参考文章 Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
查看ActivityThread$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);}第5行,变量receiver是一个IIntentReceiver类型的对象,在注册广播的流程中提到过IIntentReceiver,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver。其实InnerReceiver是一个Binder接口,封装BroadcastReceiver对象后,使组件对象可以在进程间传递。
查看LoadedApk$ReceiverDispatcher$InnerReceiver$performReceive方法源码:
@Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {//...final LoadedApk.ReceiverDispatcher rd;//...rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);//... }第10行,调用LoadedApk$ReceiverDispatcher$performReceive方法;
查看LoadedApk$ReceiverDispatcher$performReceive方法源码:
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);//...if (intent == null || !mActivityThread.post(args.getRunnable())) {//...}}第10行,变量mActivityThread是ActivityThread$H类型的对象,它继承了Handler,接受广播的操作是在Handler所在的线程中执行,也就是在ActivityThread主线程中执行。
args.getRunnable()返回一个Runnable接口;
查看LoadedApk$ReceiverDispatcher$Args源码如下:
final class Args extends BroadcastReceiver.PendingResult { //... public final Runnable getRunnable() {return () -> { final BroadcastReceiver receiver = mReceiver; //... receiver.onReceive(mContext, intent); //... }; }}第10行,回调BroadcastReceiver$onReceive方法,于是前面注册的广播接受者,就接收到发送的广播了~
七,最后
本篇文章,从动态注册广播,发送广播,接收广播来分析BroadcastReceiver的工作机制。
阅读本篇文章前,建议先阅读如下文章:
Android Activity的启动流程源码解析(8.0)
Android Service的启动流程源码分析(8.0)
Android Service的绑定流程源码分析(8.0)
阅读全文
0 0
- Android BroadcastReceiver的工作流程源码分析(8.0)
- Android基于源码分析AsyncTask的工作流程
- BroadcastReceiver工作流程
- AsyncTask工作流程源码分析
- [netty源码分析]--服务端启动的工作流程分析
- Android四大组件BroadcastReceiver源码分析
- 结合源码分析Solr&Lucene查询打分的工作流程
- Android Service的启动流程源码分析(8.0)
- Android Service的绑定流程源码分析(8.0)
- 源码分析android的UI绘制流程
- Android vold 工作流程分析
- [Android] ButterKnifeProcessor 工作流程分析
- BroadcastReceiver源码分析
- Libevent源码分析-----Libevent工作流程探究
- Libevent源码分析-----bufferevent工作流程探究
- Libevent源码分析-----bufferevent工作流程探究
- Libevent源码分析-----Libevent工作流程探究
- Libevent源码分析-----bufferevent工作流程探究
- vijos-P1023
- zookeeper API
- Synopsys dc-2010-sp5-3安装过程(下)
- 17.11.26,web学习第十二天,还有一年,努力吧青年HTTp协议和TomCat服务器
- Unity3D协程介绍 以及 使用
- Android BroadcastReceiver的工作流程源码分析(8.0)
- 表达式类型自动提升
- 正向代理&&反向代理
- 关于java里 return的接收
- 把带符号的二进制数据(10进制显示) 来 换成十进制的数据
- PHPStorm 常用功能设置
- 进制
- Servlet之用户登录过程实现
- HTML && CSS 学习笔记(1)CSS(关键词:CSS/样式表/style)