Android进程间通信之AIDL(二)

232 阅读3分钟

Android中每个应用程序都有自己进程,对象不允许跨进程内存共享,此时就需要解决进程间数据通讯问题,要实现进程间通信可以使用AIDL实现。

AIDL

一种接口描述语言,IPC机制基于接口,轻量级。使用代理类在客户端和服务端实现数据传递

支持数据类型

  • 8种基本类型
  • CharSequence
  • ArrayList<支持类型>
  • Parceable序列化实现类(跨进程本质上也是序列化反序列化过程)
  • AIDL接口本身

实现AIDL需做2件事

  1. 引入AIDL相关类
  2. 调用AIDL生成的class
1. 绑定服务conn运行在主线程,不能做耗时操作;
2. 客户端调服务端方法耗时需起线程;
3. 服务端的方法运行在服务端的binder线程池无需另起线程
4. 导包,使用的序列化对象必须有同名的.aidl文件。
5. 两种方式:定义接口;序列化对象。定向化tag(in out inout)。
权限验证:服务端Binder的onTranscat中包名验证或权限验证。
死亡回调:正常运行连接断开现象,死亡代理重新绑定或conn断链时重新注册。

实现步骤

  1. 创建服务端aidl文件,接口定义
  2. 创建服务端service,实现aidl定义接口,将Binder对象返回(实现aidl.stub)
  3. 拷贝服务端aidl至客户端,同包名路径
  4. 绑定服务端service,成功建立连接,拿到binder对象并转为aidl接口类型对象
  5. 通过对象调用service实现方法
  6. 使用完后,根据需要解绑
  7. 通过回调实现双向通信

具体实现

  • 以相机数据为例,实现两个进程间通信

服务端

  • 创建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)
        }
    }
}

报错检查

  1. 自定义对象实现序列化
  2. aidl显示导包
  3. tag使用是否正确
  4. inout需实现序列化读写方法
  5. 包名一致