设为首页 加入收藏

TOP

从AIDL开始谈Android进程间Binder通信机制(一)
2015-08-31 21:23:17 来源: 作者: 【 】 浏览:88
Tags:AIDL 开始 Android 进程 Binder 通信 机制

概述


我们知道,在Android app中的众多activity,service等组件可以运行在同一进程中,也可以运行在不同进程中。当组件运行在同一进程中进行通信就显得比较简单,在之前的Android线程间通信机制中已经讲过了;而当它们运行在不同的进程中时,就需要使用我们本文中所要介绍的Binder机制了。


Binder作为一种进程间通信机制,负责提供远程调用的功能(RPC),它的系统组件主要包括四种:Client, Server, ServiceManager, Binder Driver. 它们之间的关系如下图所示:



从图中我们可以看出,Client, Server, ServiceManager运行在系统的用户态,而Binder Driver运行在内核态。为了完成Client端到Server端的通信任务,用户空间的需要操作Binder Driver提供的/dev/binder文件来完成交互。那么ServiceManager的工作是什么呢?ServiceManager负责管理Server并向Client端提供一个Server的代理接口(proxy)。通过代理接口中定义的方法,Client端就可以使用Server端提供的服务了。整个过程如下:


Client端调用代理接口的方法,将Client的参数打包为parcel对象发送给内核空间中BinderDriver;


Server端读取到BinderDriver中的请求数据,将parcel对象解包并处理;


处理好后,将处理结果打包返回给BinderDriver,再交给Client端。


另外,Client端与Server端的调用过程是同步的,即在Server返回结果之前,Client端是阻塞的。调用过程如下所示:



OK,下面我们通过AIDL的一个例子来分析一下以上过程时如何进行的。


AIDL小栗子


首先,创建一个aidl文件“ICalculateAIDL.aidl”,这个接口里面定义了要对外提供的服务,我们这里定义了计算加法和减法的函数:


创建好后,rebuild一下我们的项目,可以生成同名的java文件。这是一个接口,里面包含了一个名为Stub的静态抽象类,以及我们在aidl文件中定义的加减法函数。里面详细代码在后面分析,接口文件结构如下:



然后我们需要实现服务端方面的功能,创建一个service,我们顺手把生命周期中各方法都打印出来,并完成加法和减法函数的实现:


public class CalculateService extends Service {
? ?
private static final String TAG="SERVER";
? ?
public CalculateService() {
? ? }

? ? @Override
? ?
public void onCreate() {
? ? ? ?
super.onCreate();
? ? ? ? Log.e(TAG,
"OnCreate");
? ? }

? ? @Override
? ?
public int onStartCommand(Intent intent, int flags, int startId) {
? ? ? ? Log.e(TAG,
"onStartCommand");
? ? ? ?
return super.onStartCommand(intent, flags, startId);
? ? }

? ? @Override
? ?
public IBinder onBind(Intent intent) {
? ? ? ? Log.e(TAG,
"onBind");
? ? ? ?
return mBinder;
? ? }


? ? @Override
? ?
public void onDestroy() {
? ? ? ?
super.onDestroy();
? ? ? ? Log.e(TAG,
"onDestroy");
? ? }

? ? @Override
? ?
public boolean onUnbind(Intent intent) {
? ? ? ? Log.e(TAG,
"onUnbind");
? ? ? ?
return super.onUnbind(intent);
? ? }

? ? @Override
? ?
public void onRebind(Intent intent) {
? ? ? ? Log.e(TAG,
"onRebind");
? ? ? ?
super.onRebind(intent);
? ? }

? ?
private final ICalculateAIDL.Stub mBinder=new ICalculateAIDL.Stub(){
? ? ? ? @Override
? ? ? ?
public int add(int a, int b) throws RemoteException {
? ? ? ? ? ?
return a+b;
? ? ? ? }

? ? ? ? @Override
? ? ? ?
public int minus(int a, int b) throws RemoteException {
? ? ? ? ? ?
return a-b;
? ? ? ? }
? ? };
}


在service中,我们使用刚刚生成的ICalculateAIDL.Stub静态抽象类创建了一个Binder对象,实现了其中有关计算的业务方法,并在onBind方法中返回它。另外我们还需要在manifest文件中对该服务进行注册:


? ? ? ? ? ? android:name=".CalculateService"
? ? ? ? ? ? android:enabled="true"
? ? ? ? ? ? android:exported="true" >
? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ?

? ? ? ?


这时候,我们的服务端工作就完成了。我们开始编写客户端的代码来调用这个服务。首先,我们定义一个activity,包含四个按钮:



然后我们可以在activity中启动之前定义好的service并调用它所提供的服务:


public class MainActivity extends Activity implements View.OnClickListener {

? ? Button mBind;
? ? Button mUnbind;
? ? Button mAdd;
? ? Button mMinus;
? ? TextView txt_res;
? ?
private static final String TAG="CLIENT";
? ?
private ICalculateAIDL mCalculateAIDL;
? ?
private boolean binded=false;
? ? @Override
? ?
protected void onCreate(Bundle savedInstanceState) {
? ? ? ?
super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? mBind
= (Button) findViewById(R.id.btn_bind);
? ? ? ? mUnbind
= (Button) findViewById(R.id.btn_unbind);
? ? ? ? mAdd
= (Button) findViewById(R.id.btn_add);
? ? ? ? mMinus
= (Button) findViewById(R.id.btn_minus);
? ? ? ? txt_res
= (TextView) findViewById(R.id.txt_res);

? ? ? ? mBind.setOnClickListener(
this);
? ?

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇使用Visual Studio 2015开发Andro.. 下一篇Android线程间异步通信机制源码分..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: