IPC(四)_Aidl的基本使用过程

来源:互联网 发布:知乐小说猎情 编辑:程序博客网 时间:2024/06/03 05:34

AIDL全称 Android Interface definition language的缩写,顾名思义,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口.
下面是AIDL的详细使用过程。
简单起见,就完成一个客户端调用服务端,完成一次两个数加法的运算。
首先新建一个工程Server,然后规范起见,创建一个单独的.aidl的包。右键新建文件,创建一个.aidl的文件。

package com.example.server.aidl;interface IAdd{int  add(int i,int j);}

这个时候在工程根目录下会自动创建一个.java 的文件
这里写图片描述
接着就是写Server端的服务了

package com.example.server;import com.example.server.aidl.IAdd;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class MyService extends Service {    @Override    public IBinder onBind(Intent intent) {        // TODO 自动生成的方法存根        return add;    }    IAdd.Stub  add=new IAdd.Stub() {        @Override        public int add(int i, int j) throws RemoteException {                int sum=i+j;                Log.e("ethan", "sum=="+sum);            return sum;        }    };}

服务内部没有特别的东西,就是实例化一个IAdd的接口对象,然后把该对象转换成IBinder类型的对象(stub方法就是干这事的)。之后通过onBind()方法返回 ,实例化并转化类型过后的对象add。

由于是跨进程启动,所以需要隐式启动服务。因此在Manifest中给服务注册上Action

 <service android:name="com.example.server.MyService">            <intent-filter >                <action android:name="com.example.server.MyService.MyAidl"/>            </intent-filter>        </service>

接下来就是客户端的代码实现了
首先把服务端的Aidl复制到客户端(连包名一起)
这里写图片描述
接着就是写MainActivity里面的代码了

public class MainActivity extends Activity implements OnClickListener {    private Button button1,button2;    private IAdd add;    ServiceConnection conn=new ServiceConnection() {                @Override        public void onServiceDisconnected(ComponentName name) {             }           @Override        public void onServiceConnected(ComponentName name, IBinder service) {            add=IAdd.Stub.asInterface(service);             }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initViews();    }    private void initViews() {        // TODO 自动生成的方法存根        button1=(Button) findViewById(R.id.button1);        button2=(Button) findViewById(R.id.button2);        button1.setOnClickListener(this);        button2.setOnClickListener(this);    }    @Override    public void onClick(View v) {    switch (v.getId()) {    case R.id.button1:        bindService(new Intent("com.example.server.MyService.MyAidl"), conn, BIND_AUTO_CREATE);        break;    case R.id.button2:        try {            add.add(3, 2);        } catch (RemoteException e) {            // TODO 自动生成的 catch 块            e.printStackTrace();        }        break;    }    }

在MainActivity里面,首先注册两个按钮,一个用来绑定Service,一个用来调用远程服务。接着实例化一个ServiceConnection的对象conn,然后在button1的点击事件里,执行bindService,bindServic
e的三个参数分别为隐式地洞Service的intent,ServiceConnection的实例化对象conn,以及flag参数。当执行完该方法后,会回调ServiceConnection里面的public void onServiceConnected(ComponentName name, IBinder service) 提供一个IBinder 的对象service回来,这个service其实是BinderProxy类型,然后调用aidl接口将service转换成IAdd类型的对象add。
于是就可以通过add,调用IAdd接口里面的方法了。
接着点击button2,执行接口IAdd接口里面的add方法。

    case R.id.button2:        try {            add.add(3, 2);        } catch (RemoteException e) {            // TODO 自动生成的 catch 块            e.printStackTrace();        }        break;

接着,控制台顺利打印出Log sum=5。证明调用远程服务成功了。

 E/ethan(2015): sum==5

回看AIDL的使用过程,其实和IPC(一)使用纯Binder进行进程间通信
大体上差不多,AIDL其实就是把Binder中的transact函数封装到了IAdd接口内部。上文拿到的IAdd的接口对象add,实际上是BinderProxy(实现了IBinder接口)的对象转化过来的,也就是把BinderProxy对象封装到了IAdd接口对象内部。当我们调用add.add()方法时候,内部还是调用的BinderProxy中的transact()方法来发送数据的。

下篇IPC(五)——浅谈AIDL的架构原理。

0 0
原创粉丝点击