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开发笔记的完整目录
相关文章推荐
- Android自由行之走进zxing,轻松实现二维码扫描
- android Intent启动flag含义
- Android Studio插件开发实战(3)-FindViewByMe插件分析
- Android绘制时钟
- 关于Android Canvas.drawText方法中的坐标参数的正确解释
- Android确定分区布局
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android SharedPreferences的简单使用
- Android的文件操作
- Android Fragment 你应该知道的一切
- Android手机内置SD卡路径的获取
- Android 5.0新增任务调度作业jobScheduler
- Android studio 史上最简单添加so库
- Android图片加载神器之Fresco-加载图片基础[详细图解Fresco的使用]
- Android-MediaRecord介绍
- Android拨号程序的编写
- Android——点击复制TextView中部分特殊样式字体
- 关于android native层的Ixxx 接口中Binder机制的探讨
- Android开发之控制相机
- Android开发出现ScrollView can host only one direct child