Android系统中每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而AIDL就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行。
AIDL(Android接口定义语言): AIDL是在Android中实现进程间通信的一种机制,其本质是一种语言,AIDL的优势在于速度快(系统底层直接是共享内存),性能稳,效率高,一般进程间通信就用它。
AIDL其实是对Binder机制的封装,通过Binder来实现进程间的通信。所以两个通信的进程中有一个是客户端(Client),一个是服务器端(Service)。
例子:使用AIDL实现在客户端调用服务端的getString()方法获取字符串
一:服务器端
1.在Android Studio中新建一个Service项目。
2.创建一个AIDL接口:
(1)在app\src\main目录下右击创建一个AIDL文件,取名为“MyAidlService”:
(2)创建完毕后Service项目中MyAidlService.aidl文件的文件路径默认为:com.example.service(下图红圈内),MyAidlService.aidl文件代码如下:
MyAidlService.aidl文件中有一个接口,接口内有一个getString()方法。
3.定义好AIDL接口后需要编写Service端的代码:
新建一个MyService类继承自Service类,代码如下:
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class MyService extends Service {
class Mybind extends MyAidlService.Stub{
@Override
public String getString() throws RemoteException{
String string = "我是从服务器返回的";
return string;
}
}
Mybind mybind = new Mybind();
@Override
public IBinder onBind(Intent intent) {
return mybind;
}
}
在MyService类中定义了一个内部类Mybind继承自MyAidlService.Stub类(MyAidlService.Stub类继承自Binder类),在Mybind类中重写了getString()方法,此处即是getString()方法的逻辑实现处。接着创建了Mybind类的一个实例对象mybind,并在onBind()方法中将该对象return。
到此Service端的代码基本结束,只剩下AndroidManifest.xml还需要配置一下,这部分内容放在下面讲。
二:客户端
1.在Android Studio中新建一个Client项目。
2.同样需要创建一个AIDL接口,步骤同服务器端,需要注意的是,Service和Client端的MyAidlService.aidl文件名、文件内容、文件路径要相同,由于Service项目内MyAidlService.aidl文件的默认路径为com.example.service,Client项目内MyAidlService.aidl文件的默认路径为com.example.client,所以这里将Client项目内的文件路径修改为com.example.service。
3.定义好AIDL接口后需要编写Client端的代码:
(1)在Client端的页面创建两个按钮和一个文本框,分别用来绑定服务、解绑服务、显示获取到的字符串。
(2)在MainActivity中的代码如下:
package com.example.client;
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.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.service.MyAidlService;
public class MainActivity extends AppCompatActivity {
private Button bindService,unbindService;
private TextView text;
private MyAidlService myAidlService;
private ServiceConnection connection = new ServiceConnection() {//创建服务连接对象
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//当成功绑定服务时回调该方法
myAidlService = MyAidlService.Stub.asInterface(service);//向下转型得到服务器端Mybind类的实例
try{
String str = myAidlService.getString();//调用实例的getString方法
text.setText(str);//将获取到的字符串显示到屏幕
}catch (RemoteException e){
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {//解除服务绑定时回调该方法
myAidlService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService = (Button) findViewById(R.id.bind);
unbindService = (Button) findViewById(R.id.unbind);
text = (TextView) findViewById(R.id.text);
bindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();//构建一个意图
intent.setAction("com.example.service.MyService");
intent.setPackage("com.example.service");
bindService(intent,connection,BIND_AUTO_CREATE);//绑定服务,绑定成功时
//服务器端的onBind()方法return的Mybind实例就会作为参数传递给connection实例
}
});
unbindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
unbindService(connection);//解除服务绑定
}
});
}
}
客户端的代码到此结束,剩下的就是在Service项目中修改AndroidManifest.xml文件,给MyService设置过滤器,代码如下:
所有的代码都写完了,接下来在模拟器上安装Service端和Client端,首先安装Service端,启动后回到手机主界面,再安装Client端,启动后点击BIND按钮,在下面的文本框就会弹出服务器端的字符串:"我是从服务器端返回的"。至此实现了Service端和Client端的通信。 效果如下:
总结:AIDL机制实现进程间通信是基于Binder机制的,AIDL其实是对Binder机制的封装。所以AIDL的实现过程和活动绑定服务的方式很相像,因为活动绑定服务也是通过Binder实现的。两者的区别在于活动绑定服务时Service类中新建了一个继承自Binder类内部类,而在AIDL实现进程间通信里的Service类新建了一个继承自MyAidlService.Stub类的内部类,MyAidlService.Stub类其实也是继承自Binder类的,只不过该类里面多了MyAidlService.aidl文件内定义的getString()方法。