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...

  • 相关阅读:
    118/119. Pascal's Triangle/II
    160. Intersection of Two Linked Lists
    168. Excel Sheet Column Title
    167. Two Sum II
    172. Factorial Trailing Zeroes
    169. Majority Element
    189. Rotate Array
    202. Happy Number
    204. Count Primes
    MVC之Model元数据
  • 原文地址:https://www.cnblogs.com/wnpp/p/13135501.html
Copyright © 2011-2022 走看看