前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(五十三)远程接口调用AIDL

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

作者头像
aqi00
发布2019-01-18 11:09:30
7330
发布2019-01-18 11:09:30
举报
文章被收录于专栏:老欧说安卓老欧说安卓

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接口定义文件的例子:

代码语言:javascript
复制
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不认这个对象;下面是补充后的文件定义例子:

代码语言:javascript
复制
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方法中获取对方服务的实例。代码例子如下:

代码语言:javascript
复制
	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客户端的示例代码:

代码语言:javascript
复制
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服务端的示例代码:

代码语言:javascript
复制
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开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年01月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AIDL概述
  • AIDL定义修改
    • 普通方法
      • 方法中传递了自定义数据结构
      • 项目代码修改
        • 客户端代码修改
          • 服务端代码修改
            • 需要注意的地方
            • 使用示例
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档