zoukankan      html  css  js  c++  java
  • 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文件。

    其中的  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<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: ");
         // 应该返回 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

  • 相关阅读:
    appcan双击返回退出系统
    实现两个矩阵相乘的C语言程序
    编写简单的windows桌面计算器程序
    使用C++实现图形的旋转、缩放、平移
    使用MFC创建C++程序
    SQL server2017的操作(练习题)
    使用SQL语句在SQL server2017上创建数据库
    使用交互式方式在SQL server2017上创建数据库
    解决VS2017编译后的EXE文件不能在其他电脑上运行的问题
    傅里叶分析之掐死教程(完整版)更新于2014.06.06----转载
  • 原文地址:https://www.cnblogs.com/huansky/p/9465698.html
Copyright © 2011-2022 走看看