Android中通过Binder机制实现跨进程通信,Binder机制比较典型的例子就是AIDL Service。AIDL跨进程通信的实现在Android中是比较重要的知识点,同时也有一定的难度。本文通过一个具体简单的栗子来讲述如何实现跨进程通信。 Android跨进程通信,由四大部分组成,分别是Client、Server、Service Manager和Binder驱动程序。其中Service Manager和Binder驱动程序系统已经为我们实现好,用户只需要按照规范实现Client和Server就可以了。 Client和Server在进程间通讯时分别做哪些事情? Client:调用Server提供的接口函数,传递参数给Server,接收Server返回的结果。 Server:对接收到的Client的参数进行处理,为Client实现接口函数。 下面我们来举一个例子: 该例子中我们一共编写两个应用程序,一个是Client端,一个是Server端。这两个应用程序实现一个加法运算,在Client端传递两个数给Server端,Server端对这两个数进行相加,并将结果返回给Client端。 Client界面如下图,在EditText中输入加数,点击求和按钮,将数据传递到Server端,并获取Server端计算的结果后显示在求和按钮的下方。
Server端界面如下:
Server端实现了计算Client端传递参数的接口,以及Client端获取计算结果的接口。同时,Server端也将结果显示到界面上,这样就可以直观地看到两个应用程序有相互影响,而不是说Client端自己计算了结果。 代码实现步骤如下: 1.编写.aidl文件CalcMethods.aidl: 这里设计了以下两个接口函数: addFunc:传递两个参数给Server端; addGetResult:获取Server端计算结果。
// CalcMethods.aidl package com.gucheng.calcclient; // Declare any non-default types here with import statements interface CalcMethods { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ long addFunc(long addOne, long addTwo); long addGetResult(); }该文件在两个应用程序中都要包含。编写了该文件后编译就会生成对应的.java文件。
2.新建一个服务类AIDLService.java,实现aidl文件中定义的接口。 主要实现如下:
private static CalcMethods.Stub mCalcMethod = new CalcMethods.Stub() { @Override public long addFunc(long addOne, long addTwo) throws RemoteException { result = addOne + addTwo; Log.d(TAG, "addFunc result is " + result); CalcServerActivity.mResult = result; return result; } @Override public long addGetResult() throws RemoteException { return result; } };3.在Server端的AndroidManifest.xml文件中注册该AIDLService。
<service android:name=".service.AIDLService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.gucheng.aidl"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>4.编写Client端的代码: 实例化ServiceConnection对象mServiceConnection。该对象在调用bindService绑定服务的时候会用到。链接成功返回一个类型为CalcMethods的对象mCalcMethods,该类型就是我们定义的AIDL类。通过该变量我们可以访问在Server端实现的方法。
private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "service Connected"); mBound = true; mCalcMethods = CalcMethods.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } };这里我们在点击了求和按钮的响应事件里调用Server端实现的方法 。点击了求和按钮后,获取EditText中的数值,调用addFunc函数来传递参数给Server端,调用addGetResult获取计算结果,并将结果显示到TextView中。
calcStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String one = addOne.getText().toString(); numOne = Long.valueOf(one); String Two = addTwo.getText().toString(); numTwo = Long.valueOf(Two); try { Log.d(TAG, "mCalcMethods.addFunc"); mCalcMethods.addFunc(numOne, numTwo); numResult = mCalcMethods.addGetResult(); resultView.setText("GetResult is " + numResult); } catch (RemoteException e) { Log.d(TAG, "mCalcMethods.addFunc exception"); e.printStackTrace(); } } });完整代码已经上传到github: Server端:https://github.com/gucheng3116/CalcServer Client端:https://github.com/gucheng3116/CalcClient
有问题可以给我留言,或者发送邮件到459843397@qq.com