什么是AIDL服务
一般创建的服务并不能被其他的应用程序访问。为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
服务端创建过程
- 新建一个扩展名为IMyService.aidl的文件,并写下需要的接口。重新编译,会自动生成一个IMyService.java文件。
- 建立一个服务类(Service的子类)。并在创建的服务类中创建一个内部类,实现由aidl文件生成的Java接口。在服务类的onBind方法返回时,将实现aidl接口的内部类对象返回出去。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package com.um.aidlservicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
public MyService() {
}
// 创建一个继承自IMyService.Stub的内部类
public class MyServiceImpl extends IMyService.Stub {
// 必须实现AIDL文件中的接口
@Override
public int add(int arg1, int arg2) throws RemoteException {
return arg1 + arg2;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new MyServiceImpl();
}
}- 在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,
标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
1
2
3
4
5
6<service
android:name="com.um.aidlservicedemo.MyService"
android:enabled="true"
android:exported="true"
android:process=":remote">
</service>客户端使用
- 新建一个AidlClientTestActivity,并将刚才远程服务端自动生成的app/build/目录下面的IMyService.java文件连同包目录一起复制到src/main目录中。

- 调用AIDL服务首先要绑定服务,然后才能获得服务对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54package com.um.aidlservicedemo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class AidlClientTestActivity extends AppCompatActivity {
private static String TAG = "AidlClientTestActivity";
TextView textView;
IMyService iMyService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected: ");
iMyService = IMyService.Stub.asInterface(service);
try {
textView.setText("" + iMyService.add(1,2));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected: ");
iMyService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: ");
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
Intent serviceIntent = new Intent();
serviceIntent.setComponent(new ComponentName("com.um.aidlservicedemo","com.um.aidlservicedemo.MyService"));
bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
unbindService(serviceConnection);
}
}整体结构
前面有提到Stub、asInterface等关键字,在这一节中我们主要针对AIDL内部机制的分析来深入理解AIDL调用的过程。打开IMyService.Java文件查看,发现他的结构是这样的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96package com.um.aidlservicedemo;
public interface IMyService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
* 可以看出,Stub其实是一个实现了IMyService的Binder抽象类。
*/
public static abstract class Stub extends android.os.Binder implements com.um.aidlservicedemo.IMyService {
private static final java.lang.String DESCRIPTOR = "com.um.aidlservicedemo.IMyService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
//把远程Service的Binder对象传递进去,得到的是远程服务的本地代理
public static com.um.aidlservicedemo.IMyService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.um.aidlservicedemo.IMyService))) {
return ((com.um.aidlservicedemo.IMyService) iin);
}
return new com.um.aidlservicedemo.IMyService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
//两个不同进程之间传递是通过onTransact接口完成的
@Override
public 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_add: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//远程服务的本地代理,当然也会继承自IMyService
private static class Proxy implements com.um.aidlservicedemo.IMyService {
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;
}
//调用的add方法其实就是这里。
@Override
public int add(int arg1, int arg2) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(arg1);
_data.writeInt(arg2);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
//可以看到,系统将我们的方法转换成以FIRST_CALL_TRANSACTION为基准的数字。
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int add(int arg1, int arg2) throws android.os.RemoteException;
}下面时一个结构图:

整体上来看,IMyService.java文件中的IMyService类有一个Stub的内部类,还有一个getValue方法。这个方法就是我们在aidl中定义的方法。同时我们看到,生成的IMyService继承自IInterface,说明这也是一个接口,并没有对getValue进行实现。
对于add这个方法,当我们在服务端的内部类中继承了IMyService.Stub抽象类以后,就需要对未曾实现的getValue方法进行定义。
再来看IMyService的内部类Stub。这个内部类是一个实现了IMyService接口的Binder抽象类。内部有3个方法asInterface、asBinder、onTransact,还有一个内部类Proxy。得到的服务端Service对象
现在我们来看一下客户端当初得到的服务端对象的情况,当我们连接上服务端后,会被动调用onServiceConnected方法:
1
2
3public void onServiceConnected(ComponentName name, IBinder service) {
iMyService = IMyService.Stub.asInterface(service);
}在这里得到的service对象其实就是MyServiceImpl对象,他是实现了IMyService.Stub具体接口的IBinder。再来看一下asInterface:
1
2
3
4
5
6
7
8
9
10
11public static com.um.aidlservicedemo.IMyService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.um.aidlservicedemo.IMyService))) {
return ((com.um.aidlservicedemo.IMyService) iin);
}
//通过asInterface得到的其实是远程Service的本地“代理”,而代理对象的参数是远程的服务端“obj”
return new com.um.aidlservicedemo.IMyService.Stub.Proxy(obj);
}可以看出,onServiceConnected参数是远程服务端的IBinder对象,返回值是IMyService.Stub.Proxy(obj),这里的Proxy是Stub的内部类:
1
private static class Proxy implements com.um.aidlservicedemo.IMyService {}
内部除了构造方法以外,只有add方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@Override
public int add(int arg1, int arg2) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(arg1);
_data.writeInt(arg2);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
} 到这里我们看到,Proxy内部确实拥有服务端的各个方法,但这些方法并不是真实的实现,而只是通过mRemote.transact传输出去。
也就是说,在客户端通过mIMyService = IMyService.Stub.asInterface(service)得到的就是Proxy对象,可以通过这个对象间接的调用服务端的各个方法,而具体调用过程就是经过mRemote.transact传输给真正的Service(也就是MyService.MyServiceImpl类)。
那么,具体来说,我们是如何通过这个代理对象调用到真实的getValue呢?
如何通过代理对象调用远端Service方法
在代理类的add方法中看到,他是调用了mRemote.transact的方法。
而mRemote.transact的方法通过底层的Binder通讯,将数据传输给服务端进程,并调用服务端的onTransact方法:
1 | public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { |
因为当初得到的远程服务对象是MyServiceImpl的对象,因此这里的this就指向了MyServiceImpl类。因此getValue方法就进入到了MyServiceImpl的内部,也就是远程服务端的内部。由此完成了一次完整的调用过程。
AIDL总结
- AIDL要是实现的最终目标是跨进程访问,简单的说就是得到另一个进程的对象,并调用其方法。
- AIDL与接口类似,本质属性都是一个Interface(AIDL文件是IInterface,而Interface是继承自Interface的),而且都只定义了抽象方法,没有具体的实现,需要子类去实现。
- 与接口不同的是:由AIDL生成的stub类本质上是一个Binder!这个类所生成的对象有两种方式可以传递给另外一个进程:
- 一种是通过bindService的方式,绑定一个服务,而在绑定后,服务将会返回给客户端一个Binder的对象,此时可以把继承自stub的Binder传递给客户端。
- 另外一种就是把继承自stub的类提升为系统服务,此时,我们通过ServiceManager去得到当前的系统服务,ServiceManager就会把目标Service的Binder对象传递给客户端。
- 经过上面两种方法得到的Binder对象,就像得到了本地的某个对象一样,可以调用其远程的方法。