实现MIUI+的多任务投屏

前言

MIUI+ 是小米出的解决生态鸿沟的 PC 与小米手机
MIUI+ 刚出来的时候,我觉得其大致原理和 Scrcpy 差不多,无非是将类似于 scrcpy-server 的东西集成到了 MIUI 系统内,投屏万变不离其宗,录屏,推流,客户端拉流,渲染,处理指针数据,但是在自己体验的时候发现,延迟真的高!,不对,是有一些新的玩意,当时也觉得挺黑科技的,阴差阳错直到最近才了解其中的原理。

偶然翻 scrcpy 的 issue 和刷酷安发现的

先来看下效果,可以同时开三个窗口投屏,并且互不影响,当场冷静分析了一波,没琢磨明白
直到看到这个 issue 和这个视频。
脑子只有一个念头:写!!!
准备给自己的一个个人app,无界投屏,加上这个功能。

然后近期B站出现很多的,华为啥分布啥流转,我姑且不讨论它的原理,但本文的方案同样能做到。

思路分析

简单概括一下视频的内容,up 主用一个截屏软件创建了一个截屏,然后配合 scrcpy 和 am stack list ,am display move-stack,这几个命令,也实现了 MIUI+ 一样的功能。
怎么把这系列操作更优雅的实现起来呢?

录屏截屏的时候干了什么?

把Up的app下载了下来,点击录屏。
然后通过adb查看,多了一个虚拟显示器,这个时候已经能通过 scrcpy –display x来投屏了,不过画面是纯黑的,再模仿视频的操作,也能实现相同的效果,咱怎么把这个功能更优雅的实现呢?
去狂补了一波安卓截屏,录屏,等一系列的知识。一系列文章,中间躺了一些坑,翻出大佬的联系方式交流一波。
录屏方案的区别是通过 MediaCodec 获取 Surface 还是通过获得 Surface 的区别,相同的一点是它们都会
创建虚拟显示器

万幸,博主用的那个 app 是开源的。的确是 tag 没给对,我以为这个 tag 有的功能越多越好,结果把能给的都给了,最后看源码发现其中有的是冲突的,只能生效其中一个。

尝试创建虚拟显示器

我想通过 ADB -> PUSH DEX -> dex创建虚拟显示器来
实现无任何侵入性(表面上无侵入性)实现多任务投屏,最后还是失败了。
安卓创建 VirtualDisplay 有两种方式,一种是用 DisplayManager,一种用 MediaProjection,而 MediaProjection 会申请权限,最后会从 activity 的 onResult 中回调,也就是说,整个过程,依赖 app的运行,于是我再次尝试用 VirtualDisplay。
1.adb push dex
2.dex 使用 DisplayManager 创建虚拟显示器
最后还是由失败告终,奈何绕不过安卓权限的管理,

MIUI+ 也完全得益于 Rom的 的支持,当时心里一个念头,我做ROM这些功能也许能做得更好。
原因如下:
adb的权限取决与安卓的一个叫做 shell.apk 的系统 app,可以轻松的反编译查看它的 ManiFest,是并没有屏幕录制的权限的,所以最后用 adb shell 启动的app_process也是没有这个权限的,反射出对象实例也没用。
具体方案如下:
由于我想靠 dex 来完成这整个流程,并且这个dex 是独立运行的,不依赖 app,而 DisplayManager 是一个services,是由工厂函数得到的,那么不依赖 app 的 dex 只有靠反射来得到对象。
这一系列的方案 scrcpy 已经有现成的了。

反射拿对象

没问题

创建虚拟显示器

后来看到了 scrcpy 的这个 issue,才恍然大悟
shell.apk
所以这条路是走不通了,不过尝试的过程中总结了不少东西,单独的dex也可以干很多事,包括学习 scrcpy wrappers 通过反射实现不依赖 Context 和 activity 拿各种对象实例。

创建虚拟显示器最终实现

最后只能依赖一个 app 了,但这终将成为用户排斥的一点,“人家鸿蒙就没弹窗要权限,为什么你的还弹窗要权限”。
把这个能力集成到无界投屏安卓端。
首先看下如何创建一个能让 scrcpy 渲染的虚拟显示器。
除了关键的 creat函数,我们还有必要的步骤如下
这段代码抄过去,你也能拥有一个虚拟显示器🧐

创建时机控制

首先这个虚拟显示器的创建时机是在控制端,也就是说装上 app 等待控制的那端,不需要主动创建,不然还得用户点击按钮创建。
用一个简单的广播来实现,控制端需要被控端创建的时候,利用adb发起广播,用户再点击确认授权,即可完成创建,

这个确认是绕不开了
上图!
并且最后实现的方案不用限制窗口。
不仅如此,由于无界投屏起初的设计,就是支持安卓to安卓的,所以还可以实现以下效果。
app 运行了,但没完全运行,跑另外的手机上去了。

最后

我觉得无论是华为的碰一碰投屏,小米的MIUI+,并不能成为“生态鸿沟解决方案”,只是为了打造各自的生态链而出的必要产物,因为用户不能用小米手机投华为电脑,不能用华为手机碰一碰投小米电脑,也不能小米手机投华为手机,所以便有了无界投屏的诞生。
无界投屏是一年前我开始移植 scrcpy 到安卓的成果,其中客户端的 C 语言代码移植到安卓花了不少时间,主要是依赖 ffmpeg 解码以及 sdl2 进行视频渲染,而无界投屏在 PC 端也作为一个 GUI,上架半年没太多时间维护,目前也只有部分用户,PC端也有很多工作量,我甚至会因为一个 case 来回切换 Windows/macOS/Linux系统多次,并且最后要以一套代码兼容各个平台,都是需要做相关处理的。
这个项目不开源喔,但是可供免费使用。
官网!
参考文献

芜湖

作者

梦魇兽

发布于

2021-10-22

更新于

2023-03-11

许可协议

评论