zoukankan      html  css  js  c++  java
  • Aidl和Binder解析

    先上实例代码:

    service:

    public class AidlService extends Service{

        @Override
        public IBinder onBind(Intent arg0) {
            /*return new AIDLTest.Stub() {

                @Override
                public String hello(String name) throws RemoteException {
                    // TODO Auto-generated method stub
                    return "hello"+name;
                }
            };*/
            return mBinder;
        }

        //一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象【对象的引用】
        private final AIDLTest.Stub mBinder = new AIDLTest.Stub() {

            @Override
            public String hello(String name) throws RemoteException {
                // TODO Auto-generated method stub
                return "hello"+name;
            }
        };

    client:

    Intent intent = new Intent();
    intent.setPackage("包名");

    context.bindService(intent, serviceConnection,Context.BIND_AUTO_CREATE);
    private ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
    Log.d(TAG, "++++++ onServiceConnected: success ++++++");
    AIDLTest vasInterface = AIDLTest.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
    vasInterface = null;
    }
    };

    vasInterface.hello("aaaaaaaa");

    解析:

    最主要的部分是AS自动生成的AIDLTest文件:

    /*
     * This file is auto-generated.  DO NOT MODIFY.
     * Original file: F:\Project\Practice\FrameworkDemo\app\src\main\aidl\com\example\admin\frameworkdemo\AIDLTest.aidl
     */
    package com.example.admin.frameworkdemo;
    
    public interface AIDLTest extends android.os.IInterface {
        /**
         * Local-side IPC implementation stub class.
         */
        public static abstract class Stub extends android.os.Binder implements com.example.admin.frameworkdemo.AIDLTest {
            private static final java.lang.String DESCRIPTOR = "com.example.admin.frameworkdemo.AIDLTest";
    
            /**
             * Construct the stub at attach it to the interface.
             */
            public Stub() {
                this.attachInterface(this, DESCRIPTOR);
            }
    
            /**
             * Cast an IBinder object into an com.example.admin.frameworkdemo.AIDLTest interface,
             * generating a proxy if needed.
             */
            public static com.example.admin.frameworkdemo.AIDLTest asInterface(android.os.IBinder obj) {
                if ((obj == null)) {
                    return null;
                }
                android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.example.admin.frameworkdemo.AIDLTest))) {
                    return ((com.example.admin.frameworkdemo.AIDLTest) iin);
                }
                return new com.example.admin.frameworkdemo.AIDLTest.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_hello: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _arg0;
                        _arg0 = data.readString();
                        java.lang.String _result = this.hello(_arg0);
                        reply.writeNoException();
                        reply.writeString(_result);
                        return true;
                    }
                }
                return super.onTransact(code, data, reply, flags);
            }
    
            private static class Proxy implements com.example.admin.frameworkdemo.AIDLTest {
                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 java.lang.String hello(java.lang.String name) throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.lang.String _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        _data.writeString(name);
                        mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.readString();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }
            }
    
            static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        }
    
        public java.lang.String hello(java.lang.String name) throws android.os.RemoteException;
    }

    步骤:

    如以下代码,在服务端,AidlService在被client端的bindservice启动之后,会执行onBind,返回一个继承于IBinder的类mBinder

    IBinder是底层的一个借口,实现该接口的类也具有了远程调用的能力,并重写了方法hello,这个后面再说。

    private final AIDLTest.Stub mBinder = new AIDLTest.Stub() {

            @Override
            public String hello(String name) throws RemoteException {
                // TODO Auto-generated method stub
                return "hello"+name;
            }
        };

    client端绑定成功之后,得到IBinder的继承类的应用,其实就是service端的mBinder的引用

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "++++++ onServiceConnected: success ++++++");
            vasInterface = AIDLTest.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            vasInterface = null;
        }
    };

    client端紧接着执行

    AIDLTest.Stub.asInterface(service);

    进入asInterface:

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

    这里queryLocalInterface判断是跨进程调用,如果是跨进程调用,执行

    return new com.example.admin.frameworkdemo.AIDLTest.Stub.Proxy(obj);

    此时得到了一个Proxy类,传进去的obj是远程服务端的mBinder引用,即Proxy类持有远程服务端mBinder的引用。

    此时回到client调用接口:

    vasInterface.hello("aaaaaaaa");

    此时我们知道vasInterface是一个AIDLTest.Stub.Proxy,执行里面的方法hello,

    @Override
                public java.lang.String hello(java.lang.String name) throws android.os.RemoteException {
                    android.os.Parcel _data = android.os.Parcel.obtain();
                    android.os.Parcel _reply = android.os.Parcel.obtain();
                    java.lang.String _result;
                    try {
                        _data.writeInterfaceToken(DESCRIPTOR);
                        _data.writeString(name);
                        mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
                        _reply.readException();
                        _result = _reply.readString();
                    } finally {
                        _reply.recycle();
                        _data.recycle();
                    }
                    return _result;
                }

    可以看到hello里面执行了可以看到里面执行了mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);

    data代表了客户端传进去的数据,reply代表了服务端将要返回来的数据。

    mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);

    该方法实际上是通过底层的Binder驱动调用到C/C++层的JavaBBinder对象的tansact方法,而该方法通过JNI来调用JAVA 层上Binder对象的execTransact()方法,
    并进而调用开发者自己可以覆盖的onTransact()方法从而达到了通信的目标
    @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_hello: {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _arg0;
                        _arg0 = data.readString();
                        java.lang.String _result = this.hello(_arg0);
                        reply.writeNoException();
                        reply.writeString(_result);
                        return true;
                    }
                }
                return super.onTransact(code, data, reply, flags);        }

    这里面执行了:this.hello(_arg0),而这个函数执行的应该就是子类mBinder在应用层定义的匿名类的里面的方法:

    rivate final AIDLTest.Stub mBinder = new AIDLTest.Stub() {

            @Override
            public String hello(String name) throws RemoteException {
                // TODO Auto-generated method stub
                return "hello"+name;
            }
        };

    然后通过reply.writeString(_result);将执行结果写到replay里面。

    为什么AS自动生成的AIDLTest文件里面,Stub要定义为AIDLTest的内部类:

    自动生成的aidl文件可能不止一个,Stub定义成内部类,使用的时候容易区分,比如:AIDLTest.Stub,AIDLTest2.Stub...

  • 相关阅读:
    Swift3 ——S3 API中间件兼容性测试
    解决 Python.h:没有那个文件或目录 错误的方法
    Swift云存储特性研究
    解决updateaptxapi占用资源过高的问题
    dll开发及调用
    git批量备份
    UDP端口扫描
    将markdown文件转换为pdf
    指定ssh key访问git
    CentOS6.2调整home分区大小
  • 原文地址:https://www.cnblogs.com/wnpp/p/13135501.html
Copyright © 2011-2022 走看看