使用AIDL完成一次简单的Android进程间通信

来源:互联网 发布:excel相同数据排序 编辑:程序博客网 时间:2024/06/04 18:50

AIDL(Android Interface Definition Language):安卓接口描述语言。通常我们使用它来帮助我们完成进程间的通信。程序中的数据交换和通信其实都是内存之间的调用来完成的,但是不同的进程之间是不能访问相互之间的内存的,AIDL通过binder机制实现一条管道,客户端和服务端都去实现它,然后利用这个管道相互通信。类似于线程之间共享进程的内存来实现通信,进程则是通过将数据拆分成系统可识别的单元从而进行通信。

一.实现Service的服务端暴露接口进行通信。

要实现进程间的通信,首先作为服务端的应用进程要实现和客户端一样的接口并启动起来,等待客户端的接入。首先是AIDL文件的编写,这两个文件在各自的程序中,放置的包名要一样,程序的应用包名不能一样,否则会冲突,但是AIDL文件的包名要一样。

package com.example.aidlclient;interface TestPrint{    void print();}

以上就是整个AIDL文件的代码,一个包的声明和一个接口的定义,注意这个接口是不能添加public和private这些权限修饰词的。这个AIDL文件的名字是TestPrint.aidl,保存之后将在gen文件夹中对应的目录下自动生成java类。接下来就是Service类的编写,提供接口方法的。

public class MyService extends Service {    @Override    public void onCreate() {        super.onCreate();        Log.i("com.example.androidserver", "service create success") ;    }    @Override    public IBinder onBind(Intent arg0) {        return new MyBinder();    }    class MyBinder extends TestPrint.Stub {        @Override        public void print() throws RemoteException {            Log.i("com.example.androidserver", "return mybinder") ;        }    }}

这个Service中最重要的就是onBind方法的返回了,客户端连接服务之后拿到这个binder对象进行其他操作,可以看到这个binder对象是继承自TestPrint.Stub类的,这个是AIDL文件自动生成的一个类,这个继承了binder接口,实现了TestPrint里面的接口,所以这个对象可以做onBind方法的返回值,又可以在客户端调用这个已经实现了TestPrint里面接口的方法。接下来就是客户端连接服务端了。

二.客户端:

在客户端里面可以创建一个跟服务端一样的包,并且把服务端里面的AIDL文件拷到客户端里面,客户端也将自动生成一份java类文件,在gen目录下,这时候我们只要启动服务端进程,客户端开启服务连接服务端的service:

class MyServiceConnection implements ServiceConnection {        public void onServiceConnected(ComponentName name, IBinder binder) {            tp = TestPrint.Stub.asInterface(binder);        }        public void onServiceDisconnected(ComponentName name) {        }    }

以上是service连接的内部类,里面调用了TestPrint.Stub.asInterface(binder)方法将连接服务端之后返回的binder对象转化成一个TestPrint对象,我们连接服务端service成功之后就会调用这个方法,拿到这个对象。

        msc = new MyServiceConnection();        intent = new Intent();        intent.setComponent(new ComponentName("com.example.androidserver",                "com.example.androidserver.MyService"));        bindService(intent, msc, Context.BIND_AUTO_CREATE);

通过以上代码之后,我们定义的全局变量tp就被赋值了,就可以调用服务端的方法了。

        case R.id.print:            if (tp != null) {                try {                    tp.print();                } catch (RemoteException e) {                    e.printStackTrace();                }            }            break;

点击按钮之后就可以调用服务端实现的TestPrint接口方法进行字符串的打印了。

0 0
原创粉丝点击