是否可以从adb shell命令读取二进制stdout?例如,如何使用screencap的所有示例包括两个步骤:
adb shell screencap -p /sdcard/foo.png
adb pull /sdcard/foo.png
Run Code Online (Sandbox Code Playgroud)
但是,该服务支持写入stdout.例如,您可以执行以下操作:
adb shell "screencap -p > /sdcard/foo2.png"
adb pull /sdcard/foo2.png
Run Code Online (Sandbox Code Playgroud)
这同样有效.但是,如何阅读亚行的产出呢?我想做的是以下内容:
adb shell screencap -p > foo3.png
Run Code Online (Sandbox Code Playgroud)
并避免中间写入SD卡.这会生成看起来像PNG文件的strings foo3.png东西(正在运行生成带有IHDR,IEND等的东西)并且大小大致相同,但就图像阅读器而言,文件已损坏.
我也尝试在java中使用ddmlib来做到这一点,结果是一样的.我很乐意使用任何必要的图书馆.我的目标是减少获取捕获的总时间.在我的设备上,使用双命令解决方案,获取图像大约需要3秒钟.使用ddmlib和捕获stdout需要不到900毫秒,但它不起作用!
是否有可能做到这一点?
编辑:这是两个文件的hexdump.第一个,screen.png来自stdout并且已损坏.第二个,xscreen来自双命令解决方案并且有效.图像应在视觉上相同.
$ hexdump -C screen.png | head
00000000 89 50 4e 47 0d 0d 0a 1a 0d 0a 00 00 00 0d 49 48 |.PNG..........IH|
00000010 44 52 00 00 02 d0 00 00 05 00 08 06 00 00 00 6e |DR.............n|
00000020 ce 65 3d 00 00 00 04 73 42 49 54 08 08 08 08 7c |.e=....sBIT....||
00000030 08 64 88 00 00 20 00 49 44 41 54 78 9c ec bd 79 |.d... .IDATx...y|
00000040 9c 1d 55 9d f7 ff 3e 55 75 f7 de b7 74 77 d2 d9 |..U...>Uu...tw..|
00000050 bb b3 27 10 48 42 16 c0 20 01 86 5d 14 04 11 dc |..'.HB.. ..]....|
00000060 78 44 9d c7 d1 d1 11 78 70 7e 23 33 8e 1b 38 33 |xD.....xp~#3..83|
00000070 ea 2c 8c 8e 0d 0a 08 a8 23 2a 0e 10 82 ac c1 40 |.,......#*.....@|
00000080 12 02 81 24 64 ef ec 5b ef fb 5d 6b 3b bf 3f ea |...$d..[..]k;.?.|
00000090 de db dd 49 27 e9 ee 74 77 3a e3 79 bf 5e 37 e7 |...I'..tw:.y.^7.|
$ hexdump -C xscreen.png | head
00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR|
00000010 00 00 02 d0 00 00 05 00 08 06 00 00 00 6e ce 65 |.............n.e|
00000020 3d 00 00 00 04 73 42 49 54 08 08 08 08 7c 08 64 |=....sBIT....|.d|
00000030 88 00 00 20 00 49 44 41 54 78 9c ec 9d 77 98 1c |... .IDATx...w..|
00000040 c5 99 ff 3f d5 dd 93 37 27 69 57 5a e5 55 4e 08 |...?...7'iWZ.UN.|
00000050 24 a1 00 58 18 04 26 08 8c 01 83 31 38 c0 19 9f |$..X..&....18...|
00000060 ef 7c c6 3e 1f 70 f8 7e 67 ee 71 e2 b0 ef ce f6 |.|.>.p.~g.q.....|
00000070 f9 ec 73 04 1b 1c 31 60 23 84 30 22 88 a0 40 10 |..s...1`#.0"..@.|
00000080 08 65 69 95 d3 4a 9b c3 c4 4e f5 fb a3 67 66 77 |.ei..J...N...gfw|
00000090 a5 95 b4 bb da a4 73 7d 9e 67 55 f3 ed 50 5d dd |......s}.gU..P].|
Run Code Online (Sandbox Code Playgroud)
只需快速浏览一下就可以添加几个额外的0x0d(13)字节.回车?这会敲响任何铃声吗?它是否混合在一些空白行中?
Aje*_*t47 85
与命令不同adb shell,adb exec-out不使用pty哪个修改二进制输出.所以你可以做到
adb exec-out screencap -p > test.png
Run Code Online (Sandbox Code Playgroud)
https://android.googlesource.com/platform/system/core/+/5d9d434efadf1c535c7fea634d5306e18c68ef1f
请注意,如果您将此技术用于在STDERR上生成输出的命令,则应将其重定向到/dev/null,否则adb将在其STDOUT中包含STDERR,从而破坏输出.例如,如果您尝试备份和压缩目录:
adb exec-out "tar -zcf - /system 2>/dev/null" > system.tar.gz
Run Code Online (Sandbox Code Playgroud)
Tom*_*mas 48
很抱歉发布一个旧问题的答案,但我自己只是遇到了这个问题,并希望只通过shell来完成.这对我很有用:
adb shell screencap -p | sed 's/^M$//' > screenshot.png
Run Code Online (Sandbox Code Playgroud)
这^M是我通过按ctrl + v - > ctrl + m得到的一个字符,只是注意到它在复制粘贴时不起作用.
adb shell screencap -p | sed 's/\r$//' > screenshot.png
Run Code Online (Sandbox Code Playgroud)
也为我做了伎俩.
fad*_*den 13
如上所述,"adb shell"正在执行换行(0x0a)到回车+换行(0x0d 0x0a)转换.这是由伪tty线路规则执行的.由于shell没有"stty"命令,因此没有简单的方法来处理终端设置.
这是可能做到你想要什么ddmlib.您需要编写在设备上执行命令的代码,捕获输出并通过线路发送.这或多或少是DDMS对某些功能的作用.这可能比它的价值更麻烦.
该repair()解决方案-将所有CRLF到LF -感觉摇摇欲坠,但实际上是可靠的,因为"腐败" LF到CRLF的转换是确定性的.我曾经做过同样的事情来修复无意的ASCII模式FTP传输.
值得注意的是,PNG文件格式是明确设计用于捕获这个(和相关的)问题.神奇的数字从0x89开始,以捕获任何剥离高位的内容,然后是"PNG",这样您就可以轻松地告诉文件中的内容,然后使用CR LF来捕获各种ASCII行转换器,然后使用0x1a来捕获旧的MS-DOS程序使用Ctrl-Z作为特殊的文件结束标记,然后使用单独的LF.通过查看文件的前几个字节,您可以准确地告诉它对它做了什么.
...这意味着您的repair()函数可以接受"损坏"和"纯粹"输入,并可靠地确定它是否需要执行任何操作.
编辑:另外一个注意事项:设备端二进制文件可以配置tty以避免转换,使用cfmakeraw().请参阅Android 5.0中screenrecord命令中的prepareRawOutput()函数,该函数可以通过ADB shell连接从实时屏幕捕获发送原始视频.
Ale*_* P. 10
最好的解决方案是使用adb exec-out像@AjeetKhadke建议的命令.
让我说明adb shell和adb exec-out输出之间的区别:
~$ adb shell "echo -n '\x0a'" | xxd -g1
00000000: 0d 0a
~$ adb exec-out "echo -n '\x0a'" | xxd -g1
00000000: 0a
Run Code Online (Sandbox Code Playgroud)
它的工作原理在Windows中(我用hexdump的的GnuWin32 Hextools用于演示),以及:
C:\>adb shell "echo -n '\x0a'" | hexdump
00000000: 0D 0A
C:\>adb exec-out "echo -n '\x0a'" | hexdump
00000000: 0A
Run Code Online (Sandbox Code Playgroud)
缺点是,为了能够从使用adb exec-out命令中受益,设备和主机PC都必须支持adb shellV2协议.
照顾PC端是相当简单的 - 只需将platform-tools包(包含adb二进制文件)更新到最新版本即可.adbd设备上的守护程序版本链接到Android版本.的adb shellV2协议已在的Android 5.0与完整一起被引入adb大修(从去c到C++代码).但是有一些回归(又称错误),因此adb exec-outAndroid 5.x的实用性仍然有限.最后,不支持Android 4.x和旧设备.幸运的是,那些仍在用于开发的旧设备的份额正在快速下降.
深入挖掘十六进制转储后,很明显每次发出字符0x0A时,shell都会发出0x0D 0x0A.我使用以下代码修复了流,现在二进制数据是正确的.当然,现在问题是为什么adb shell这样做呢?但无论如何,这解决了这个问题.
static byte[] repair(byte[] encoded) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i=0; i<encoded.length; i++) {
if (encoded.length > i+1 && encoded[i] == 0x0d && encoded[i+1] == 0x0a) {
baos.write(0x0a);
i++;
} else {
baos.write(encoded[i]);
}
}
try {
baos.close();
} catch (IOException ioe) {
}
return baos.toByteArray();
}
Run Code Online (Sandbox Code Playgroud)
编辑:我明白为什么要这样做.它将LF转换为CR/LF,就像老式DOS一样.我想知道是否有某个地方可以关闭它?
是的,在Unix / Linux / Mac OS X上,可以通过在前面加上“ stty -onlcr;”来接收adb shell的二进制输出。你的指挥( NO ~~需要一个根深蒂固的Android)。
1. 下载“ stty”可执行文件。
http://www.busybox.net/downloads/binaries/latest/
对于旧版android,请使用busybox-armv5l,其他则使用busybox-armv7l。
将文件重命名为“ stty”
2. 将“ stty”文件上传到android并设置适当的权限。
adb push somelocaldir/stty /data/local/tmp/
adb shell chmod 777 /data/local/tmp/stty
Run Code Online (Sandbox Code Playgroud)
3. 加上“ stty -onlcr;” 像这样命令
adb shell /data/local/tmp/stty -onlcr\; screencap -p > somelocaldir/output.png
or:
adb shell "/data/local/tmp/stty -onlcr; screencap -p" > somelocaldir/output.png
or (Only for Windows):
adb shell /data/local/tmp/stty -onlcr; screencap -p > somelocaldir/output.png
Run Code Online (Sandbox Code Playgroud)
做完了!
但对于Windows OS,默认情况下,来自Android的LF将转换为CR CR LF。
即使您执行了上述步骤,您仍然可以获得CR LF。
这“似乎”是因为本地adb.exe使用fwrite导致CR被前置。
除了在Windows OS上手动将CR LF转换为LF之外,我没有其他办法。
这是适用于任何地方(包括 Linux 和 Windows)的解决方案。
您将需要netcat实用程序,通常名为nc.
如果 和nc都busybox nc在您的设备上失败,您需要新鲜的busybox. 您可以使用Play Market中的busybox安装程序(需要root),或使用osexp2003的解决方案(从官方网站下载busybox ,将其放入/data/local/tmp/设备并添加执行权限)。
这个想法是用作netcat原始 HTTP 服务器。
好吧,事实上甚至不是一个合适的服务器。它只会发送其输入作为对任何TCP 连接的响应(无论是来自浏览器的 HTTP 请求、telnet 连接还是只是netcat)并终止。
运行您想要从中获取输出的命令,如下所示:
adb shell 'screencap -p | busybox nc -p 8080 -l >/dev/null'
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,screencap -p获取屏幕截图(PNG 图像)并将其通过管道传输到netcat.
-l告诉它netcat充当服务器(监听连接),并-p 8080告诉它使用 TCP 端口 8080。省略>/dev/null将简单地打印例如传入的 HTTP GET 请求到您的终端。
上面的示例将等待某人连接、发送屏幕截图,然后才终止。
当然,您可以在没有 的情况下运行它adb shell,例如从设备上的终端模拟器。
按上述方式运行命令后,您可以通过在浏览器中打开或通过任何其他方式从手机下载其输出http://ip.of.your.phone:8080,例如使用netcat:
busybox nc ip.of.your.phone:8080 >screenshot.png
Run Code Online (Sandbox Code Playgroud)
如果你想使用USB线下载,你需要使用ADB转发连接,如下所示:
adb forward tcp:7080 tcp:8080
Run Code Online (Sandbox Code Playgroud)
之后您可以使用localhost:7080代替ip.of.your.phone:8080.
您可以使用以下命令删除此转发:
adb forward --remove tcp:7080
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27692 次 |
| 最近记录: |