为使应用程序之间能够彼此通信,Android提供了IPC (Inter Process Communication,进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android接口定义语言)。

简单来说,AIDL 就是定义一个接口,客户端(调用端)通过 bindService 来与远程服务端建立一个连接,在该连接建立时会将返回一个 IBinder 对象,该对象是服务端 Binder 的 BinderProxy。在建立连接时,客户端通过 asInterface 函数将该 BinderProxy 对象包装成本地的 Proxy,并赋值给Proxy类的mRemote 字段,本地通过 mRemote 即可调用远程方法。

1、创建 .aidl 文件

 首先打开 Android Studio,new 一个 AIDL file。具体代码如下 :

interface IMyAidlInterface {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,            double aDouble, String aString);}

basicTypes 方法事接口自带的,不过可以知道,在 aidl 中只能使用这些基本类型参数:int, long, boolean, float,double , String ;

除了 basicTypes 方法之外,我们也可以添加自己的方法。因此,可以删除 basicTypes 方法,添加自己的方法。

二、生成 .java 文件

添加完方法之后,选中 .aidl 文件,在弹出的菜单中选择 Synchronize LocalAIDLS... Service.java,就会会自动帮你生成对应的 java 代码。

格式化代码之后,如下所示:

/* * This file is auto-generated.  DO NOT MODIFY. * Original file: /Users/shenjiaqi/Documents/sjq/booksource/chapter6/DatabaseTest/app/src/main/aidl/com/example/databasetest/IMyAidlInterface.aidl */package com.example.databasetest;public interface IMyAidlInterface extends android.os.IInterface {    /**     * Local-side IPC implementation stub class.     */    public static abstract class Stub extends android.os.Binder implements com.example.databasetest.IMyAidlInterface {        private static final java.lang.String DESCRIPTOR = "com.example.databasetest.IMyAidlInterface";        /**         * Construct the stub at attach it to the interface.         */        public Stub() {            this.attachInterface(this, DESCRIPTOR);        }        /**         * Cast an IBinder object into an com.example.databasetest.IMyAidlInterface interface,         * generating a proxy if needed.         */        public static com.example.databasetest.IMyAidlInterface asInterface(android.os.IBinder obj) {            if ((obj == null)) {                return null;            }            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);            if (((iin != null) && (iin instanceof com.example.databasetest.IMyAidlInterface))) {                return ((com.example.databasetest.IMyAidlInterface) iin);            }            return new com.example.databasetest.IMyAidlInterface.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_basicTypes: {                    data.enforceInterface(DESCRIPTOR);                    int _arg0;                    _arg0 = data.readInt();                    long _arg1;                    _arg1 = data.readLong();                    boolean _arg2;                    _arg2 = (0 != data.readInt());                    float _arg3;                    _arg3 = data.readFloat();                    double _arg4;                    _arg4 = data.readDouble();                    java.lang.String _arg5;                    _arg5 = data.readString();                    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);                    reply.writeNoException();                    return true;                }            }            return super.onTransact(code, data, reply, flags);        }        private static class Proxy implements com.example.databasetest.IMyAidlInterface {            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;            }            /**             * Demonstrates some basic types that you can use as parameters             * and return values in AIDL.             */            @Override            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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.writeInt(anInt);                    _data.writeLong(aLong);                    _data.writeInt(((aBoolean) ? (1) : (0)));                    _data.writeFloat(aFloat);                    _data.writeDouble(aDouble);                    _data.writeString(aString);                    mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);                    _reply.readException();                } finally {                    _reply.recycle();                    _data.recycle();                }            }        }        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);    }    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;}

如果,你需要修改 .aidl 文件,那么修改之后,选择 build -> make project 即可,会重新生成对应的java文件。

其中的  proxy 是一个静态类,实现了这个 IMyAidlInterface 接口。Stub 继承了 Binder 同时实现了 IMyAidlInterface 接口。

三、传输复杂数据

如果,需要传递复杂数据,那么就需要实现 Parcelable 接口,可序列化:

public class Info implements Parcelable {    private String content;    public String getContent() {        return content;    }    public void setContent(String content) {        this.content = content;    }    public Info() {    }    public Info(Parcel in) {        content = in.readString();    }    public static final Creator CREATOR = new Creator() {        @Override        public Info createFromParcel(Parcel in) {            return new Info(in);        }        @Override        public Info[] newArray(int size) {            return new Info[size];        }    };    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeString(content);    }    /**     * 参数是一个Parcel,用它来存储与传输数据     *     * @param dest     */    public void readFromParcel(Parcel dest) {        //注意,此处的读值顺序应当是和writeToParcel()方法中一致的        content = dest.readString();    }    //方便打印数据    @Override    public String toString() {        return "content : " + content;    }}

与此同时,也要建一个 info.aidl 文件,表明数据也是可以传递的。

package com.viii.aidlclient;//注意:Info.Info.java的包名应当是一样的//这个文件的作用是引入了一个序列化对象 Info 供其他的AIDL文件使用//注意parcelable是小写parcelable Info;

这样就可以使用 info 对象了。 不用在受前面的基本类型变量所控制。

四、建立 service

接下去,新建一个Service负责接收消息,并在AndroidManifest.xml里面注册 Service:

public class MyService extends Service {    private static final String TAG = "MyService";   // private MyBinder mMyBinder = new MyBinder();    @Nullable    @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "onBind: ");
     // 应该返回 mBinder
return null; } @Override public void onCreate() { Log.d(TAG, "onCreate: "); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); }  // 这里就是服务端的实现 private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {      // 具体实现过程 } };}

这时候,可以 basicTypes 方法添加具体函数代码,实现你想要的功能。

当我们在本地获取到代理后之后,调用 basicTypes 就会触发服务端的调用。

5、获取服务

接下去在mainactivity中进行绑定。

public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    private IMyAidlInterface mService;    private boolean mIsBound;    private AdditionServiceConnection mServiceConnection;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        doBindService() ;    }/**     * bind service     */    private void doBindService() {        mServiceConnection = new AdditionServiceConnection();        Intent intent = new Intent(this, MyService.class);        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);    }    /**     * unbind service     */    private void doUnbindService() {        if (mIsBound) {            unbindService(mServiceConnection);            mServiceConnection = null;            mIsBound = false;        }    }    /**     * ServiceConection     */    class AdditionServiceConnection implements ServiceConnection {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {
       // 连接的时候获取本地代理,这样我们就可以调用 service 中的方法了。 mService
= IMyAidlInterface.Stub.asInterface((IBinder) service); mIsBound = true; try { //设置死亡代理 service.linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { e.printStackTrace(); } Log.d(TAG, "onServiceConnected: "); } @Override public void onServiceDisconnected(ComponentName name) { mService = null; mIsBound = false; Log.d(TAG, "onServiceDisconnected: "); } } /** * 监听Binder是否死亡 */ private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override public void binderDied() { if (mService == null) { return; } mService.asBinder().unlinkToDeath(mDeathRecipient, 0); mService = null; //重新绑定 doBindService(); } }; @Override protected void onStop() { super.onStop(); doUnbindService(); }}

将远程服务的 binder 拿到之后,我们就可以调用相关方法实现自己的功能呢。

到这里,一个 AIDL 就被我们实现了。

 

具体实例代码见 :https://download.csdn.net/download/szengjiaqi/10613236

 

更多相关文章

  1. 实现三星S3蒲公英水波纹效果(三)——Activity水波纹实现篇
  2. android 读取资源字符串的 方法
  3. android onTouchEvent和setOnTouchListener中onTouch的区别
  4. android 被强制横屏,Activity重启问题解决方案
  5. Android(安卓)user defined service handling
  6. 浅谈Java中Collections.sort对List排序的两种方法
  7. NPM 和webpack 的基础使用
  8. Python list sort方法的具体使用
  9. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程

随机推荐

  1. Sending and receiving broadcast messag
  2. android 让自己的app成为launcher
  3. Android短信发送和监控
  4. Android的简单的广播的例子
  5. Android 101 for iOS Developers
  6. Android 各种机型兼容问题
  7. Android: Runtime.exec()的陷阱
  8. Android(安卓)开发中的  AsyncTask 的
  9. android中比较两张图片的相似度
  10. Adding prebuilt shared library to Andr