AIDL全称是“Android Interface Definition Language”,即Android的接口定义语言。AIDL用来协助开发者来处理进程间通信,在之前的博文《Android开发笔记(五十一)通过Messenger实现进程间通信》中,我们知道可以使用Messenger完成进程间通信。但是Messenger每次调用都只能传递一个消息包,不能很好的完成一些复杂的调用,比如说我们想像API调用那样通过不同的方法来实现不同的动作,这时Messenger就难以实现了。所以Android引入了AIDL服务来完成这种RPC调用。 下面是在项目工程中运用AIDL的具体方法和步骤。
通过菜单“File”——“New”创建扩展名为aidl的文件,文件内容与interface接口格式类似(区别在于要在输入参数前面加上in关键字)。文件定义完成并且没有错误,则ADT会自动在gen目录下生成该aidl文件对应的java文件。下面是一个AIDL接口定义文件的例子:
interface IUserService {
double multiply(in double a1, in double a2);
}
如果想在aidl方法中使用自定义数据结构,则需加上如下步骤: 1、把自定义数据结构的代码(如User.java)挪到aidl包下面,这个数据结构必须实现Parcelable接口; 2、在aidl包下新建一个User.aidl文件,文件内容为“parcelable User;”;很简单,告诉aidl,我这里有个叫做User的parcelable对象; 3、在aidl接口定义中添加新的方法,并使用import导入User的完整路径。即使User.java就在aidl目录下,那也得import,不然ADT不认这个对象;下面是补充后的文件定义例子:
import com.example.exmprocess.aidl.data.User;
interface IUserService {
double multiply(in double a1, in double a2);
int save(in List<User> userList);
}
1、定义一个ServiceConnection对象,在onServiceConnected方法中获取对方服务的实例。代码例子如下:
private IUserService mService;
private ServiceConnection mAidlConn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
mService = IUserService.Stub.asInterface(binder);
}
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
2、远程服务当然只能通过bindService方法启动,不能通过startService方法启动。同时Intent对象也只能通过setAction来指定对方服务的动作,而不能直接指定对方服务的class; 3、绑定服务后,再调用aidl服务端,即可使用mService来调用相应的方法;
重写的Binder类要改为继承自Stub(原来继承自Binder),即ADT根据aidl文件定义自动生成的Stub类,查看自动生成的java源码,其实Stub类就是从Binder类派生出来的。 另外,服务端的Binder类需要实现aidl中定义的方法。
1、intent-filter节点中的“android:name”必须填入原始名称,不可用“@string/aaa”这种定义来代替。 2、Android5.0之后不能再隐式启动Service,只能显式启动Service,所以需要判断当前SDK版本从而做分支处理。 3、aidl定义文件需要同时加入到客户端项目代码与服务端项目代码中,并且aidl文件所在的包路径也要保持一致。
下面是AIDL服务调用的效果图:
下面是AIDL客户端的示例代码:
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.exmprocess.R;
import com.example.exmprocess.aidl.data.IUserService;
import com.example.exmprocess.aidl.data.User;
import com.example.exmprocess.util.IntentUtil;
public class AidlActivity extends Activity implements OnClickListener {
private static final String TAG = "AidlActivity";
private String AIDL_SERVICE = "com.example.exmprocess.aidl.action.AIDL_ADD";
private TextView tv_aidl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aidl);
tv_aidl = (TextView) findViewById(R.id.tv_aidl);
Button btn_aidl_bind = (Button) findViewById(R.id.btn_aidl_bind);
Button btn_aidl_unbind = (Button) findViewById(R.id.btn_aidl_unbind);
Button btn_aidl_send = (Button) findViewById(R.id.btn_aidl_send);
btn_aidl_bind.setOnClickListener(this);
btn_aidl_unbind.setOnClickListener(this);
btn_aidl_send.setOnClickListener(this);
}
private IUserService mService;
private ServiceConnection mAidlConn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder binder) {
mService = IUserService.Stub.asInterface(binder);
}
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_aidl_bind) {
Intent intent = new Intent();
intent.setAction(AIDL_SERVICE);
Intent newIntent = intent;
//Android5.0之后不能再隐式启动Service,只能显式启动Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
newIntent = new Intent(IntentUtil.getExplicitIntent(this, intent));
}
boolean bBind = bindService(newIntent, mAidlConn, Context.BIND_AUTO_CREATE);
Toast.makeText(this, "绑定结果为"+bBind, Toast.LENGTH_LONG).show();
} else if (v.getId() == R.id.btn_aidl_unbind) {
unbindService(mAidlConn);
mService = null;
} else if (v.getId() == R.id.btn_aidl_send) {
if (mService == null) {
Toast.makeText(this, "未绑定AIDL服务", Toast.LENGTH_LONG).show();
} else {
try {
double a1 = 123;
double a2 = 9;
double result = mService.multiply(a1, a2);
List<User> userList = new ArrayList<User>();
userList.add(new User(1, "张三", "111111"));
userList.add(new User(2, "李四", "999999"));
userList.add(new User(3, "王五", "123456"));
int count = mService.save(userList);
String desc = String.format("%f*%f计算结果是%f\n本次保存了%d条记录",
a1, a2, result, count);
tv_aidl.setText(desc);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
下面是AIDL服务端的示例代码:
import java.util.List;
import com.example.exmprocess.aidl.data.IUserService.Stub;
import com.example.exmprocess.aidl.data.User;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class AidlService extends Service {
private static final String TAG = "AidlService";
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Stub {
@Override
public double multiply(double a1, double a2) throws RemoteException {
return a1*a2;
}
@Override
public int save(List<User> userList) throws RemoteException {
//此处省略保存操作
return userList.size();
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mBinder;
}
}