Android Bound Service(三) ----- 解说 AIDL产生的接口类

在上一篇解说使用 AIDL进行跨进程传数据的文章中,有提到了会解说 AIDL产生的接口类,所以在这一篇文章,

就是学习接口类大致是如何构成的,还有这个接口怎麽完成跨进程的工作。AIDL类产生的接口类代码大约像这样…

public interface IMyInterface extends IInterface {
    public int getPid() throws RemoteException;
    public String getServiceName() throws RemoteException;
    public void makeSingingService() throws RemoteException;

    public abstract static class Stub extends Binder implements IMyInterface {
        private static final String DESCRIPTOR = "com.example.shanwu.interprocesscomm.IMyInterface";

        static final int TRANSACTION_getPid = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_getServiceName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
        static final int TRANSACTION_makeSingingService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

        public Stub() {
            attachInterface(this, DESCRIPTOR);
        }

        public static IMyInterface asInterface(IBinder obj) {
            if (obj == null) {
                return null;
            }
            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (iin != null && iin instanceof IMyInterface) {
                Log.d("guang", "iin != null && iin instanceof IMyInterface --" + String.valueOf(android.os.Process.myPid()));
                return (IMyInterface) iin;
            } else {
                Log.d("guang", "lin else" + String.valueOf(android.os.Process.myPid()));
                return new IMyInterface.Stub.Proxy(obj);
            }
        }

        @Override
        public IBinder asBinder() {
            return this;
        }

        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION:
                    Log.d("guang","INTERFACE_TRANSACTION -- stub "+ String.valueOf(android.os.Process.myPid()));
                    reply.writeString(DESCRIPTOR);
                    return true;

                case TRANSACTION_getPid:
                    Log.d("guang","TRANSACTION_getPid -- stub "+ String.valueOf(android.os.Process.myPid()));
                    data.enforceInterface(DESCRIPTOR);
                    int result = this.getPid();
                    reply.writeNoException();
                    reply.writeInt(result);
                    return true;

                case TRANSACTION_getServiceName:
                    Log.d("guang","TRANSACTION_getServiceName -- stub "+ String.valueOf(android.os.Process.myPid()));
                    data.enforceInterface(DESCRIPTOR);
                    String serviceName = this.getServiceName();
                    reply.writeNoException();
                    reply.writeString(serviceName);
                    return true;

                case TRANSACTION_makeSingingService:
                    Log.d("guang","TRANSACTION_makeSingingService -- stub "+ String.valueOf(android.os.Process.myPid()));
                    data.enforceInterface(DESCRIPTOR);
                    this.makeSingingService();
                    reply.writeNoException();
                    return true;
            }
            return super.transact(code, data, reply, flags);
        }

        private static class Proxy implements IMyInterface {
            private IBinder mRemote;

            Proxy(IBinder remote) {
                mRemote = remote;
            }

            @Override
            public IBinder asBinder() {
                return mRemote;
            }

            public String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }


            @Override
            public int getPid() throws RemoteException {
                Log.d("guang", "getPid -- proxy " + String.valueOf(android.os.Process.myPid()));
                Parcel data = Parcel.obtain();
                Parcel reply = Parcel.obtain();
                int result;

                try {
                    data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getPid, data, reply, 0);
                    reply.readException();
                    result = reply.readInt();
                } finally {
                    // ensure we recycle parcels back to pool, but why ?
                    data.recycle();
                    reply.recycle();
                }
                return result;
            }

            @Override
            public String getServiceName() throws RemoteException {
                Log.d("guang", "getServiceName -- proxy " + String.valueOf(android.os.Process.myPid()));

                Parcel data = Parcel.obtain();
                Parcel reply = Parcel.obtain();
                String result;

                try {
                    data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_getServiceName, data, reply, 0);
                    reply.readException();
                    result = reply.readString();
                } finally {
                    data.recycle();
                    reply.recycle();
                }

                return result;
            }

            @Override
            public void makeSingingService() throws RemoteException {
                Log.d("guang", "makeSingingService -- proxy " + String.valueOf(android.os.Process.myPid()));

                Parcel data = Parcel.obtain();
                Parcel reply = Parcel.obtain();

                try {
                    data.writeInterfaceToken(DESCRIPTOR);
                    mRemote.transact(Stub.TRANSACTION_makeSingingService, data, reply, 0);
                    reply.readException();
                } finally {
                    Log.d("guang", "makeSingingService finally-- proxy " + String.valueOf(android.os.Process.myPid()));
                    data.recycle();
                    reply.recycle();
                }

            }
        }
    }

}

突然一看,感觉相当复雜,但是稍微整理一下,它的架构就大约清楚了…


它是由二个内部类构成的,一个叫 Stub,一个叫 Proxy。Stub是一个 abstract class 需要提供服务的 Service 实现相关的方法

    private final IMyInterface.Stub mBinder = new IMyInterface.Stub() {
        @Override
        public int getPid() throws RemoteException {
            return android.os.Process.myPid();
        }

        @Override
        public String getServiceName() throws RemoteException {
            return "Worker Service~ ";
        }

        @Override
        public void makeSingingService() {
            mHandler.sendEmptyMessage(MSG_START_SING);
        }
    };
并且在建立连结回调 onBind()的时候,返回此 Stub 对象

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

而 Proxy 则是一个内部静态类实现了该接口,成为使用服务的接口对象代理,而在调用bindService()时,回调 onServiceConnected() 时初始化

        mServiceConn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                mService = IMyInterface.Stub.asInterface(iBinder);
                Log.d("guang", "onServiceConnected");
                mIsBind = true;
            }

            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                Log.d("guang", "onServiceDisconnected");
                mIsBind = false;
            }
        };
然後在客户端调这个远端的 Proxy 对象使用

            case R.id.btn_sing:
                if (mIsBind) {
                    try {
                        mWorkerId = mService.getPid();
                        Toast.makeText(MainActivity.this, mWorkerId + "", Toast.LENGTH_LONG).show();
                        mService.makeSingingService();
                    } catch (RemoteException e) {
                        Log.e("guang", "Service is dead " + e);
                    }
                }
                break;
最後,我们可以将它们的沟通流程简化成下面的一张图

这样看起来,会不会简单一些? 有问题欢迎一起讨论~~

范例代码都在 GitHub


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值