minicap 是开源项目 STF 中的高速截图工具。STF 利用此工具不断的传输图片信息并在 web 端绘制实现 Real-time screen view。
minicap 的使用有很强的针对性,针对不同架构的 CPU 和 SDK 制作了不同的 "minicap" 和 "minicap.so" 文件。
获取 CPU 版本
$ABI=adb shell getprop ro.product.cpu.abi
获取 SDK 版本
$SDK=adb shell getprop ro.build.version.sdk
push 文件(红色字体为 minicap 项目路径,具体依个人情况而定)
adb push libs/$ABI/minicap /data/local/tmp/
adb push jni/minicap-shared/aosp/libs/android-$SDK/$ABI/minicap.so /data/local/tmp/
检查 minicap 是否可用
adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1080x1920@1080x1920/0 -t
若在结果中包含 "OK" 字样则表示可用
-P 后面的参数格式:{RealWidth}x{RealHeight}@{VirtualWidth}x{VirtualHeight}/{Orientation}
Orientation 可以理解为手机的旋转角度,可选参数为 0 | 90 | 180 | 270
如何获取 Orientation
adb shell dumpsys display
(win 下 grep 更换为 findstr)获取分辨率 和 rotation 方向(adb 一般获取到为 0 or 1)(同学们自己动手做一次文件差异对比就知道用什么参数了)启动 adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1080x1920@1080x1920/0
此时相当于启动了一个 socket 服务端。然后设置下访问端口adb forward tcp:1313 localabstract:minicap
(其意思是将 pc 上的端口 1313 重定向至手机上的 minicap)然后就可以通过 1313 端口来获取 minicap 不断发出来的信息了。
minicap 会不断的返回很多二进制信息,这些二进制信息代表什么意思?
其返回的信息可以分为两类Global header binary format 和 Frame binary format(以下简称为 Banner 和 Frame), 其数据格式如下:
每次客户端连接 minicap 服务时,最先收到的24字节为 Banner 数据段(该数据段只会在最开始发送一次)。 然后接收到的数据可视为 N个Frame 数据段,Frame数据的前4个字节为 Frame 中 JPG 数据的长度,其后为JPG内容数据。
(注:官方示例的数据处理方法是建立在收到的二进制数据以 16 进制形式表现的情况下)
根据使用者解析语言不同还需要注意大小端存储的问题
数据解析思路:
tempdata //保存还没有被处理的数据 framehead //保存fram的前4个字节 framejpg //保存frame中jpg数据 jpglength //JPG数据长度 for { minicapread(data) } function minicapread(data) { data = append(tempdata,data) // ------------Banner start------------ if banner not ok{ if data length >= 24{ getBanner(data) data = data - Banner // 减去banner长度余下的数据 }else{ tempdata = data return } } // ------------Banner end------------ // ------------JPG length start------------ if framhead length < 4{ if data length >= (framehead length - 4) { framehead = getHead(data) jpglength = getJpgLength(framhead) data = data - framehead }else{ framehead = append(framehead,data) return } } // ------------JPG length end------------ // ------------JPG start------------ if framejpg length < jpglength{ if data length >= (jpglength - framejpg length){ framjpg = getJpg(data) data = data - framejpg }else{ framejpg = append(framejpg,data) return } } // ------------JPG end------------ tempdata = append(tempdata,data) }
假设分辨率为 1080x1920, 以 左上角为 0,0 坐标
当屏幕为竖屏显示时以 Orientation=0 启动 minicap 服务,此时我们会得到正常的宽高为 1080x1920 的截图。
若翻转手机为横屏显示数据时,依然得到宽高为 1080x1920 的截图且高度在 1080 以上时的部分为黑色填充。只有关闭 minicap 以 Orientation=90 重新启动,可以获取到宽高为 1920x1080 的正常截图。
也就是说想要实时正确获取屏幕显示,要监控屏幕方向,并以新的方向重启 minicap 服务。(可查看 STF 的输出日志)