对Android广播接收与发出机制的一些AMS以外的源码分析
来源:互联网 发布:左飞 算法之美 编辑:程序博客网 时间:2024/06/06 05:40
1.简介
在安卓的广播机制中,用户自定义的Activity或自定义的子类BroadcastReceiver扮演着接收器的角色,Activity本身以及各类系统事件(如有电话拨入)也可以扮演广播发出者的角色。而其中,Android的Activity Manager Service无疑扮演着核心角色。总体上,安卓的广播采用的是订阅者、发布者的设计模式。
本文中,我们不深入AMS进行源码分析,而是关于接收与发出广播前,Activity周边依赖的一些类进行的一些初始化操作。本文也更倾向于从体系结构层次探讨广播的实现机制。
2.注册一个广播接收器
我们结合实例来进行分析。首先,我们定义一个MyActivity,用于接收广播:
public class MyActivity extends Activity implements OnClickListener { ...... @Override public void onCreate() { super.onCreate(); IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION); registerReceiver(counterActionReceiver, counterActionFilter); } ...... }
在这里,我们就通过registerReceiver方法将自己注册到广播接收器之中。让我们进行一下细致的分析。
阅读源码可知,Activity实现了Context接口,而registerReceiver正是Context的一个成员方法,而Activity继承的是ContextWrapper包装类,我们调用的是ContextWrapper实现中的registerReceiver方法,源码为:
@Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); }
这里,mBase是ContextImpl的一个实例(在Activity初始化时,将实现类绑定到ContextWrapper包装类上,也就是我们常说的装饰者模式,这里不展开讲了)。
接下来我们看到ContextImpl中的
registerReceiver(receiver, filter);
方法:
@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()); }//最终的执行方法 private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null;//开始寻找IIntentReceiver实例 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 {//找到实例后,调用ActivityManagerService的注册接收器方法 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(); } }
我们可以看到,经过多层跳转,最后进入registerReceiverInternal方法中。此方法内先是寻找IIntentReceiver实例(这是一个Binder对象),再调用ActivityManagerNatice中的方法。
我们进入ActivityManagerNative.java中的ActivityManagerProxy的的registerReceiver中看一看:
public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, IntentFilter filter, String perm, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(packageName); data.writeStrongBinder(receiver != null ? receiver.asBinder() : null); filter.writeToParcel(data, 0); data.writeString(perm); data.writeInt(userId); mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0); reply.readException(); Intent intent = null; int haveIntent = reply.readInt(); if (haveIntent != 0) { intent = Intent.CREATOR.createFromParcel(reply); } reply.recycle(); data.recycle(); return intent; }在这里,通过Binder底层通信机制去调用AMS中的registerReceiver函数,至此,在广播接收器注册过程中,对AMS的调用的前期初始化代码已全部分析完了。
3.发送广播
大家都知道,在Service或Activity等组件类中向外发送广播可以直接调用sendBroadcast(intent);
而这里sendBroadcast方法事实上是在其父类ContextWrapper中定义的,源码如下:
@Override public void sendBroadcast(Intent intent) { mBase.sendBroadcast(intent); }和第二章中提到的一样,mBase是ContextImpl的一个实例,因此我们看到ContextImpl中的sendBroadcast方法
@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()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }因此,会直接深入调用ActivityManagerNative.java中的ActivityManagerProxy的broadcastIntent方法:
public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null); data.writeInt(resultCode); data.writeString(resultData); data.writeBundle(map); data.writeStringArray(requiredPermissions); data.writeInt(appOp); data.writeBundle(options); data.writeInt(serialized ? 1 : 0); data.writeInt(sticky ? 1 : 0); data.writeInt(userId); mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0); reply.readException(); int res = reply.readInt(); reply.recycle(); data.recycle(); return res; }
随后,此进程通过Binder通信机制调用AMS中的相关方法进行广播的发送。
4. 小结
总体上,AMS外部的代码就是层层深入,进行初始化操作,而AMS内部则是通过订阅/发布的设计模式来实现广播。
下一章,我们将探讨AMS内部对于广播发送/接收机制的处理,或对Binder机制进行一些讨论
- 对Android广播接收与发出机制的一些AMS以外的源码分析
- 广播的发出与接收
- Android简单的广播发出和接收
- 2016年9月2号-心情很差--收发广播Broadcast,两个广播同时发出的接收与本项目发出广播,另一个项目接收广播
- 【记录】Android 广播的发送与接收
- Android 广播的发送与接收
- Android广播的发送与接收
- android的广播发送与接收
- Android 广播代码的发送与接收
- Android广播的发送与接收
- Android ActivityManagerService(AMS)的启动分析
- Android ActivityManagerService(AMS)的启动分析
- 广播的接收与U盘广播
- 广播的接收与U盘广播
- 广播的发送与接收
- 广播的发送与接收
- 广播的发送与接收
- Android广播之发送广播的源码分析
- php面向对象必知会
- C语音基础-typedef 24
- Java调用Dll
- 通信框架Netty的详细介绍及应用
- Linux下C语言开发(已知进程名得到其PID号)
- 对Android广播接收与发出机制的一些AMS以外的源码分析
- 判断今天是今年的第几天(2)
- Windows版本搭建安装React Native环境配置及相关问题
- CSS Fundamentals/Basic CSS Structure & Syntax
- && 和 || 的一些用法
- 关于基类和派生类的构造函数和析构函数的执行顺序问题
- Git提交记录
- php冒泡和选择排序
- phpStorm(1)——内置的REST Client (发送http请求)