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机制进行一些讨论