public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
在最后几句代码可以看到调用了ActivityManagerNative.getDefault().startActivity,
ActivityManagerNative.getDefault()会得到的一个
ActivityManagerProxy
对象(
IActivityManager接口
),这个类在
ActivityManagerNative中
,它的
startActivity函数源码如下:
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
在这个函数中将一系列信息包装到Parcel中(包括intent),然后调用了mRemote.transact函数。
同时,注意这里
transact的第一个参数传的是START_ACTIVITY_TRANSACTION,这是一个code,在下面会用到。
这样我们就碰触到了IBinder机制,
IBinder很多文章都分析过,这里根据我的理解大概简单讲一下。
IBinder机制主要实现在底层(c++),通过它来实现进程间的通信.
简单来说是一端作为service,另一端作为client(实际上都是service,只不过在不同的情况下角色不同,都可以转换)
(1)消息发出方,即客户端的service通过BpBinder(在这个流程中就是
代码中的mRemote
)打开/dev/binder设备(linux的一块内核空间,实际上就是共享内存),并将信息写入(即IBinder的
transact函数)。
(2)消息接收方,即服务端的service会开启循环线程(其实从注册后就开始了),通过BBinder(在这个流程中是一个
ActivityManagerNative对象,下面会讲到)不停的从/dev/binder设备中读取信息,然后根据信息做相应的处理(IBinder的onT
ransact函数)
(3)这时当原客户端从
/dev/binder设备得到对方已收到的信息后,角色转换为服务端,等待回复即replay(同样循环线程)。
(4)当原服务端处理后需要回复时,角色转为客户端,发送回复。
这样就实现了跨进程的通信。
因为是通过binder,所以我们的消息如intent之类都要包装成binder支持的Parcel,这也是intent只能传递可系列化对象的原因。同时因为这块共享内存大小的限制,也就导致了intent传递数据的大小限制(关于Parcel和大小限制请阅读:Android中Intent/Bundle的通信原理及大小限制一文)。
同样因为binder机制,我们不仅可以启动本app中的activity(自己同时是客户端和服务端),也可以启动其他app中公开的acitivity。
ActivityManagerNative类实际上继承了Binder(IBinder接口),也就是上面提到的BBinder的角色。当接收并解析binder消息后会调用它的
onTransact来进行处理,
在
ActivityManagerNative中
onTransact非常庞大,根据code做不同的处理,我们只需要关注
START_ACTIVITY_TRANSACTION这个code即可。
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
...
}
拿到Parcel类型的数据,然后反系列化解析成Intent等,最后调用
startActivity,但是在
ActivityManagerNative并没有找到这个函数,那是因为
ActivityManagerNative是一个抽象类,真正的实现是在它的子类
ActivityManagerService中,然后通过ApplicationTreadProxy等类启动activity。这部分不是我们本文的重点,而且比较复杂,就不详细说了。借用网上一张时序图来展示一下这个流程。
Android进阶之路系列:http://blog.csdn.net/column/details/16488.html