Android中每个应用程序都有自己进程,对象不允许跨进程内存共享,此时就需要解决进程间数据通讯问题,要实现进程间通信可以使用AIDL实现。
AIDL
一种接口描述语言,IPC机制基于接口,轻量级。使用代理类在客户端和服务端实现数据传递
支持数据类型
- 8种基本类型
- CharSequence
- ArrayList<支持类型>
- Parceable序列化实现类(跨进程本质上也是序列化反序列化过程)
- AIDL接口本身
实现AIDL需做2件事
- 引入AIDL相关类
- 调用AIDL生成的class
1. 绑定服务conn运行在主线程,不能做耗时操作;
2. 客户端调服务端方法耗时需起线程;
3. 服务端的方法运行在服务端的binder线程池无需另起线程
4. 导包,使用的序列化对象必须有同名的.aidl文件。
5. 两种方式:定义接口;序列化对象。定向化tag(in out inout)。
权限验证:服务端Binder的onTranscat中包名验证或权限验证。
死亡回调:正常运行连接断开现象,死亡代理重新绑定或conn断链时重新注册。
实现步骤
- 创建服务端aidl文件,接口定义
- 创建服务端service,实现aidl定义接口,将Binder对象返回(实现aidl.stub)
- 拷贝服务端aidl至客户端,同包名路径
- 绑定服务端service,成功建立连接,拿到binder对象并转为aidl接口类型对象
- 通过对象调用service实现方法
- 使用完后,根据需要解绑
- 通过回调实现双向通信
具体实现
- 以相机数据为例,实现两个进程间通信
服务端
- 创建AIDL相关类
# 接口回调类,回传bitmap图像
package com.dcxing.feature;
interface ICameraCallback {
void updateFrame(in byte[] data);
}
# 交互类,控制相机
package com.dcxing.feature;
import com.dcxing.feature.ICameraCallback;
interface ICameraInterface {
void switchCamera();
void pauseUpdateFrame(boolean pause);
void registerCallback(ICameraCallback callback);
void unRegisterCallback(ICameraCallback callback);
}
# 服务类,提供跨进程通信
class CameraService: Service() {
private lateinit var mCameraManager: CameraManager
private var mCameraCallback: ICameraCallback? = null
override fun onBind(intent: Intent?): IBinder = mService
private val mService: ICameraInterface.Stub = object: ICameraInterface.Stub() {
override fun switchCamera() {
if (::mCameraManager.isInitialized) {
mCameraManager.switchCamera()
}
}
override fun pauseUpdateFrame(pause: Boolean) {
if (::mCameraManager.isInitialized) {
mCameraManager.setPauseCamera(pause)
}
}
override fun registerCallback(callback: ICameraCallback?) {
mCameraCallback = callback
}
override fun unRegisterCallback(callback: ICameraCallback?) {
LogTool.i("release resource")
mCameraCallback = null
}
}
override fun onCreate() {
super.onCreate()
mCameraManager = CameraManager(applicationContext)
mCameraManager.setOnPreviewResultCallBack(object : CameraManager.OnPreviewResultCallBack {
override fun onPreviewResult(bitmap: Bitmap) {
try {
bitmap.toByteArray().let {
mCameraCallback?.updateFrame(it)
} ?: LogTool.i("updateFrame data is null")
} catch (e: RemoteException) {
LogTool.e(e)
}
}
override fun onTakePicture(bitmap: Bitmap) {
}
})
mCameraManager.onResume()
}
override fun onUnbind(intent: Intent?): Boolean {
if (::mCameraManager.isInitialized) {
mCameraManager.onPause()
}
return super.onUnbind(intent)
}
}
客户端
- 绑定AIDL服务通信
class CameraAidlActivity : BaseActivity<ActivityCameraBinding>(),
CameraManager.OnPreviewResultCallBack, CoroutineScope by MainScope() {
companion object {
const val REQUEST_PERMISSION_CAMERA = 112
fun start(context: Context) {
val intent = Intent(context, CameraAidlActivity::class.java)
context.startActivity(intent)
}
}
private var mCameraInterface: ICameraInterface? = null
private val mCameraConn = object: ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mCameraInterface = ICameraInterface.Stub.asInterface(service)
mCameraInterface?.let {
try {
it.registerCallback(object : ICameraCallback.Stub() {
override fun updateFrame(data: ByteArray?) {
LogTool.i("updateFrame data: $data")
data?:return
try {
data.byteArrayToBitmap()?.let {
onPreviewResult(it)
}?: LogTool.w("updateFrame bitmap is null")
} catch (e: RemoteException) {
LogTool.e("updateFrame RemoteException: ${e.message}")
}
}
})
} catch (e: RemoteException) {
LogTool.e("register RemoteException: ${e.message}")
}
}
}
override fun onServiceDisconnected(name: ComponentName?) {
mCameraInterface = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(mBinding.root)
mBinding.switchCamera.setOnClickListener {
mCameraInterface?.switchCamera()
}
mBinding.takeCamera.setOnClickListener {
// val bitmap = mBinding.cameraPreview.toBitmap()
mBinding.takeImageView.setImageBitmap(BitmapTool.viewToBitmap(mBinding.cameraPreview))
}
mBinding.pauseCamera.setOnClickListener {
mCameraInterface?.pauseUpdateFrame(true)
}
mBinding.resumeCamera.setOnClickListener {
mCameraInterface?.pauseUpdateFrame(false)
}
checkAndRequestPermission()
bindCameraService()
}
private fun bindCameraService() {
LogTool.i("bind Service")
val intent = Intent("com.dcxing.feature.ICameraInterface")
intent.setPackage("com.dcxing.x")
bindService(intent, mCameraConn, Context.BIND_AUTO_CREATE)
}
private fun unbindCameraService() {
if (mCameraInterface != null) {
// mCameraInterface?.unRegisterCallback(this)
unbindService(mCameraConn)
mCameraInterface = null
}
}
override fun onDestroy() {
super.onDestroy()
unbindCameraService()
}
private fun checkAndRequestPermission() {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
// 权限未被授予,请求权限
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.CAMERA, Manifest.permission.SYSTEM_ALERT_WINDOW),
REQUEST_PERMISSION_CAMERA)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_PERMISSION_CAMERA -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//同意
} else {
//拒绝
finish()
}
}
}
}
override fun onPreviewResult(bitmap: Bitmap) {
launch {
mBinding.cameraPreview.setImageBitmap(bitmap)
}
}
override fun onTakePicture(bitmap: Bitmap) {
launch{
mBinding.takeImageView.setImageBitmap(bitmap)
}
}
}
报错检查
- 自定义对象实现序列化
- aidl显示导包
- tag使用是否正确
- inout需实现序列化读写方法
- 包名一致