Android中跨进程通信方式之使用AIDL进阶篇

本文分析上一篇《Android中跨进程通信方式之使用AIDL》中IUserManager的内部结构。

package com.example.aidl;

public interface IUserManager extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.aidl.IUserManager {
        private static final java.lang.String DESCRIPTOR = "com.example.aidl.IUserManager";

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

        /** * Cast an IBinder object into an com.example.aidl.IUserManager * interface, generating a proxy if needed. */
        public static com.example.aidl.IUserManager asInterface(
                android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.aidl.IUserManager))) {
                return ((com.example.aidl.IUserManager) iin);
            }
            return new com.example.aidl.IUserManager.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_findUser: {
                data.enforceInterface(DESCRIPTOR);
                java.util.List<com.example.aidl.User> _result = this.findUser();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }
            case TRANSACTION_addUser: {
                data.enforceInterface(DESCRIPTOR);
                com.example.aidl.User _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.aidl.User.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.addUser(_arg0);
                reply.writeNoException();
                return true;
            }

            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.example.aidl.IUserManager {
            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.util.List<com.example.aidl.User> findUser()
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.example.aidl.User> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_findUser, _data, _reply,
                            0);
                    _reply.readException();
                    _result = _reply
                            .createTypedArrayList(com.example.aidl.User.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addUser(com.example.aidl.User user)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((user != null)) {
                        _data.writeInt(1);
                        user.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addUser, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }


        }

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

    public java.util.List<com.example.aidl.User> findUser()
            throws android.os.RemoteException;

    public void addUser(com.example.aidl.User user)
            throws android.os.RemoteException;

}

首先IUserManager继承IInterface,IInterface是远程AIDL需要继承的类。
具体AIDL是通过内部类Stub实现的,继承了Binder。

public static abstract class Stub extends android.os.Binder implements com.example.aidl.IUserManager

DESCRIPTOR是描述符,必须是包名+类名

private static final java.lang.String DESCRIPTOR = "com.example.aidl.IUserManager";

将IBinder对象转换成IUserManager接口,如果不在一个进程,那么会转换成它的代理。

        /** * Cast an IBinder object into an com.example.aidl.IUserManager * interface, generating a proxy if needed. */
        public static com.example.aidl.IUserManager asInterface(
                android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.example.aidl.IUserManager))) {
                return ((com.example.aidl.IUserManager) iin);
            }
            return new com.example.aidl.IUserManager.Stub.Proxy(obj);
        }

onTransact是服务端最终执行的方法,根据code判断是执行接口中的哪个方法。从data中写入参数,将执行结果通过reply返回。
onTransact方法运行在服务端的Binder线程池中。

        @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_findUser: {
                data.enforceInterface(DESCRIPTOR);
                java.util.List<com.example.aidl.User> _result = this.findUser();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }
            case TRANSACTION_addUser: {
                data.enforceInterface(DESCRIPTOR);
                com.example.aidl.User _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.example.aidl.User.CREATOR
                            .createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                this.addUser(_arg0);
                reply.writeNoException();
                return true;
            }

            }
            return super.onTransact(code, data, reply, flags);
        }

代理类Proxy,如果客户端与服务端不在一个进程中,那么代理类会工作。

private static class Proxy implements com.example.aidl.IUserManager

这两个方法是客户端调用的。从data中写入参数,客户端调用transact方法,客户端当前线程挂起,该方法会执行服务端onTransact方法,等待服务端运行结束,将执行结果通过reply返回,客户端线程才继续执行。

            @Override
            public java.util.List<com.example.aidl.User> findUser()
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.util.List<com.example.aidl.User> _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_findUser, _data, _reply,
                            0);
                    _reply.readException();
                    _result = _reply
                            .createTypedArrayList(com.example.aidl.User.CREATOR);
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            @Override
            public void addUser(com.example.aidl.User user)
                    throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((user != null)) {
                        _data.writeInt(1);
                        user.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_addUser, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }

方法的code值

static final int TRANSACTION_findUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_addUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

IUserManager两个需要实现的抽象方法

public java.util.List<com.example.aidl.User> findUser()
            throws android.os.RemoteException;

    public void addUser(com.example.aidl.User user)
            throws android.os.RemoteException;

总结:当客户端跨进程请求服务端时,客户端当前线程会被挂起(transact方法执行,调用服务端onTransact方法),直到服务端返回数据才会继续执行,如果服务端是一个耗时的方法,那么客户端需要在子线程中请求,服务端的方法是运行在Binder线程池中的,所以不需要在用子线程去执行它。

你可能感兴趣的:(安卓跨进程通信)