今天在分析Application的启动流程
ActivityThread 中的ApplicationThread 是一个stub类
ActivityManagerService作为IActivityManager的stub
使用 attachApplication 方法将该ApplicationThread 的 stub对象 传入,这看上去像是一个binder的双向绑定
见如下代码
final ApplicationThread mAppThread = new ApplicationThread();
private void attach(boolean system) {
......
if (!system) {
......
//mgr是其实就是ActivityServiceManager的一个binder远程调用对象
final IActivityManager mgr = ActivityManager.getService();
try {
//这里将mAppThread这个binder对象传入了
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
//ActivityServiceManager持有ApplicationThread这个binder对象 完成Applicaiton的绑定等工作
......
} else {
......
}
......
}
private class ApplicationThread extends IApplicationThread.Stub{
......
void bindApplication(...)
......
}
在大部分的学习资料中,介绍AIDL时一般使用传统的 service-client 做为示例
通常情况下,client远程绑定service并调用service的方法。但是涉及到service调用client方法的却很少,
今天来尝试实现一个client与service的双向绑定
一:定义两个AIDL类
//ClientInterface.aidl
package vivo.testaidl;
interface ClientInterface {
String messageFromClient();
}
//ServiceInterface.aidl
package vivo.testaidl;
import vivo.testaidl.ClientInterface;
interface ServiceInterface {
String messageFromService();
void registerClient(ClientInterface cb);
}
实现了简单的message打印功能
二:编写service端
package vivo.testaidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
/**
* Created by chenlong on 2019/3/11.
*/
public class RemoteService extends Service {
private ClientInterface mClientBinder;
private ServiceInterface mServiceBinder = new ServiceInterface.Stub() {
@Override
public String messageFromService() throws RemoteException {
if (mClientBinder != null) {
String messageFromClient = mClientBinder.messageFromClient();
System.out.println("messageFromClient = " + messageFromClient);
}
return "message from service";
}
@Override
public void registerClient(ClientInterface clientBinder) throws RemoteException {
// 这里拿到的直接就是ClientInterface的proxy类型
// 之前我们看AIDL源码的时候说过Service的onServiceConnected里面传入的是BinderProxy
// 然后使用asInterface来进行转换为定义的Interface
// 那这里为啥可以直接使用 不需要转换呢 我们看AIDL生成的源码部分
// Service的registerClient方法
// @Override
// public void registerClient(vivo.testaidl.ClientInterface cb) throws android.os.RemoteException {
// android.os.Parcel _data = android.os.Parcel.obtain();
// android.os.Parcel _reply = android.os.Parcel.obtain();
// try {
// _data.writeInterfaceToken(DESCRIPTOR);
// _data.writeStrongBinder((((cb != null)) ? (cb.asBinder()) : (null)));
// mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
// _reply.readException();
// } finally {
// _reply.recycle();
// _data.recycle();
// }
// }
// 调用了 mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
// 我们知道这里会调用Stub的onTransact方法 并传入TRANSACTION_registerClient这个code
// 在看 onTransact 方法
// case TRANSACTION_registerClient: {
// data.enforceInterface(DESCRIPTOR);
// vivo.testaidl.ClientInterface _arg0;
// _arg0 = vivo.testaidl.ClientInterface.Stub.asInterface(data.readStrongBinder());
// this.registerClient(_arg0);
// reply.writeNoException();
// return true;
// 真相大白
// 其实在registerClient的时候 ServiceInterface已经帮忙转换过了
mClientBinder = clientBinder;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return (IBinder) mServiceBinder;
}
}
三:编写client端
package vivo.testaidl;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
/**
* Created by chenlong on 2019/3/11.
*/
public class ClientActivity extends Activity {
ServiceInterface mService;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, RemoteService.class);
this.bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
ClientInterface mClientBinder = new ClientInterface.Stub() {
@Override
public String messageFromClient() throws RemoteException {
return "Message From Client";
}
};
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ServiceInterface.Stub.asInterface(service);
try {
mService.registerClient(mClientBinder);
String messageFromService = mService.messageFromService();
System.out.println("messageFromService = " + messageFromService);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
}
四:注册
<?xml version="1.0" encoding="utf-8"?>
<manifest package="vivo.testaidl"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ClientActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true"
android:process=":remote"></service>
</application>
</manifest>
client端在页面启动后绑定service 并且在拿到service的serviceBinder对象后调用方法并传入了一个clientBinder进去,service端拿到clientBinder之后调用了clientBinder的方法 实现双向的通信,整个过程比较简单,唯一一个比较引人注意的地方就是service的registerClient方法,在之前的“从AIDL调用看Binder使用方法”这篇文章中 ,我们拆解了整个AIDL调用的逻辑,并自己实现了模拟的AIDL调用,其中AidlInterfaceUtils的asInterface方法实现了对一个系统提供的远程IBinder的转换,那我们将clientBinder作为参数传给ServiceBinder的时候 Service拿到这个binder 为什么不需要使用asInterface进行转换呢,我们进一步追踪源码
看AIDL 自动生成的源码部分
// Service的registerClient方法
@Override
public void registerClient(vivo.testaidl.ClientInterface cb) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((cb != null)) ? (cb.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
// 调用了 mRemote.transact(Stub.TRANSACTION_registerClient, _data, _reply, 0);
// 我们知道这里会调用Stub的onTransact方法 并传入TRANSACTION_registerClient这个code
// 在看 onTransact 方法
case TRANSACTION_registerClient: {
data.enforceInterface(DESCRIPTOR);
vivo.testaidl.ClientInterface _arg0;
_arg0 = vivo.testaidl.ClientInterface.Stub.asInterface(data.readStrongBinder());
this.registerClient(_arg0);
reply.writeNoException();
return true;
// 真相大白
// 其实在registerClient的时候AIDL自动生成的代码已经把IBinder转为ServiceInterface了
其实在registerClient的时候AIDL自动生成的代码已经调用了asInterface方法 把IBinder转为ServiceInterface了
代码下载
https://download.csdn.net/download/binghelonglong123/11012666