AIDL实现应用进程间的通信。

来源:互联网 发布:装修软件手机版 编辑:程序博客网 时间:2024/05/22 01:58

AIDL是android中进程间通讯的一种实现方式。AIDL(Android Interface Definition Language)是一种接口定义语言,编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。

这种方式很像Service通过接口实现参数传递以及与Activity之间进行交互的实现方式。

直接上DEMO:

1、建立服务端工程。就是一个aidl接口和一个Service类。aidl接口中有一个接口方法。

aidl接口的创建是在工程目录下new一个Text File 并加上 .aidl后缀名完成的,这里需要注意的是aidl文件名需要与定义的接口名保持一致。


建好aidl接口后,可以看到gen目录下自动为我们生成了IName.java类,里面代码如下如下。

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: D:\\android\\2015_11\\aidl_service\\src\\com\\aidl_service\\IName.aidl */package com.aidl_service;public interface IName extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.aidl_service.IName{private static final java.lang.String DESCRIPTOR = "com.aidl_service.IName";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.aidl_service.IName interface, * generating a proxy if needed. */public static com.aidl_service.IName asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.aidl_service.IName))) {return ((com.aidl_service.IName)iin);}return new com.aidl_service.IName.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_showName:{data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();this.showName(_arg0);reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.aidl_service.IName{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public void showName(java.lang.String name) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeString(name);mRemote.transact(Stub.TRANSACTION_showName, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_showName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public void showName(java.lang.String name) throws android.os.RemoteException;}
不用看懂,只需要知道IName接口中的抽象内部类Stub继承android.os.Binder类并实现IPerson接口,比较重要的方法是asInterface(IBinder)方法,该方法会将IBinder类型的对象转换成IName类型,必要的时候生成一个代理对象返回结果。

接下来就是service了:

public class AIDLService extends Service {private Handler mHandler = new Handler();public  IName.Stub stubBinder = new IName.Stub() {@Overridepublic void showName(String name) throws RemoteException {mHandler.post(new Runnable() {@Overridepublic void run() {Toast.makeText(AIDLService.this, "aidl中的接口方法", Toast.LENGTH_SHORT).show();}});}};@Overridepublic IBinder onBind(Intent intent) {return stubBinder;}}
里面就是实现接口方法,让后在OnBind方法中返回该接口对象。最后需要到AndroidManifest.xml中做一些配置工作

 <service android:name="com.aidl_service.AIDLService">           <intent-filter>               <action android:name="com.aidl_service.AIDLService"/>           </intent-filter>       </service>
这样就完成了。

接下来我们看看客户端,客服端需要做什么呢?就是将接口暴露出来,直接调用接口方法达到数据的共享。


第一步直接将aidl文件连包名一起复制到客服端路径下。不需要服务,所以这里已将同包下的服务类删掉了。拷贝过来后也会自动在gen目录下生成一个IName.java类,该类的内容与在服务端生成该类的内容一样。

最后看看MainActivity里做了什么?

public class MainActivity extends Activity {private Button mBtn;private IName INameBinder;private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {if(INameBinder != null)INameBinder = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {INameBinder = IName.Stub.asInterface(service);   //转化为对应aidl接口对象}};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mBtn = (Button) findViewById(R.id.aidl_btn);        Intent intent = new Intent("com.aidl_service.AIDLService");        bindService(intent, conn, BIND_AUTO_CREATE);        mBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {try {INameBinder.showName("123");} catch (RemoteException e) {e.printStackTrace();}}});    }        @Override    protected void onDestroy() {    super.onDestroy();    if(conn != null){    unbindService(conn);    }    }}
里面就是启动服务,并在ServiceConnection里面得到了aidl接口的实列,也就是IBinder的实列。
@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {INameBinder = IName.Stub.asInterface(service);   //转化为对应aidl接口对象}
通过该实列来实现对服务端里进程间的通信。

在测试运行的时候先启动服务端。在启动客户端MainActivity点击按钮调用接口方法弹出对话框。

最后上效果图:



注意在定义aidl文件时,接口方法中的参数和返回值若是int ,string等基本数据类型是不需要import导入的。若是实现其他的接口或者是自定义序列号对象类型则需要import导入。




0 1