Android:不使用AIDL实现进程间的通信

来源:互联网 发布:怎么设计淘宝店 编辑:程序博客网 时间:2024/06/04 19:06

在上一篇:Android Studio中实现AIDL

中我们已经学会使用AIDL的简单操作,那么现在来实现一下在不依赖AIDL的前提下,实现进程间的通信。

1、Binder:

实现进程间的相互通信。

2、Service:

一个独立的进程。在Android中我们要实现进程间的通信,就必须要用到Service,那么我么就从这里开始分析:

@Overridepublic IBinder onBind(Intent intent) {    Logger.d("onBind");    return mBinder;}
在实onBind(Intent intent)方法中,我们必须要返回一个IBinder对象,如果不返回,则不能够正常通信:

IBinder

android.os.IBinderKnown Indirect SubclassesBinderBase class for a remotable object, the core part of a lightweight remote procedure call mechanism defined byIBinder

其子类就是一个Binder,

那么我们在来看通过AIDL实现进程通信时的方法:

这里使用:ICalculatorAIDL.aidl 为例

分析代码:

private final ICalculatorAIDL.Stub mBinder = new ICalculatorAIDL.Stub() {    @Override    public String aidlTest(String msg) throws RemoteException {        return "经过AIDL测试后:"+msg;    }};
onBinder()方法中的mBinder由这里获取,那么我们看看ICalculatorAIDL.Stub :

/** * Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.gr.aidl.ICalculatorAIDL {
Stub实质就是一个Binder对象的子类,那么我们可以设想创建一个类来继承Binder类,来代替Stub;

private final MyBinder mBinder = new MyBinder();private class MyBinder extends Binder {    /**     * 要实现通信,必须要从写该方法     * @param code 服务器通过该指令来区分所要执行的方法     * @param data 客户端传入的数据     * @param reply 服务端返回的数据     * @param flags 是否有返回值,0为有,1为没有     * @return     * @throws RemoteException     */    @Override    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {        return super.onTransact(code, data, reply, flags);    }

现在来分析一下AIDL中onTransact()方法中到底做了什么。

// ICalculatorAIDL.aidlpackage com.gr.aidl;// Declare any non-default types here with import statementsinterface ICalculatorAIDL {    String aidlTest(String msg);}
@Overridepublic 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_aidlTest: {            //与客户端的writeInterfaceToken对用,标识远程服务的名称            data.enforceInterface(DESCRIPTOR);            //创建String对象            java.lang.String _arg0;            //从data中读取String数据,因为我传入的是一个String            _arg0 = data.readString();            //调用aidlTest()方法,并传入对应参数(在CalculatorAIDLService中已被实现)            java.lang.String _result = this.aidlTest(_arg0);            reply.writeNoException();            //写入执行结果,返回给客户端            reply.writeString(_result);            return true;        }    }    return super.onTransact(code, data, reply, flags);}
ok,既然这样,我们也这样实现:

private class MyBinder extends Binder {    public static final String DESCRIPTOR = "CalculatorAIDLService";    public static final int TAG = 0x11;//这里是自己定义的,方便区别    @Override    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {        switch (code) {            case TAG:                data.enforceInterface(DESCRIPTOR);                String param = data.readString();                String result = "这里是使用不依赖AIDL加工的:"+param; //修改文字格式                reply.writeNoException();                reply.writeString(result);                return true;        }        return super.onTransact(code, data, reply, flags);    }}

3、Client:

客户端与服务端的连接是通过ServieceConnection进行通信的:

private ServiceConnection mServiceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//            mIcalculatorAIDL = ICalculatorAIDL.Stub.asInterface(iBinder);            mBinder = iBinder; 
Logger.d("onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName componentName) { Logger.d("onServiceDisconnected"); } };
如果连接成功,则调用onServiceConnection()方法,并传递一个IBinder对象回来。这里的IBinder就是我们所要的Binder。在上面代码中我们在之前使用AIDL方法的时候,调用了:

//            mIcalculatorAIDL = ICalculatorAIDL.Stub.asInterface(iBinder);
通过观察,实质上是调用了:

return new com.gr.aidl.ICalculatorAIDL.Stub.Proxy(obj);
继续:

    private static class Proxy implements com.gr.aidl.ICalculatorAIDL {        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 aidlTest(java.lang.String msg) 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(msg); //传入的参数值                mRemote.transact(Stub.TRANSACTION_aidlTest, _data, _reply, 0); //调用IBinder中的transact
                _reply.readException();
_result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_aidlTest = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}
这里的Proxy对我们的接口方法进行了实现:

 @Override        public java.lang.String aidlTest(java.lang.String msg) throws android.os.RemoteException {}
现在客户端上实现:

//onClick 事件public void sendMessage(View view) {    Logger.d("sendMessage");    if (mBinder == null) {        return;    }    Parcel _data = Parcel.obtain();    Parcel _reply = Parcel.obtain();    String _result = "";    try {        _data.writeInterfaceToken(CalculatorAIDLService.DESCRIPTOR);        _data.writeString(mMessage);
        //注意:这里不能直接使用MyBinder类的mBinder.onTransact()方法,如果在这里调用的话,得不到准确结果        /**     * Default implementation rewinds the parcels and calls onTransact.  On     * the remote side, transact calls into the binder to do the IPC.     */   /** public final boolean transact(int code, Parcel data, Parcel reply,    *      int flags) throws RemoteException {    *     if (false) Log.v("Binder", "Transact: " + code + " to " + this);    *     if (data != null) {    *         data.setDataPosition(0);    *     }    *     boolean r = onTransact(code, data, reply, flags);    *     if (reply != null) {    *         reply.setDataPosition(0);    *     }    *     return r;    * }      */         mBinder.transact(CalculatorAIDLService.TAG,
_data, _reply, 0);
        _reply.readException();
_result = _reply.readString(); Toast.makeText(this, _result, Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); } finally { _reply.recycle(); _data.recycle(); }}
ok,现在运行测试:


源码下载

1 0
原创粉丝点击