Kotlin进程通信------AIDL

Posted 战国剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin进程通信------AIDL相关的知识,希望对你有一定的参考价值。

前篇介绍了进程通信中,串行通信的方式Messenger。但如果进程间,有多个方法要并行调用,那么Messenger就不合适使用,而应该使用AIDL方式。

Java方式的AIDL,在之前的文章中有介绍:Android远程接口之AIDL——Parcelable、in、out、inout简例

此处,主要将前文中的Java方式用Kotlin方式翻译。

AIDL方式通信,在Kotlin中遵循和Java中同样的规则,包括数据结构的限制,AIDL文件的编写。

一、AIDL文件编写

AIDL文件的编写,有特定的要求如下:

支持数据类型如下:
1. Java 的原生类型
2. String 和CharSequence
3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;  以上三种类型都不需要导入(import)
4. AIDL 自定义生成的接口  需要导入(import)
————————————————
版权声明:本文为CSDN博主「战国剑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yangzhaomuma/article/details/50576017

除基础类型外,如果我们要自定义类,需要手动导入(import),并且aidl文件和同名类文件的位置,有做要求:

以上图为例:

1、aidl文件夹与java文件夹,同层次

2、自定义的类,如果要在aidl中使用,有两个需要注意的地方:

      2-1: 需要在java文件夹、aidl文件夹两处地方都做定义,并且包名需要一致,如图中的UserInfo类。

     2-2: 如UserInfo这种在aidl中使用的自定义类,需要实现 Parcelable 接口。

了解以上规则,就用代码实现相应逻辑。

3、具体的AIDL文件如下(kotlin中,具体的aidl文件写法,还是java形式的):

3-1 IBase.aidl

// IBase.aidl
package com.me.kotlinprocess;
import com.me.kotlinprocess.aidl.UserInfo;
// Declare any non-default types here with import statements

interface IBase 
   int add(int i,int j);
   String getUserInfo(in UserInfo userInfo);
   void getaList(out String[] list);
   void setaList(in String[] list);
   void gettList(inout String[] list);

3-2 UserInfo.aidl

// UserInfo.aidl
package com.me.kotlinprocess.aidl;

// Declare any non-default types here with import statements
parcelable UserInfo;

二、server端实现

server端,只需要实现service接口,并返回onBind的实现即可。此处IBase.Stub即是服务的实现。

kotlin中,服务的实现,应该是屏蔽了in、out 、inout参数的差异。此处生成的方法都是统一以out修饰。此处有疑议,如有不对请指出。

class AidlService : Service() 

    override fun onBind(intent: Intent?): IBinder? 
        return stub
    

    val stub:IBase.Stub = object:IBase.Stub()
        override fun add(i: Int, j: Int): Int 
            return i+j
        

        override fun getUserInfo(userInfo: UserInfo?): String 
            val resultString : String = "---- $userInfo?.name  $userInfo?.address $userInfo?.age ----"
            return resultString
        

        override fun getaList(list: Array<out String>?) 
            println("getaList $list?.get(0)")
        

        override fun setaList(list: Array<out String>?) 
            println("setaList $list?.get(0)")
        

        override fun gettList(list: Array<out String>?) 
            println("gettList $list?.get(0)")
        


    

三、client端实现

client端的实现,流程也很清晰。先连接上服务,之后,可通过接口调用具体的服务。

1、连接服务

var iBase: IBase? = null
//连接定义
private val serviceConnect = object : ServiceConnection 
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) 
            println("connect success")
            iBase = IBase.Stub.asInterface(service)
        

        override fun onServiceDisconnected(name: ComponentName?) 
            println("connect fail")
            iBase = null
        
    


//连接服务
bindService(
                Intent(this, AidlService::class.java),
                serviceConnect,
                Context.BIND_AUTO_CREATE
            )

2、调用服务

fun testAidl() 
        val add = iBase?.add(1, 2)
        println("add result $add")
        val userInfo: UserInfo = UserInfo()
        userInfo.name = "bob"
        userInfo.address = "hangzhou"
        userInfo.age = 20
        val userInfo1 = iBase?.getUserInfo(userInfo)
        println("userInfo result $userInfo1")
    

最后,别忘了在manifest中加上service的定义:

<service
            android:name=".aidl.AidlService"
            android:label="@string/aidl_name"
            android:process=":aidl_remote">
        </service>

至此,完成aidl的进程通信。

aidl的信息通信,主要的嘈点在于aidl文件编写和规范、连接管理较为繁琐。可以在这基础上,封装一套简易通信框架。期待后续。

以上是关于Kotlin进程通信------AIDL的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin进程通信------AIDL

kotlin简单实现AIDL进程间通信

kotlin简单实现AIDL进程间通信

Android中的IPC进程通信方式第三篇

Android中的IPC进程通信方式第四篇

源码分析——从AIDL的使用开始理解Binder进程间通信的流程