您的位置:首页 > 移动开发 > Android开发

Android开发笔记(五十三)远程接口调用AIDL

2016-01-19 16:32 429 查看

AIDL概述

AIDL全称是“Android Interface Definition Language”,即Android的接口定义语言。AIDL用来协助开发者来处理进程间通信,在之前的博文《Android开发笔记(五十一)通过Messenger实现进程间通信》中,我们知道可以使用Messenger完成进程间通信。但是Messenger每次调用都只能传递一个消息包,不能很好的完成一些复杂的调用,比如说我们想像API调用那样通过不同的方法来实现不同的动作,这时Messenger就难以实现了。所以Android引入了AIDL服务来完成这种RPC调用。

下面是在项目工程中运用AIDL的具体方法和步骤。

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;
}

}


点此查看Android开发笔记的完整目录
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: