手记

Android AIDL 实例

 为使应用程序之间能够彼此通信,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文件。

三、传输复杂数据

如果,需要传递复杂数据,那么就需要实现 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<Info> CREATOR = new Creator<Info>() {
        @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: ");        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 方法添加具体函数代码,实现你想要的功能。

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) {
            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

 原文出处:https://www.cnblogs.com/huansky/p/9465698.html


0人推荐
随时随地看视频
慕课网APP