美文网首页android之binder学习攻克
Android插件化基础--Binder机制

Android插件化基础--Binder机制

作者: 风咏而归 | 来源:发表于2018-05-11 12:57 被阅读0次

    Binder是一套基于CS的架构。下面以一个极简的例子来学习Binder

    1.首先定义一个IMedia.aidl文件。
    interface IMedia {
        boolean start();
        boolean stop();
    }
    
    2.然后IDE会帮我们自动生成一个IMedia.java文件
    public interface IMedia extends android.os.IInterface {
    
            public static abstract class Stub extends android.os.Binder implements com.cmeiyuan.pluginstudy.IMedia {
                    
                    public android.os.IBinder asBinder(){
                        return this;
                    }
                    
                    public static com.cmeiyuan.pluginstudy.IMedia asInterface(android.os.IBinder obj) {
                        ...
                    }
                    
                    public boolean onTransact(...){
                        ...
                        start();
                        ...
                    }
                    
                    private static class Proxy implements com.cmeiyuan.pluginstudy.IMedia {
                        ...
                    }
            }
        }
        public boolean start() throws android.os.RemoteException;
    }
    

    IMedia是一个继承于android.os.IInterface的接口,它的内部类Stub实现了android.os.IInterfaceasBinder()方法,直接返回了Sub类实例。我们继续看Sub类的asInterface()方法

    public static com.cmeiyuan.pluginstudy.IMedia asInterface(android.os.IBinder obj) {
        if ((obj == null)) {
            return null;
        }
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (((iin != null) && (iin instanceof com.cmeiyuan.pluginstudy.IMedia))) {
            return ((com.cmeiyuan.pluginstudy.IMedia) iin);
        }
        return new com.cmeiyuan.pluginstudy.IMedia.Stub.Proxy(obj);
    }
    

    这个方法的作用是将远程Binder对象转换为方便使用的IMedia接口对象,这个远程Binder对象是我们bindService()时返回的。首选通过obj.queryLocalInterface(DESCRIPTOR)查询是否有本地接口对象,这种情况是当Server端和Client端处于同一进程,没有必要进行多进程通信。如果没有本地接口对象,那么直接new一个Stub.Proxy(obj)实例返回。我们来看一下这个Proxy类的具体实现

    private static class Proxy implements com.cmeiyuan.pluginstudy.IMedia {
        private android.os.IBinder mRemote;
    
        Proxy(android.os.IBinder remote) {
            mRemote = remote;
        }
        
        @Override
        public boolean start() throws android.os.RemoteException {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            boolean _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                mRemote.transact(Stub.TRANSACTION_start, _data, _reply, 0);
                _reply.readException();
                _result = (0 != _reply.readInt());
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }
    }
    

    这个Proxy类是Stub类的内部类,其实就是对obj的一层封装(代理),那么我们通过这个代理类,就很容易和Server端进行通信了。具体实现也很简单,就是调用远程Binder对象mRemotetransact()方法,将数据发送给Server端。

    Stub是一个抽象类,继承于Binder类,实现了父类的onTransact()方法,onTransact()方法的作用是执行Server端的操作,并将操作的结果返回给Client端。一般情况,我们需要写一个子类继承于Stub类,然后实现IMedia的接口方法,这些方法会被父类onTransact()方法调用到。

    3.总结一下多进程通信过程:

    (1)通过bindService()得到远程Binder对象obj
    (2)通过IMedia.Stub.asInterface(obj)得到一个远程代理类Sub.Proxy对象mediaRemoteProxy
    (3)调用mediaRemoteProxy.start()方法,事实上是调用了其内部远程Binder对象mRemotetransact()方法,将数据发送给Server
    (4)服务端收到Client端发送过来的数据时onTransact()会被调用,有一个子类继承于IMedia.Stub类,实现了start()方法,onTransact()被调用时,自然调用到了子类里的start()方法。换言之,Server端的操作被Client调用执行了。

    4.start()方法是在哪个线程被执行的
    private IMedia.Stub stub = new IMedia.Stub() {
        @Override
        public boolean start() throws RemoteException {
            Log.d("cmy", "media start:" + Thread.currentThread().getId());
            return true;
        }
    };
    

    通过调试程序发现start()方法被执行在名为binder1binder2的线程中,而不是主线程。这也解释了系统的ActivityManagerService向应用进程发送消息时,需要使用H类把消息转发到UI线程,而且也必须这么做,因为UI线程调用了Looper.loop()开启了循环,线程是被阻塞的。

    相关文章

      网友评论

        本文标题:Android插件化基础--Binder机制

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