在Android中每个应用程序都运行在自己的进程空间,不同的进程不能直接访问对方的进程空间,如果要在进程间通信,必须将传递对象解析成操作系统可以理解的基本类型,通过操作系统作为桥梁来传递到对方的进程。
AIDL(Android Interface Definition Language) Android 接口定义语言用于生成两个进程之间进行进程间通信的代码。
AIDL服务端实现
定义AIDL接口
- AIDL接口文件的后缀名为.aidl.保存在src目录下
- AIDL接口文件与一般的接口大体相似,都是以interface作为关键字,每个aidl文件只能定义一个接口,与一般接口不同的是AIDL文件只能定义接口声明和方法声明,不能定义静态常量。
- AIDL文件中方法声明的参数和返回值可以是基本数据类型,String,CharSequence,List,Map,实现了Parcelable接口的类,甚至是其他AIDL生成的接口。其中后两者即使位于同一个包也需要使用import包含进来。实现了Parcelable接口的类除了要建立一个实现android.os.Parcelable接口的类外,还需要为这个类单独建立一个aidl文件,并使用parcelable关键字进行声明。
- 除了基本类型,String,CharSequence这些类型,其他的都需要指明方向,in表示由客户端设置,out表示由服务端设置,inout表示两者均可设置。
- 如果其他应用程序需要进行IPC,则这些应用程序的src也需要有这个aidl文件
- 首先,先创建一个继承Service的服务类 MyAIDLService

- 紧接着选中刚刚创建的MyAIDLService.java文件在右键弹出的菜单中选择File->New->AIDL->AIDL File
这时候就会在main目录下自动创建一个aidl目录,并且在MyAIDLService.java 平行的对应包下创建一个aidl文件。
package com.idealist.testaidl.service;
import com.idealist.testaidl.bean.Person; import com.idealist.testaidl.callback.IResultCallback; interface IMyAidlInterface { void savePersonInfo(in Person person,IResultCallback callback); List<Person> getPersonInfos(); }
|
这里用到了Person这个Bean以及IResultCallback这个回调接口,前者是实现了Parcelable接口的类,后者是其他AIDL生成的接口。具体如下:
com/idealist/testaidl/callback/IResultCallback.aidl
package com.idealist.testaidl.callback;
interface IResultCallback { void reportResult(String result); }
|
com/idealist/testaidl/bean/Person.aidl
package com.idealist.testaidl.bean parcelable Person
|
下面是Person的实现类:
com.idealist.testaidl.bean.Person
package com.idealist.testaidl.bean; import android.os.Parcel; import android.os.Parcelable;
public class Person implements Parcelable {
public Person() {} protected Person(Parcel in) { name = in.readString(); tel = in.readString(); }
public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel in) { return new Person(in); }
@Override public Person[] newArray(int size) { return new Person[size]; } };
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTel() { return tel; }
public void setTel(String tel) { this.tel = tel; }
private String name = null; private String tel = null;
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(name); parcel.writeString(tel); } }
|
点击build后就可以编译,编译结束后就可以产生如下的Stub文件了:

- 实现MyAIDLService类:
这里实现的功能很简单就是在客户端绑定并调用Serive的savePersonInfo方法的时候,将会存储起来,如果客户端调用getPersonInfos将会返回存储信息的列表。
package com.idealist.testaidl.service;
import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.support.annotation.Nullable; import android.util.Log;
import com.idealist.testaidl.bean.Person; import com.idealist.testaidl.callback.IResultCallback;
import java.util.ArrayList; import java.util.List;
public class MyAIDLService extends Service { private List<Person> mPersonInfoList = new ArrayList<Person>();
private IMyAidlInterface.Stub mIBinder = new IMyAidlInterface.Stub() { @Override public void savePersonInfo(Person person, IResultCallback callback) throws RemoteException { if(mPersonInfoList != null && person != null) { mPersonInfoList.add(person); Log.i("xiaohai.lin", "Name = " + person.getName() + " -- " + "Tel " + person.getTel() + " Has add to list"); } if(callback != null) { callback.reportResult("Person info had add Sucessfully !"); } }
@Override public List<Person> getPersonInfos() throws RemoteException { return mPersonInfoList; } };
@Nullable @Override public IBinder onBind(Intent intent) { return mIBinder; }
public boolean onUnbind(Intent intent) { Log.i("xiaohai.lin", "客户端解除绑定"); return super.onUnbind(intent); } }
|
- 最后一定要注意在AndroidManifest.xml文件中作如下声明:
<service android:name=".service.MyAIDLService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MyAIDLService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
|
整个服务端源码结构如下:

AIDL客户端实现
创建一个新的Android项目工程,将服务器端的AIDL相关的文件连同包复制到客户端项目,项目结构如下图所示:

package com.ideallist.testaidlclient;
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.view.View; import android.widget.Button; import android.widget.Toast;
import com.idealist.testaidl.bean.Person; import com.idealist.testaidl.callback.IResultCallback; import com.idealist.testaidl.service.IMyAidlInterface;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private IMyAidlInterface mInterface = null; private Button mBindServiceBtn = null; private Button mUnbindServceBtn = null; private Button mSetPersonInfoBtn = null; private Button mGetPersonInfoBtn = null; private boolean isBind = false; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mInterface = IMyAidlInterface.Stub.asInterface(iBinder); isBind = true; Toast.makeText(MainActivity.this, "Binded to Server !",Toast.LENGTH_LONG).show(); }
@Override public void onServiceDisconnected(ComponentName componentName) { if(mInterface != null) { mInterface = null; } Toast.makeText(MainActivity.this, "Ubind to Server !",Toast.LENGTH_LONG).show(); isBind = false; } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBindServiceBtn = (Button) findViewById(R.id.bindservice); mUnbindServceBtn = (Button) findViewById(R.id.unbindservice); mSetPersonInfoBtn = (Button) findViewById(R.id.setpersonInfo); mGetPersonInfoBtn = (Button) findViewById(R.id.getpersonInfo);
mBindServiceBtn.setOnClickListener(this); mUnbindServceBtn.setOnClickListener(this); mSetPersonInfoBtn.setOnClickListener(this); mGetPersonInfoBtn.setOnClickListener(this); }
private IResultCallback.Stub mResultCallBack = new IResultCallback.Stub() { @Override public void reportResult(String result) throws RemoteException { Toast.makeText(MainActivity.this, "Result = " + result,Toast.LENGTH_LONG).show(); } };
@Override public void onClick(View view) { int id = view.getId(); switch (id) { case R.id.bindservice: if(!isBind) { Intent intent = new Intent("android.intent.action.MyAIDLService"); intent.setPackage("com.idealist.testaidl"); bindService(intent, conn, BIND_AUTO_CREATE); } break; case R.id.unbindservice: if(isBind) { unbindService(conn); } break; case R.id.setpersonInfo: if(mInterface != null ) { Person person = new Person(); person.setName("Jimmy"); person.setTel("1111111111"); try { mInterface.savePersonInfo(person,mResultCallBack); } catch (RemoteException e) { e.printStackTrace(); } } break; case R.id.getpersonInfo: if(mInterface != null ) { try { List<Person> mList = mInterface.getPersonInfos(); for (Person p : mList) { Toast.makeText(MainActivity.this,"Name = " + p.getName()+" : "+ " Tel "+ p.getTel(),Toast.LENGTH_LONG).show(); } } catch (RemoteException e) { e.printStackTrace(); } } break;
} } }
|
写客户端最需要注意的就是每个类和Service中的对应关系。一旦对应错误就有可能访问不到对应的方法。