一、AIDL是什么?
AIDL(Android Interface Definition Language)是Android接口定义语言,用于进程间的通信(IPC),它能实现让多个应用程序组件之间与某个Service进行跨进程通信,从而实现多个应用程序共享一个服务的功能。
二、为什么要通过AIDL进行IPC通信?
系统为一个应用分配一个进程,进程运行在自己的内存空间,一个进程不能直接访问另外一个进程,如果要进程间的通信,需要通过AIDL,AIDL是生成Android设备上两个进程之间通讯的代码。
三、Demo例子
我们需要创建两个应用,代表两个进程。
1、服务端写一个IAidl.aidl文件,
package com.txfy.aidl;
interface IAidl{
void testAidl();
}
2、创建远程服务
public class AidlAService extends Service {
private static final String TAG = "AIDLService";
private void Log(String str) {
Log.i(TAG, "----------" + str + "----------");
}
public void onCreate() {
Log("service created");
}
public void onStart(Intent intent, int startId) {
Log("service started id = " + startId);
}
//绑定的时候调用的方法
public IBinder onBind(Intent t) {
Log("service on bind");
//返回该对象到客户端的onServiceConnected
return new MyBinder();
}
public void onDestroy() {
Log("service on destroy");
super.onDestroy();
}
//解绑服务
public boolean onUnbind(Intent intent) {
Log("service on unbind");
return super.onUnbind(intent);
}
public void onRebind(Intent intent) {
Log("service on rebind");
super.onRebind(intent);
}
//创建Binder,返回给客户端的
private class MyBinder extends Stub {
//客户端通过代理对象调用testAidl() ,testAidl()再调用服务里面的方法
@Override
public void testAidl() throws RemoteException {
callMe();
}
}
public void callMe() {
Log("Call service me");
}
}
3、AndroidManifest.xml配置,注意Service要放在应用程序唯一包名的文件夹上
<service android:name="com.example.AliPay.AidlAService" >
<intent-filter>
<action android:name="com.txfy.testAidl" ><!--这个是隐式意图,名字任意起-->
</action>
</intent-filter>
</service>
应用结构如图
4、复制IAidl.aidl文件到客户端,IAidl.aidl所在的包名必须与服务端的包名一致
5、客户端AIDLAActivity.java代码调用远程服务
public class AAIDLActivity extends Activity {
private IAidl mItestAidl;
private Button mAidlCallbackAidl;
private Button mAidlUnbindAidl;
private ServiceConnection mConnection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
//初始化服务
initService();
initView();
setOnclickListener();
}
private void initService() {
Intent service = new Intent();
//隐式调用远程服务
// <service android:name="com.example.AliPay.AidlAService" >
// <intent-filter>
// <action android:name="com.txfy.testAidl" >
// </action>
// </intent-filter>
// </service>
service.setAction("com.txfy.testAidl");
mConnection = new MyServiceConnection();
bindService(service, mConnection, Context.BIND_AUTO_CREATE);
}
private void setOnclickListener() {
mAidlCallbackAidl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
//调用远程服务
mItestAidl.testAidl();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
mAidlUnbindAidl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
unbindService(mConnection);
}
});
}
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// iService = IService.Stub.asInterface(service);
// 返回他的代理类
mItestAidl = IAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
private void initView() {
mAidlCallbackAidl = (Button) findViewById(R.id.id_aidlcallback_btn);
mAidlUnbindAidl = (Button) findViewById(R.id.id_aidlunbind_btn);
}
}
特别注意:如果出现一下错误
**** enforceInterface() expected 'com.txfy.aidl.IAidl' but read 'com.example.AliPay.IAidl'
那就是你没把IAidl.aidl放在服务端的唯一包名下面,客户端默认去服务端的唯一包名下面找