文章目录
背景
2024年第一篇博客,希望所有看到这篇博客的同学都能财务自由,早日退休!
跨进程渲染就是在服务端进程渲染,在客户端进程显示。在一些 3d 的应用场景,当多个应用需要显示时,就可以使用跨进程渲染,这样做的好处就是,客户端进程比较轻量,无需每个客户端都引入 3d 引擎,减少包大小,减少内存占用。
实现步骤
Android 里面的跨进程渲染主要是通过 Surfaceview 和 SurfaceControlViewHost 来实现的,主要的流程如下
需要通过跨进程通信的方式传递hosttoken,displayid和surfacePackge,以此来实现客户端进程的 SurfaceView 和 服务端进程的 SufaceControlViewHost 的互相绑定,绑定成功之后就可以开始渲染了。
服务端
以下是服务端的代码示例,服务端收到客户端传递过来的 displayId,hostToken,width 和 height 之后,创建 SurfaceControlViewHost,然后创建一个 view 给到 SurfaceControlViewHost ,接着将 surfacePackage 传递给客户端。
kotlin
if (msg.what == MSG_SURFACE_DISPLAY){
val bundle = msg.data
val displayId = bundle.getInt("displayId")
val width = bundle.getInt("width")
val height = bundle.getInt("height")
val hostToken = bundle.getBinder("hostToken")
val display = getSystemService(DisplayManager::class.java)!!.getDisplay(displayId)
val surfaceControlViewHost = SurfaceControlViewHost(this@HostService,display,hostToken)
val root_view = LayoutInflater.from(this@HostService).inflate(R.layout.show_layout,null)
surfaceControlViewHost.setView(root_view, width, height)
msg.replyTo.send(obtainSurfacePkg(surfaceControlViewHost.surfacePackage!!))
}
客户端
客户端创建 SurfaceView 之后,将相关的参数传递给服务端
kotlin
bindService(intent, object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.i(TAG, "service connected")
handler.post {
remoteMessenger = Messenger(service)
val msg = obtainSurfaceDisplay(
surfaceview.hostToken,
surfaceview.display.displayId,
surfaceview.width,
surfaceview.height
)
msg?.replyTo = handleMessenger
remoteMessenger?.send(msg)
}
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.i(TAG, "service disconnected")
}
}, Context.BIND_AUTO_CREATE)
收到服务端返回的 surfacePackage 之后,绑定到 SurfaceView。
kotlin
if (msg.what == MSG_SURFACE_PACKAGE) {
val data = msg.data
val surfacePackage: SurfacePackage = data.getParcelable("surfacePkg")!!
surfaceview.setChildSurfacePackage(surfacePackage)
}
运行结果:
其中测试按钮以及图标均未服务端进程渲染出来的。