AIDL 入门

225 阅读2分钟

AIDL 的使用

  1. 创建 aidl 接口

WechatIMG14.jpeg

  1. 创建 Person 对象,并实现 Parcelable 接口,Person 类可以放在 adil 目录下也可以放在 java 目录下,放在 aidl 目录下需要修改 buid.gradle 文件,否则找不到 Person 类,修改如下
android {
    ...
    sourceSets{
        main{
            java {
                // 指定 sourceSets
                srcDirs "src/main/java","src/main/aidl"
            }
        }
    }
}
  1. 创建 Person.aidl,可能会出现
// Perso.aidl
package com.lixuanlin.aidldemo;

// 注意 parcelable 是小写

parcelable Person;
  1. 修改 IDemonInterface.aidl
// IDemoInterface.aidl
package com.lixuanlin.aidldemo;
// 需要手动 import
import com.lixuanlin.aidldemo.Person;
// Declare any non-default types here with import statements

interface IDemoInterface {
    void add(in Person person);
    List<Person> get();
}
  1. 手动触发编译后,会生成 IDemoInterface.java 文件,结构如下,后面我讲详解介绍该类
public interface IDemoInterface extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.lixuanlin.aidldemo.IDemoInterface {
        ...

        private static class Proxy implements com.lixuanlin.aidldemo.IDemoInterface {
            ...
        }

        ...
    }

    public void add(com.lixuanlin.aidldemo.Person person) throws android.os.RemoteException;

    public java.util.List<com.lixuanlin.aidldemo.Person> get() throws android.os.RemoteException;
}
  1. 创建 Service,实现 IDemoInterface.Stub 接口
class RemoteService : Service() {
    override fun onBind(p0: Intent?): IBinder? {
        return RemoteBinder()
    }

    inner class RemoteBinder : IDemoInterface.Stub() {
        private val persons = ArrayList<Person>()
        override fun add(person: Person?) {
            person?.run {
                persons.add(this)
            }

        }

        override fun get(): ArrayList<Person> {
            return persons
        }

    }
}
  1. 注册 Service
//指定进程名
<service android:name=".RemoteService" android:process=":remote"/>
  1. 绑定服务,并调用方法
class MainActivity : AppCompatActivity() {

    var demoInterface: IDemoInterface? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent(this, RemoteService::class.java)
        // 绑定服务
        bindService(intent, object : ServiceConnection {
            override fun onServiceDisconnected(p0: ComponentName?) {
                demoInterface = null
            }

            override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
                // 获取接口
                demoInterface = IDemoInterface.Stub.asInterface(p1)
            }

        }, BIND_AUTO_CREATE)
    }

    fun add(view: View) {
        // 方法调用
        val person = Person()
        demoInterface?.add(person)
    }
    fun get(view: View) {
        // 方法调用
        demoInterface?.get()
    }
}

源码分析

/*
 * 客户端调用 transact() 方法后,服务端 onTransact() 方法会得到执行
 */
package com.lixuanlin.aidldemo;

public interface IDemoInterface extends android.os.IInterface {
    /**
     * 代表服务端
     */
    public static abstract class Stub extends android.os.Binder implements com.lixuanlin.aidldemo.IDemoInterface {
        private static final java.lang.String DESCRIPTOR = "com.lixuanlin.aidldemo.IDemoInterface";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.lixuanlin.aidldemo.IDemoInterface interface,
         * generating a proxy if needed.
         */
        public static com.lixuanlin.aidldemo.IDemoInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.lixuanlin.aidldemo.IDemoInterface))) {
                // 未跨进程
                return ((com.lixuanlin.aidldemo.IDemoInterface) iin);
            }
            // 跨进程
            return new com.lixuanlin.aidldemo.IDemoInterface.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 {
            java.lang.String descriptor = DESCRIPTOR;
            // 根据 code 区分不同的方法调用
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(descriptor);
                    com.lixuanlin.aidldemo.Person _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = com.lixuanlin.aidldemo.Person.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    this.add(_arg0);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_get: {
                    data.enforceInterface(descriptor);
                    java.util.List<com.lixuanlin.aidldemo.Person> _result = this.get();
                    reply.writeNoException();
                    reply.writeTypedList(_result);
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        
        /*
         * 代表客户端
         */
        private static class Proxy implements com.lixuanlin.aidldemo.IDemoInterface {
            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 add(com.lixuanlin.aidldemo.Person person) throws android.os.RemoteException {
                // 打包客户端需要传递的数据
                android.os.Parcel _data = android.os.Parcel.obtain();
                // 服务端处理后会通过 _reply 返回数据
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((person != null)) {
                        _data.writeInt(1);
                        person.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    // 跨进程操作,同步情况下会挂起
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

            @Override
            public java.util.List<com.lixuanlin.aidldemo.Person> get() throws android.os.RemoteException {
                // 打包客户端需要传递的数据
                android.os.Parcel _data = android.os.Parcel.obtain();
                // 服务端处理后会通过 _reply 返回数据
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.lixuanlin.aidldemo.Person> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    // 跨进程操作,同步情况下会挂起
                    mRemote.transact(Stub.TRANSACTION_get, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.createTypedArrayList(com.lixuanlin.aidldemo.Person.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_get = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public void add(com.lixuanlin.aidldemo.Person person) throws android.os.RemoteException;

    public java.util.List<com.lixuanlin.aidldemo.Person> get() throws android.os.RemoteException;
}

下篇文章将会介绍 transact 方法是怎么进行跨进程操作