Android AIDL

AIDL简介

什么是AIDL

AIDL是Android中IPC(Inter-Process Communication)方式中的一种,AIDL是Android Interface definition language的缩写

AIDL有什么作用

对于小白来说,AIDL的作用是让你可以在自己的APP里绑定一个其他APP的service,这样你的APP可以和其他APP交互。

什么场景下使用AIDL

AIDL更加适合在多个应用程序之间,多线程的情况下进行进程间通信

Binder更适合在多个应用程序之间单线程都情况下进行进程间通信

Messenger更适合在只有进程间通信单线程单个应用程序中使用

使用AIDL

新建AIDL文件

首先,在Android Studio中项目那边有机,New–>Folder–>AIDL Folder
Android AIDL_第1张图片
新建出来都aidl目录跟java是同级的
Android AIDL_第2张图片
aidl目录下新建对应都aidl文件
Android AIDL_第3张图片

AIDL支持的数据类型

Android 开发网中有写

All primitive types in the Java programming language (such as int, long, char, boolean, and so on)
String
CharSequence
List
Map

虽然官方文档指明所有的java基础数据类型都是被支持的,但是实际上short并不支持,如果数据类型中含有short,则编译的时候会报以下错误:ERROR: xxx/IMyAidlInterface.aidl:15.38-43: Failed to resolve 'short'

需要注意的是Map不能够写泛型,如果写泛型的话,编译的时候会报以下错误:aidl E 08-31 17:11:09 17172 8244311 type_java.cpp:357] Don't know how to create a Map container.

List虽然可以写泛型,但是泛型只能是上面提到的那些数据类型才行,类似于Integer也是不能被支持的,如果List的泛型是Integer,则编译的时候会报以下错误:ERROR: xxx/IMyAidlInterface.aidl:16.63-70: Failed to resolve 'Integer'

对于自定义的实现了Parcelable的数据类型也是可以支持的,但是必须建立一个.aidl文件声明你的parcelable类,例如

package top.xuqingquan.aidltest;

parcelable User;

对于所有非基本数据类型要求一个定向的tag来指定数据是去往哪个方向的,且只能是inoutinout

以下是完整的aidl文件

// IMyAidlInterface.aidl
package top.xuqingquan.aidltest;

import java.util.List;
import java.util.Map;
import top.xuqingquan.aidltest.User;

interface IMyAidlInterface {

    List<User> basicTypes(byte aByte,/*short aShort,*/ int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble,char aChar, String aString,in List<String> aList,in Map aMap,CharSequence aCharSequence,in User user);

}

服务端实现

新建一个Service,onBind方法返回的是一个实现刚才aidl的接口,具体代码如下:

package top.xuqingquan.aidltest

import android.app.Service
import android.content.Intent
import android.os.IBinder


class ITestAidlService : Service() {

    private lateinit var users: MutableList<User?>

    override fun onBind(p0: Intent?): IBinder {
        users = arrayListOf()
        return iBinder
    }

    private val iBinder: IBinder = object : IMyAidlInterface.Stub() {
        override fun basicTypes(
            aByte: Byte,
            anInt: Int,
            aLong: Long,
            aBoolean: Boolean,
            aFloat: Float,
            aDouble: Double,
            aChar: Char,
            aString: String?,
            aList: MutableList<String>?,
            aMap: MutableMap<Any?, Any?>?,
            aCharSequence: CharSequence?,
            user: User?
        ): List<User?> {
            users.add(user)
            return users
        }
    }
}

客户端的实现

客户端需要将服务端的整个aidl目录下的内容全部复制一份,对于服务端有的User类,也需要在与服务端相同的包目录下定义剩下的就只需要使用bindService绑定ServiceServiceConnectiononServiceConnected可以拿到远程的aidl,这时候就可以使用它调用相关的方法了

package top.xuqingquan.aidlclienttest

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import kotlinx.android.synthetic.main.activity_main.*
import top.xuqingquan.aidltest.IMyAidlInterface
import top.xuqingquan.aidltest.User

class MainActivity : AppCompatActivity() {
    private lateinit var iTestAidl: IMyAidlInterface

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //获取到服务端
        val intent = Intent()
        //Android 5.1开始必须显式intent启动service
        intent.component =
            ComponentName("top.xuqingquan.aidltest", "top.xuqingquan.aidltest.ITestAidlService")
        bindService(intent, object : ServiceConnection {
            override fun onServiceDisconnected(p0: ComponentName?) {
                println("onServiceDisconnected")
            }

            override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
                println("onServiceConnected")
                //拿到远程到aidl
                iTestAidl = IMyAidlInterface.Stub.asInterface(p1)
            }
        }, Context.BIND_AUTO_CREATE)
        tv_result.setOnClickListener {
            try {
                val list = iTestAidl.basicTypes(
                    0, 0, 0, false, 0f, 0.0, 'a', "", emptyList(),
                    emptyMap<Any, Any>(), "", User("test", 11)
                )
                tv_result.text = "${list.size}-$list"
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }
    }
}

最后,附上AIDL文档的地址:https://developer.android.google.cn/guide/components/aidl.html

你可能感兴趣的:(Android,随笔)