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 的输出日志)
