AIDL的使用:
定义一个AIDL的接口MyInterface,接口内部定义一个String get(String s)方法,这个类默认继承IInterface,
这个类里会自动生成add()方法和代表方法的常量。
然后会在AIDL文件中会生成一个继承自Binder类,实现MyInterface类的,静态内部类Stub(这个类内部)。
创建MyService继承自Service
定义一个IBinder类型的变量:
public class MyService extends Service {
private IBinder binder = new IMyInterface.Stub() {
@Override
public String get(String s) throws RemoteException {
Log.i(TAG, s);
return "我是 Service 返回的字符串";
}
};
}
重写onBind()方法
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
在这个方法里返回binder,如果返回空,那么Activity的onServiceConnected()方法不会被回调。
创建Activity
public class MainActivity extends AppCompatActivity {
public final static String TAG = "MainActivity";
private MyInterface myInterface;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
myInterface = MyInterface.Stub.asInterface(binder);
Log.i(TAG, "连接Service 成功");
try {
String s = myInterface.get("我是Activity传来的字符串");
Log.i(TAG, "从Service得到的字符串:" + s);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "连接Service失败");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent= new Intent(MainActivity.this, MyService.class);
//startService(service);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
启动Service会初始化MyService,bindService会回调MyService的onBind()方法,返回一个binder;
这个binder就是指向了IMyInterface.Stub()并且实现了String get(String s) 如下
private IBinder binder = new IMyInterface.Stub() {
@Override
public String get(String s) throws RemoteException {
Log.i(TAG, s);
return "我是 Service 返回的字符串";
}
};
成功返回了binder,就可以成功回调MainActivity的onServiceConnected(ComponentName name, IBinder binder)方法,
并且返回的binder和方法第二个参数的IBinder binder相对应,
然后调用myInterface = MyInterface.Stub.asInterface(binder);进行判断,源码如下
public static aidl.MyInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//检查Binder是不是在当前进程
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof aidl.MyInterface))) {
return ((aidl.MyInterface) iin);
}
return new aidl.MyInterface.Stub.Proxy(obj);
}
在asInterface方法中,首先判断了传进来的IBinder是不是null,如果为null就返回一个null;
接着就判断传进来的IBinder是不是就在当前进程里面,如果是的话就直接返回IMyInterface,
不是的话就返回MyInterface.Stub.Proxy(obj)。
这里我觉得需要明白的是:直接返回的MyInterface是实现了定义的接口方法get()的,
因为在MyInterface.Stub中所实现的。当然如果是在同一进程中,
那么我们调用IMyInterface的方法时就是在本地调用方法,直接调用就可以了。
如下是Proxy的源码
private static class Proxy implements aidl.MyInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.lang.String get(java.lang.String s) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(s);
//传送数据到远程的
mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
_reply.readException();
//接受从远端传回的数据
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
在Proxy中,我们首先把Service连接成功返回的IBinder它的内部变量mRemote,这里在提一下,这里得IBinder还是是MyService中onBind所返回的。
然后,当我们调用MyInterface的方法的时候,其实就是调用的Proxy的方法了,这也是为什么这个类叫做Porxy的原因了。
当调用MyInterface.get(String s) ,我们就看Proxy中的get,先获取了两个Parcel对象 _data、_data,从变量名就可以看出,
一个是传送数据的,另一个则是接受返回数据的。接着,向_data中写入了DESCRIPTOR(也就是这个类的全名),再写入了方法参数。
然后就到了最重要的一步了,mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
这里我们调用了IBinder的transact方法,来把数据传给远端的服务器。然后在我们远程的MyService中,
里面的Stub中就会回调onTransact()(因为你把数据传个远程的服务,远端的服务收到数据也就回调了)
这里是在远程的服务里调用的。
@Overridepublic
boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getInfor: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
//取出参数
_arg0 = data.readString();
// 远程服务调用自己本地实现的方法获取返回值
java.lang.String _result = this.getInfor(_arg0);
reply.writeNoException();
//写入返回值
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
onTransact方法是在Stub的内部实现的。
先看一下它的四个参数:
code:每个方法都有一个int类型的数字用来区分(后面中的swicth),在我们例子中也就是我们Proxy中的Stub.TRANSACTION_getInfor。
data:传过来的数据,其中包含我们的参数,以及类的描述。
reply:传回的数据,我们要写入是否发生了Exception,以及返回值
flags:该方法是否有返回值 ,0表示有返回值。
调用onTransact就表示有数据传来,首先就会通过swicth判断是哪个方法,然后取出方法参数,调用本地实现的方法获取返回值,写入返回值到reply。
最后,返回true,才会把数据发送出去,发挥false就不会把结果返回给Activity了。这里也就是说,只有返回true,我们Proxy中才能接受从远端传回的数据。
//传送数据到远程的
mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
_reply.readException();
//接受从远端传回的数据
_result = _reply.readString();
注意:Service也是把数据发送出来,让客户端接受的。
Service发出了数据,客户端接收到了,就会一层一层返回去。所以,当我们简单的调用IMyInterface的getInfor时候,
先是Proxy的transact发送出数据,然后服务端的onTransact接受并处理传来的数据,再把处理得到的数据写入返回值并发送给客户端,
客户端读取值后就成为调用方法的返回值返回了。
然后AIDL的基本原理就是这样了,看明白了AIDL,才发现原来AIDL不过就是帮我们生成了那些数据写入,传送,读取的方法而已。
这个类里会自动生成add()方法和代表方法的常量。
然后会在AIDL文件中会生成一个继承自Binder类,实现MyInterface类的,静态内部类Stub(这个类内部)。
创建MyService继承自Service
定义一个IBinder类型的变量:
public class MyService extends Service {
private IBinder binder = new IMyInterface.Stub() {
@Override
public String get(String s) throws RemoteException {
Log.i(TAG, s);
return "我是 Service 返回的字符串";
}
};
}
重写onBind()方法
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
在这个方法里返回binder,如果返回空,那么Activity的onServiceConnected()方法不会被回调。
创建Activity
public class MainActivity extends AppCompatActivity {
public final static String TAG = "MainActivity";
private MyInterface myInterface;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
myInterface = MyInterface.Stub.asInterface(binder);
Log.i(TAG, "连接Service 成功");
try {
String s = myInterface.get("我是Activity传来的字符串");
Log.i(TAG, "从Service得到的字符串:" + s);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "连接Service失败");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent= new Intent(MainActivity.this, MyService.class);
//startService(service);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
启动Service会初始化MyService,bindService会回调MyService的onBind()方法,返回一个binder;
这个binder就是指向了IMyInterface.Stub()并且实现了String get(String s) 如下
private IBinder binder = new IMyInterface.Stub() {
@Override
public String get(String s) throws RemoteException {
Log.i(TAG, s);
return "我是 Service 返回的字符串";
}
};
成功返回了binder,就可以成功回调MainActivity的onServiceConnected(ComponentName name, IBinder binder)方法,
并且返回的binder和方法第二个参数的IBinder binder相对应,
然后调用myInterface = MyInterface.Stub.asInterface(binder);进行判断,源码如下
public static aidl.MyInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//检查Binder是不是在当前进程
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof aidl.MyInterface))) {
return ((aidl.MyInterface) iin);
}
return new aidl.MyInterface.Stub.Proxy(obj);
}
在asInterface方法中,首先判断了传进来的IBinder是不是null,如果为null就返回一个null;
接着就判断传进来的IBinder是不是就在当前进程里面,如果是的话就直接返回IMyInterface,
不是的话就返回MyInterface.Stub.Proxy(obj)。
这里我觉得需要明白的是:直接返回的MyInterface是实现了定义的接口方法get()的,
因为在MyInterface.Stub中所实现的。当然如果是在同一进程中,
那么我们调用IMyInterface的方法时就是在本地调用方法,直接调用就可以了。
如下是Proxy的源码
private static class Proxy implements aidl.MyInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.lang.String get(java.lang.String s) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(s);
//传送数据到远程的
mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
_reply.readException();
//接受从远端传回的数据
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
在Proxy中,我们首先把Service连接成功返回的IBinder它的内部变量mRemote,这里在提一下,这里得IBinder还是是MyService中onBind所返回的。
然后,当我们调用MyInterface的方法的时候,其实就是调用的Proxy的方法了,这也是为什么这个类叫做Porxy的原因了。
当调用MyInterface.get(String s) ,我们就看Proxy中的get,先获取了两个Parcel对象 _data、_data,从变量名就可以看出,
一个是传送数据的,另一个则是接受返回数据的。接着,向_data中写入了DESCRIPTOR(也就是这个类的全名),再写入了方法参数。
然后就到了最重要的一步了,mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
这里我们调用了IBinder的transact方法,来把数据传给远端的服务器。然后在我们远程的MyService中,
里面的Stub中就会回调onTransact()(因为你把数据传个远程的服务,远端的服务收到数据也就回调了)
这里是在远程的服务里调用的。
@Overridepublic
boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getInfor: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
//取出参数
_arg0 = data.readString();
// 远程服务调用自己本地实现的方法获取返回值
java.lang.String _result = this.getInfor(_arg0);
reply.writeNoException();
//写入返回值
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
onTransact方法是在Stub的内部实现的。
先看一下它的四个参数:
code:每个方法都有一个int类型的数字用来区分(后面中的swicth),在我们例子中也就是我们Proxy中的Stub.TRANSACTION_getInfor。
data:传过来的数据,其中包含我们的参数,以及类的描述。
reply:传回的数据,我们要写入是否发生了Exception,以及返回值
flags:该方法是否有返回值 ,0表示有返回值。
调用onTransact就表示有数据传来,首先就会通过swicth判断是哪个方法,然后取出方法参数,调用本地实现的方法获取返回值,写入返回值到reply。
最后,返回true,才会把数据发送出去,发挥false就不会把结果返回给Activity了。这里也就是说,只有返回true,我们Proxy中才能接受从远端传回的数据。
//传送数据到远程的
mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);
_reply.readException();
//接受从远端传回的数据
_result = _reply.readString();
注意:Service也是把数据发送出来,让客户端接受的。
Service发出了数据,客户端接收到了,就会一层一层返回去。所以,当我们简单的调用IMyInterface的getInfor时候,
先是Proxy的transact发送出数据,然后服务端的onTransact接受并处理传来的数据,再把处理得到的数据写入返回值并发送给客户端,
客户端读取值后就成为调用方法的返回值返回了。
然后AIDL的基本原理就是这样了,看明白了AIDL,才发现原来AIDL不过就是帮我们生成了那些数据写入,传送,读取的方法而已。
http://blog.youkuaiyun.com/u011974987/article/details/51243539