java 控制 区域投屏,Scrcpy投屏原理浅析-设备控制篇

起初我真的想过自己单独写一套来着,后来发现时间真的不够,所以有了对scrcpy源码的浅析,服务端我就用scrcpy现有的了,客户端scrcpy采用ffmpeg+sdl2.0进行了跨平台的播放,我准备用Flutter重构客户端部分

Scrcpy与vysor是都是投屏中比较优秀的项目了,非侵入性,不需要设备单独安装软件来配合,能低延迟的控制,较高的fps等等,scrcpy的star更是到了2.6w

scrcpy启动阶段

它到底是怎么做到执行scrcpy命令,在较短的时间内就立马获取到了安卓设备的屏幕的?并没有向设备申请任何的获取屏幕的权限,并且还能对设备进行较低延迟的控制。 有过使用adb经验的开发者,当PC端调试安卓设备时 我们可以输入

adb shell /system/bin/screencap -p PATH

复制代码

就能直接截取手机屏幕,去掉-p这个开关,更改成>,就可以直接截图并重定向到电脑本地,包括使用screenrecorder命令对手机进行录屏。

以上两个操作明明是会用到截取手机屏幕权限的,但是为什么没有向用户申请就能获取到屏幕?

在scrcpy的wiki中也其实提到了,原因就是adb shell的权限是非常高的,去设备的/system/app/shell也能看到shell.apk的uid与gid都是shell,这就可以直接拿到屏幕截取的权限 就好像uid与gid都为root的su命令,可以拿到一切权限一样的。

所以在scrcpy启动时,将自身sdk中的一个jar上传到了安卓设备上,这个jar并不是java的.class文件,是class java字节码经过dx工具转换成了dex文件,所以这个jar解压后就有一个dex,这个是安卓上的字节码,可以直接运行的。

push jar到手机

adb push $sdk/scrcpy-server.jar /data/local/tmp

复制代码

再利用安卓的app_process,直接启动这个jar,不仅是app_process,dalvikvm理论也是能启动的 命令如下

CLASSPATH=/data/local/tmp/scrcpy-server.jar app_process ./ com.genymobile.scrcpy.Server 1.12.1 0 8000000 0 true - true true

复制代码

这样就会 后面的那堆参数是我从源码抠出来的默认参数,也是单独执行scrcpy会跟的参数,这些参数就会由com.genymobile.scrcpy.Server类的main函数接收到 main函数收到参数遍会开启两个socket等待客户端来连接本设备,一个是视频流的socket,一个是设备控制的socket

这个socket为什么能被pc端连接到?

由于adb提供了端口转发的功能,能转发设备本地的端口到pc端,pc端就能跟这个转发的端口进行连接并收发数据。 需要android版本大于5.0 转发端口:

adb forward tcp:5005 localabstract:scrcpy

#PC上所有5005端口通信数据将被重定向到手机端UNIX类型localabstract上

复制代码

上面部分也是所有这类投屏软件的原理,包括vysor

scr

你可能感兴趣的:(java,控制,区域投屏)