AIDL 问题总结

170 阅读3分钟

在 AIDL 中,可以使用 oneway、inout 和 out 等关键字来定义不同类型的方法参数。其中 oneway 表示单向通信,即只能由客户端向服务端发送请求。

build.gradle 配置问题

sourceSets {
        main {
            java.srcDirs[
                    'src\\main\\java',
                    'src\\main\\aidl',
            ]
        }
    }

buildFeatures {
        dataBinding true
        aidl true
    }

service 启动问题

val intent = Intent().apply {
     component = ComponentName("com.demo.arouter","com.demo.arouter.aidl.ComputeService")
     action = "com.demo.aidl.ComputeService"
}
//8.0 后台启动问题
 startForegroundService(intent)
 bindService(intent, connection, Context.BIND_AUTO_CREATE )

//客户端AndroidManifest.xml配置包可见
// Android11 
<queries >
        <package android:name="com.demo.arouter"/>

        <intent>
            <action android:name="com.demo.aidl.ComputeService"/>
        </intent>
    </queries>

<service
            android:name=".aidl.ComputeService"
            android:exported="true"
            android:enabled="true">
<!--            android:process=":compute">-->
            <intent-filter>
                <action android:name="com.demo.aidl.ComputeService" />

                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

ComputeInterface.Stub

返回的IBinder 问题

  • 本地访问,返回的是本地对象
  • 远程访问service 是返回的代理对象proxy
  • proxy 执行必须经过onTransact
     public static com.demo.arouter.ComputeInterface asInterface(android.os.IBinder obj)
        {
          if ((obj==null)) {
            return null;
          }
          //本地访问,返回的是本地对象
          android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
          if (((iin!=null)&&(iin instanceof com.demo.arouter.ComputeInterface))) {
            return ((com.demo.arouter.ComputeInterface)iin);
          }
          return new com.demo.arouter.ComputeInterface.Stub.Proxy(obj);
        }

方法从1-N 按顺序写入,

热修复只能从后追加方法,而不能打乱顺序,

    int FIRST_CALL_TRANSACTION  = 0x00000001;
    static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_addTwo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_addCompute = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    static final int TRANSACTION_getCompute = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
    static final int TRANSACTION_getComputeForClientIn = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
    static final int TRANSACTION_getComputeForClientOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
    static final int TRANSACTION_getComputeForClientInOut = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);

class ComputeBinder : ComputeInterface.Stub() {
    override fun add(a: Int) {
        log("ComputeBinder add 调用了- a: $a")
    }

    override fun addTwo(a: Int, b: Int): Int {
        log("ComputeBinder addTwo 调用了- a: $a , b: $b")
        return a + b;
    }

    override fun addCompute(c: Compute?): Int {
        log("ComputeBinder addCompute 调用了- c: ${c.toString()}")
        c ?: return 0
        return c.a * c.b
    }

    override fun getCompute(a: Int, b: Int): Compute {
        log("ComputeBinder getCompute 调用了- a: $a , b: $b")
        return Compute(a + 1, b + 1)
    }

    override fun getComputeForClientIn(c: Compute?): Compute {
        log("ComputeBinder getComputeForClient 调用了- a: ${c?.a} , b: ${c?.b}")
        return c?.copy(a = 111, b = 222)?:Compute(1000,10000)
    }

    override fun getComputeForClientOut(c: Compute?): Compute {
        log("ComputeBinder getComputeForClientOut 调用了- a: ${c?.a} , b: ${c?.b}")
        return c?.copy(a = 111, b = 222)?:Compute(1000,10000)
    }

    override fun getComputeForClientInOut(c: Compute?): Compute {
        log("ComputeBinder getComputeForClientInOut 调用了- a: ${c?.a} , b: ${c?.b}")

        return c?.copy(a = 111, b = 222)?:Compute(1000,10000)
    }


    override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
        val flag = super.onTransact(code, data, reply, flags)
        log(
            """
         ComputeBinder  onTransact调用了
              code  : $code
              data  : $data
              reply : $reply
              flags : $flags
         onTransact : $flag
                
            """.trimIndent()
        )
        return flag
    }


    fun log(msg: String) {
        Log.e("TAG", "aidl-- $msg")
    }

}

in,out,intout 定向tag 问题

  1. in :user 服务端完整读取,不会写入客户端 ,user不变
  2. out : user 服务端不会读取,但会写入客户端, user改变
  3. intout : user服务端完整读取,完整写入客户端 user改变
   
   Compute getComputeForClientIn(in Compute c);
   Compute getComputeForClientOut(out Compute c);
   Compute getComputeForClientInOut(inout Compute c);

日志

1685705556056.jpg

oneWay

oneway void onewayMethod(int param); 
  • oneway 是一种用于 AIDL 方法的修饰符,表示非阻塞调用。
  • 适用场景:不需要返回结果的调用,或需要提高性能的场景。
  • 限制oneway 方法必须返回 void,且不能有 inout 或 out 参数。
  • 注意事项oneway 方法不会抛出异常,且调用顺序可能与执行顺序不一致。

通过合理使用 oneway,可以优化跨进程通信的性能和响应速度。

kotlin 序列化 问题 Compute

readFromParcel()需要手动添加, kotlin默认CREATOR写入,重新创建对象,达不到 out inout 输出的效果

package com.demo.arouter

import android.os.Parcel
import android.os.Parcelable

data class Compute(var a: Int = 0, var b: Int = 0) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readInt(),
        parcel.readInt()
    ) {
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(a)
        parcel.writeInt(b)
    }
    //需要
    fun readFromParcel(parcel: Parcel){
        a = parcel.readInt()
        b = parcel.readInt()
    }


    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Compute> {
        override fun createFromParcel(parcel: Parcel): Compute {
            return Compute(parcel)
        }

        override fun newArray(size: Int): Array<Compute?> {
            return arrayOfNulls(size)
        }
    }


}