最近项目需求,需要不同进程间进行通信,这才想起来 Android 还有个 AIDL。因为日常开发使用的少,在这里做个笔记方便以后查阅。
一、创建一个 AIDL 文件
创建方式如下图所示:
此时,系统会在 main 内生成一个 aidl 文件夹,与 java 是同级目录。AIDL 文件的具体内容,我仅仅举个例子:
package com.beviswang.datalib;
import com.beviswang.datalib.model.LocationInfo;
interface IAssistDrivingService {
// 获取位置信息
LocationInfo getLocation();
}
二、自定义类型的序列化
除了基本的数据类型和 String 类型以外,还可以传递自定义类型。众所周知,如果需要进行不同进程通信,就需要序列化这些自定义类型。如何序列化?有两种方式:实现 Parcelable 或 Serializable 接口。至于这两种如何选择嘛,请看这篇文章:Android中两种序列化方式的比较Serializable和Parcelable
这里使用 Parcelable 进行序列化,自定义类型具体内容如下:
package com.beviswang.datalib.model
import android.os.Parcel
import android.os.Parcelable
class LocationInfo() :Parcelable {
var longitude:Double = 0.0 // 经度
var latitude:Double = 0.0 // 纬度
var altitude:Double = 0.0 // 海拔高度
var direction:Float = 0f // 方向
var speed:Float = 0f // 速度
var gpsTimeStamp:Long = 0L // GPS 时间戳
var systemTimeStamp:Long = 0L // 系统时间戳
constructor(parcel: Parcel) : this() {
longitude = parcel.readDouble()
latitude = parcel.readDouble()
altitude = parcel.readDouble()
direction = parcel.readFloat()
speed = parcel.readFloat()
gpsTimeStamp = parcel.readLong()
systemTimeStamp = parcel.readLong()
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeDouble(longitude)
parcel.writeDouble(latitude)
parcel.writeDouble(altitude)
parcel.writeFloat(direction)
parcel.writeFloat(speed)
parcel.writeLong(gpsTimeStamp)
parcel.writeLong(systemTimeStamp)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<LocationInfo> {
override fun createFromParcel(parcel: Parcel): LocationInfo {
return LocationInfo(parcel)
}
override fun newArray(size: Int): Array<LocationInfo?> {
return arrayOfNulls(size)
}
}
}
三、根据自定义类型的包位置创建自定义类型的声明
创建文件位置,需要在 AIDL 文件夹下创建与自定义类型相同包名的 AIDL,该 AIDL 就是自定义类型的声明。注意:需要保证 AIDL 的文件名与自定义类型相同,同时需要在主要的 AIDL 文件内容导入该实体类的 AIDL。自定义类型 AIDL 文件内容如下:
package com.beviswang.datalib.model;
parcelable LocationInfo;
四、使用 AIDL
主进程中:
package com.beviswang.mockassistdriving.main
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import com.beviswang.datalib.IAssistDrivingService
import com.beviswang.datalib.model.LocationInfo
import com.beviswang.datalib.service.AssistDrivingService
import com.beviswang.mockassistdriving.BaseActivity
import com.beviswang.mockassistdriving.R
import org.jetbrains.anko.newTask
class MainActivity : BaseActivity() {
private var mIAssistDrivingService: IAssistDrivingService? = null
private var locationInfo: LocationInfo? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bindService(Intent().newTask().setClass(this, AssistDrivingService::class.java),
mServiceConnection, Context.BIND_AUTO_CREATE)
}
override fun onDestroy() {
super.onDestroy()
unbindService(mServiceConnection)
}
private val mServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mIAssistDrivingService = IAssistDrivingService.Stub.asInterface(service)
locationInfo = mIAssistDrivingService?.location
}
override fun onServiceDisconnected(name: ComponentName?) {
mIAssistDrivingService = null
}
}
}
其它进程:
package com.beviswang.datalib.service
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.beviswang.datalib.IAssistDrivingService
import com.beviswang.datalib.model.LocationInfo
class AssistDrivingService:Service() {
override fun onBind(intent: Intent?): IBinder {
return mIBinder
}
private val mIBinder = object : IAssistDrivingService.Stub(){
override fun getLocation(): LocationInfo {
return LocationInfo()
}
}
}
以上就是 AIDL 的简单使用方法,需要了解其结构请参阅:Android中AIDL的工作原理