Binder机制补充篇(一)transact与onTransact

前面的文章已经完成了包括Binder的底层原理,AIDL的实现等等,

最近发现漏掉了transact与onTransact,所以补充一下

看下源码及注释

transact

  /**
     * Perform a generic operation with the object.
     * 
     * @param code The action to perform.  This should
     * be a number between {@link #FIRST_CALL_TRANSACTION} and
     * {@link #LAST_CALL_TRANSACTION}.
     * @param data Marshalled data to send to the target.  Must not be null.
     * If you are not sending any data, you must create an empty Parcel
     * that is given here.
     * @param reply Marshalled data to be received from the target.  May be
     * null if you are not interested in the return value.
     * @param flags Additional operation flags.  Either 0 for a normal
     * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
     *
     * @return Returns the result from {@link Binder#onTransact}.  A successful call
     * generally returns true; false generally means the transaction code was not
     * understood.
     */
    public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
        throws RemoteException;

onTransact

 /**
     * Default implementation is a stub that returns false.  You will want
     * to override this to do the appropriate unmarshalling of transactions.
     *
     * 

If you want to call this, call transact(). * *

Implementations that are returning a result should generally use * {@link Parcel#writeNoException() Parcel.writeNoException} and * {@link Parcel#writeException(Exception) Parcel.writeException} to propagate * exceptions back to the caller.

* * @param code The action to perform. This should * be a number between {@link #FIRST_CALL_TRANSACTION} and * {@link #LAST_CALL_TRANSACTION}. * @param data Marshalled data being received from the caller. * @param reply If the caller is expecting a result back, it should be marshalled * in to here. * @param flags Additional operation flags. Either 0 for a normal * RPC, or {@link #FLAG_ONEWAY} for a one-way RPC. * * @return Return true on a successful call; returning false is generally used to * indicate that you did not understand the transaction code. */ protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException { if (code == INTERFACE_TRANSACTION) { reply.writeString(getInterfaceDescriptor()); return true; } else if (code == DUMP_TRANSACTION) { ParcelFileDescriptor fd = data.readFileDescriptor(); String[] args = data.readStringArray(); if (fd != null) { try { dump(fd.getFileDescriptor(), args); } finally { IoUtils.closeQuietly(fd); } } // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } return true; } else if (code == SHELL_COMMAND_TRANSACTION) { ParcelFileDescriptor in = data.readFileDescriptor(); ParcelFileDescriptor out = data.readFileDescriptor(); ParcelFileDescriptor err = data.readFileDescriptor(); String[] args = data.readStringArray(); ShellCallback shellCallback = ShellCallback.CREATOR.createFromParcel(data); ResultReceiver resultReceiver = ResultReceiver.CREATOR.createFromParcel(data); try { if (out != null) { shellCommand(in != null ? in.getFileDescriptor() : null, out.getFileDescriptor(), err != null ? err.getFileDescriptor() : out.getFileDescriptor(), args, shellCallback, resultReceiver); } } finally { IoUtils.closeQuietly(in); IoUtils.closeQuietly(out); IoUtils.closeQuietly(err); // Write the StrictMode header. if (reply != null) { reply.writeNoException(); } else { StrictMode.clearGatheredViolations(); } } return true; } return false; }

简单说来

我们下面测试一下:

Service

        
            
                
            
        

Client端

   public void transact(View view) {
        Parcel parcel1 = Parcel.obtain();
        Parcel parcel2 = Parcel.obtain();

        try {
            binder.transact(0,parcel1,parcel2,0);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

Server端:

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"onBind");
        Binder binder = new Binder();
        return new Binder(){

            @Override
            protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
                Log.i(TAG,"接收到远端调用"+"code"+code);
                return super.onTransact(code, data, reply, flags);
            }
        };
    }

通过测试发现onTransact 会被触发两次,

第一次是

code 1598968902

第二次才是自己定义的值

这个  1598968902 其实是一个常量值

    /**
     * IBinder protocol transaction code: interrogate the recipient side
     * of the transaction for its canonical interface descriptor.
     */
    int INTERFACE_TRANSACTION   = ('_'<<24)|('N'<<16)|('T'<<8)|'F';

参考:

https://blog.csdn.net/sergeycao/article/details/52585411

https://blog.csdn.net/u012758088/article/details/68485367

你可能感兴趣的:(安卓)