美文网首页我爱编程
Binder浅析——AIDL的使用

Binder浅析——AIDL的使用

作者: Jesse_zhao | 来源:发表于2018-04-14 16:45 被阅读50次

    Binder浅析——AIDL的使用

    前言

    我们知道Android的进程之间是相互隔离的,内存独立,互相之间是不能直接进行通信的。但是内核空间里的数据是所有进行共享的,那么Binder机制就是通过将进程数据拷贝到内核空间,然后在通过内存映射将数据传递给需要的进程,这样就能完成Android进程间通信。例如四大组件的启动都是通过binder机制和ActivityManageService进行通信,从而完成整个启动过程。

    binder机制简单示意图.png

    AIDL的使用

    一、编写aidl

    1、aidl接口定义

    package com.zyj.binderdome;
    interface IzyjAidlInterface {
     int add(int a,int b);
    }
    

    2、aidl的自动实现

    package com.zyj.binderdome;
    public interface IzyjAidlInterface extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.zyj.binderdome.IzyjAidlInterface {
        private static final java.lang.String DESCRIPTOR = "com.zyj.binderdome.IzyjAidlInterface";
    
        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
    
        /**
         * Cast an IBinder object into an com.zyj.binderdome.IzyjAidlInterface interface,
         * generating a proxy if needed.
         */
        public static com.zyj.binderdome.IzyjAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.zyj.binderdome.IzyjAidlInterface))) {
                return ((com.zyj.binderdome.IzyjAidlInterface) iin);
            }
            return new com.zyj.binderdome.IzyjAidlInterface.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_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }
    
        private static class Proxy implements com.zyj.binderdome.IzyjAidlInterface {
            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 int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                   _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public int add(int a, int b) throws android.os.RemoteException;
    }
    

    这个文件是系统自动生成的,Binder的使用都是同样的套路。
    从这个接口可以看出里面包含一个Binder的子类以及一个对应的Binder代理类,通信是主要是通过这个代理类来操作Binder的子类。

    二、service端
    class ZyjService : Service() {
    val callPackageName: String = "com.zyj.binderdome"
    private var mBinder: IzyjAidlInterface.Stub = object : IzyjAidlInterface.Stub() {
        override fun add(a: Int, b: Int): Int {
            return a * b
        }
        override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean {
            val packagesForUid = this@ZyjService.packageManager.getPackagesForUid(Binder.getCallingUid())
            if (packagesForUid?.size != 0) {
                for (c in packagesForUid) if ((this@ZyjService.callPackageName) == c) {
                    return super.onTransact(code, data, reply, flags)
                }
            }
            return false
        }
    }
    override fun onBind(intent: Intent): IBinder? {
        return mBinder
    }
    }
    

    通过Service的onBind()方法提供Binder对象。当bindService的时候,通过AMS完成对该Service的启动并且拿到Binder的对象,从而返回给client端。

    三、client端
    class MainActivity : AppCompatActivity() {
    private val zyjServiceAction: String = "com.zyj.service"
    private val serviceConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceDisconnected(name: ComponentName?) {
    
        }
    
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val izyjAidlInterface = IzyjAidlInterface.Stub.asInterface(service)
            val sum = izyjAidlInterface?.add(1, 2)
            e("MainActivity", "-->$sum")
            service?.linkToDeath(deathRecipient, 100)
        }
    
        val deathRecipient: IBinder.DeathRecipient = IBinder.DeathRecipient {
            bindService(intent, this, Context.BIND_AUTO_CREATE)
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent()
        intent.`package` = "com.zyj.binder_service"
        intent.action = zyjServiceAction
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
    }
    
    override fun onDestroy() {
        super.onDestroy()
        unbindService(serviceConnection)
    }
    }
    

    client通过ServiceConnection的onServiceConnected方法与Service端建立连接并且返回Binder对象。具体实现建立连接还是通过AMS将两者连接起来,然后在通过asBinder方法获得Binder的代理类BinderPoxy。当client端调用Binder子类对象方法时,通过底层Binder驱动将消息传递到Service端,返回结果后还是得通过底层Binder驱动将结果传递到client端。这样通过Binder驱动桥接两端的通信。

    总结

    至此我们可以知道AIDL是通过Binder机制来完成IPC的。而Android中的IPC主要也是通过Binder来完成的,当然还有一些别的实现IPC方式,比如说Socket、文件共享、Messager等。

    相关文章

      网友评论

        本文标题:Binder浅析——AIDL的使用

        本文链接:https://www.haomeiwen.com/subject/ypmlkftx.html