在Android系统中,通常一个进程不能访问其它进程的内存。AIDL(Android Interface definition language)允许定义客户端和服务端都同意为了彼此之间的通信使用进程间通信(IPC)的编程接口,其本质是用Binder实现的。
以下为一个简单的AIDL实例
服务端
1.新建AIDL文件
首先用Android Studio 新建一个Android工程,这里命名为com.example.AIDL_Server。在工程目录下,“右键“->”New”->”AIDL File”,这里接口命名为“MyAidl”,每个.aidl文件必须定义一个接口并且只需要接口声明。
这里定义接口方法为Add,返回客户端输入的两个数之和。MyAidl.aidl文件如下:
1 |
|
接着Make一下,自动会生成对应的Java文件,生成的文件名和.aidl文件名匹配,但扩展名为.java,本质为Binder实现。
###2.实现接口
上一步定义好了接口和Add方法,需要进一步实现。新建一个Service,在Service中新建一个内部类MyAidl.Stub,在该类中实现Add接口。
3.对外暴漏接口
在Service中的onBind函数中返回接口,另外还需注意在manifest文件中声明Service接口,代码如下:
1 |
|
客户端
1.复制AIDL文件
当客户端与服务器不在同一个应用程序中时,客户端必须也复制一份AIDL文件到其目录下,并且包的路径和名称不能改动,这里直接将服务端AIDL目录整体复制到客户端main目录下,同样编译后生成对应的Java文件。
2.新建ServiceConnection对象
当一个客户端(例如activity)调用bindService()连接到这个service,客户端的onServiceConnected()回调接收到由service的onBind()返回的mBinder实例。
import远程AIDL包,定义一个远程AIDL对象,新建一个ServiceConnection对象,在其ServiceConnection()函数中将接收到的Binder进行转换。
3.远程调用
调用Add进行加法运算,注意捕获RemoteException异常。代码如下: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
public class MainActivity extends AppCompatActivity {
public MyAidl mRemote = null;
public ServiceConnection sc= new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mRemote = MyAidl.Stub.asInterface(iBinder);
System.out.println("-----Connect---------");
}
public void onServiceDisconnected(ComponentName componentName) {
mRemote=null;
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent("com.example.aidl_server.myapplication.Add");
bindService(intent,sc, Context.BIND_AUTO_CREATE);
Button bt = (Button) findViewById(R.id.button);
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
try {
System.out.println(mRemote.Add(1, 2));
Toast.makeText(MainActivity.this, String.valueOf(mRemote.Add(1, 2)),Toast.LENGTH_SHORT).show();
}
catch (RemoteException e){
e.printStackTrace();
}
}
});
}
}
遇到的坑
- 服务端的Service需要启动,我是在MainActivity 里new Add()才启动服务
- bindService时,Intent名字要对应
- 客户端直接在OnCreate函数里进行远程调用失败,加了个Button在onClick里调用正常