¿Leer datos estándar binarios como datos de captura de pantalla de adb shell?

10 minutos de lectura

avatar de usuario
eric lange

¿Es posible leer la salida estándar binaria desde un comando de shell adb? Por ejemplo, todos los ejemplos de cómo usar capturas de pantalla incluyen dos pasos:

adb shell screencap -p /sdcard/foo.png
adb pull /sdcard/foo.png

Sin embargo, el servicio admite escribir en stdout. Por ejemplo, puede hacer lo siguiente:

adb shell "screencap -p > /sdcard/foo2.png"
adb pull /sdcard/foo2.png

Y esto funciona igual de bien. Pero, ¿qué pasa con la lectura de la salida a través de ADB? Lo que quiero hacer es lo siguiente:

adb shell screencap -p > foo3.png

Y evita la escritura intermedia en la tarjeta SD. Esto genera algo que aspecto como un archivo PNG (ejecutando strings foo3.png genera algo con un IHDR, IEND, etc.) y tiene aproximadamente el mismo tamaño, pero el archivo está dañado en lo que respecta a los lectores de imágenes.

También intenté hacer esto usando ddmlib en java y los resultados son los mismos. Estaría feliz de usar cualquier biblioteca necesaria. Mi objetivo es reducir el tiempo total para conseguir la captura. En mi dispositivo, usando la solución de dos comandos, se tarda unos 3 segundos en obtener la imagen. Usar ddmlib y capturar stdout lleva menos de 900 ms, ¡pero no funciona!

¿Es posible hacer esto?

EDITAR: Aquí está el volcado hexadecimal de dos archivos. El primero, screen.png vino de stdout y está dañado. El segundo, xscreen es de la solución de dos comandos y funciona. Las imágenes deben ser visualmente idénticas.

$ 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].|

A primera vista, parece que se agregan un par de bytes 0x0d (13) adicionales. Retorno de carro?? ¿Eso te suena de algo? ¿Se está mezclando en algunas líneas en blanco?

  • Supongo que está combinando la salida estándar del programa con la salida estándar del comando. No estoy configurado para probar esto yo mismo, pero ¿ha mirado el archivo que crea en detalle? Si lo abre en un editor de texto, es posible que vea una cadena incorrecta que puede eliminar. Y al menos puedes compararlo con la versión correcta para ver cuál es la diferencia.

    – espátulamanía

    27 de noviembre de 2012 a las 6:27

  • Actualicé mi pregunta para agregar hexdumps de los dos archivos. No veo que se mezclen cadenas extrañas, pero sí parece que se mezclan bytes aleatorios.

    –Eric Lange

    27 de noviembre de 2012 a las 6:48

  • No me sorprendería en absoluto si obtienes un par de créditos adicionales allí. Probablemente puede ejecutar simplemente “adb shell screencap -p” y ver cuál es el resultado. Recuerde que no está canalizando la salida de screencap -p a través de adb sino la salida de adb shell.

    – espátulamanía

    27 de noviembre de 2012 a las 6:53

  • Utilicé un editor hexadecimal para borrar los dos crs descarriados obvios e intenté ver la imagen nuevamente. Esta vez, Preview lo reconoció como PNG (no lo era antes), pero la imagen estaba en blanco. Imagemagick aún afirma que está corrupto, por lo que puede haber más basura allí. Suspiro.

    –Eric Lange

    27 de noviembre de 2012 a las 7:04

  • así: adb shell screencap -p | perl -pe ‘s/\x0D\x0A/\x0A/g’ > pantalla.png

    – Thiago

    27 de diciembre de 2017 a las 8:32

avatar de usuario
desvanecerse

Como se señaló, “adb shell” está realizando una conversión de salto de línea (0x0a) a retorno de carro + salto de línea (0x0d 0x0a). Esto lo está realizando la disciplina de línea pseudo-tty. Como no hay un comando “stty” disponible para el shell, no hay una manera fácil de alterar la configuración del terminal.

Es posible para hacer lo que quieras con ddmlib. Necesitaría escribir código que ejecutara comandos en el dispositivo, capturara la salida y la enviara por cable. Esto es más o menos lo que hace DDMS para ciertas funciones. Esto puede ser más problemático que su valor.

Él repair() La solución, convertir todo CRLF a LF, se siente inestable pero en realidad es confiable ya que la conversión LF a CRLF “corrupta” es determinista. Solía ​​hacer lo mismo para reparar transferencias FTP inadvertidas en modo ASCII.

Vale la pena señalar que el formato de archivo PNG está diseñado explícitamente para detectar exactamente este (y otros problemas relacionados). El número mágico comienza con 0x89 para atrapar cualquier cosa que elimine bits altos, seguido de “PNG” para que pueda saber fácilmente qué hay en el archivo, seguido de CR LF para atrapar varios convertidores de línea ASCII, luego 0x1a para atrapar viejos programas MS-DOS que usó Ctrl-Z como un marcador especial de fin de archivo, y luego un LF solitario. Al mirar los primeros bytes del archivo, puede saber exactamente qué se hizo con él.

… lo que significa que su repair() La función puede aceptar entradas “corruptas” y “puras”, y determinar de manera confiable si necesita hacer algo.

Editar: una nota adicional: es posible que el binario del lado del dispositivo configure el tty para evitar la conversión, usando cfmakeraw(). Ver el prepareRawOutput() función en el Registro de pantalla comando en Android 5.0, que puede enviar video sin procesar desde la captura de pantalla en vivo a través de la conexión de shell ADB.

  • Sí el repair() solución es sólida debido al determinismo. Lo optimicé un poco para reducir la cantidad de llamadas de escritura al flujo de salida y ahora no hay un aumento perceptible en el tiempo de procesamiento. Funciona genial. ¡Gracias!

    –Eric Lange

    28 de noviembre de 2012 a las 0:30


  • Re: “la conversión ‘corrupta’ de LF a CRLF es determinista”: ¿Pero es reversible? Si CRLF y LF se convierten a CRLF, entonces convertir CRLF nuevamente a LF es no 100% fiable, ya que se mezclará con los casos en los que el CRLF original era correcto.

    – ruakh

    27 de septiembre de 2013 a las 1:17


  • En este caso, CRLF se convierte en CRCRLF. Si CRLF se pasara sin modificar, entonces no sería reversible.

    – desvanecerse

    27 de septiembre de 2013 a las 4:41

  • Es bueno ver el motivo de ese comando sed explicado aquí. Me sorprendió ver que la gente no clamaba por saber por qué el sed era necesario en primer lugar.

    – Abraham Felipe

    16 de marzo de 2017 a las 14:14

avatar de usuario
sebastien247

Este comando funcionó para mí en Sistema operativo Windows:

adb exec-out screencap -p > test.png && dos2unix.exe -f test.png

Pero quieres usar esto:
https://sourceforge.net/projects/dos2unix/

  • adb exec-out funciona bien en Windows sin necesidad dos2unix. entonces tu respuesta es redundante

    – Álex P.

    9 de julio de 2017 a las 20:32

  • Sí, pero extrañamente solo exec-out no funciona en mi computadora.

    – Sebastián247

    20 de julio de 2017 a las 10:06

  • Prueba con adb de lo último platform-tools versión. Si no funciona, significa que su teléfono no admite el comando correctamente.

    – Álex P.

    21 de julio de 2017 a las 17:20


  • funciona para mí, pero solo cuando uso dos2unix dos veces, porque no tengo exec-out. adb shell screencap -p | dos2unix -f | dos2unix -f > Screencap.png Gracias por el tipp con dos2unix

    – Radón8472

    7 sep 2021 a las 12:48


La mejor solución es usar adb exec-out comando como sugirió @AjeetKhadke.

Permítanme ilustrar la diferencia entre adb shell y adb exec-out producción:

~$ adb shell "echo -n '\x0a'" | xxd -g1
00000000: 0d 0a

~$ adb exec-out "echo -n '\x0a'" | xxd -g1
00000000: 0a

Funciona en Windows (estoy usando hexdump desde Herramientas hexadecimales de GNUWin32 para la demostración) también:

C:\>adb shell "echo -n '\x0a'" | hexdump
00000000: 0D 0A

C:\>adb exec-out "echo -n '\x0a'" | hexdump
00000000: 0A

La desventaja es que para poder beneficiarse del uso de la adb exec-out comando tanto el dispositivo como la PC anfitriona deben ser compatibles adb shell protocolo V2.

Es bastante trivial ocuparse del lado de la PC: simplemente actualice el platform-tools paquete (que contiene el adb binario) a la última versión. la versión de adbd daemon en el dispositivo está vinculado a la versión de Android. Él adb shell El protocolo V2 se ha introducido en Android 5.0 junto con el completo adb revisión (pasando de c para C++ código). Pero hubo algunas regresiones (también conocidas como errores), así que adb exec-out la utilidad en Android 5.x aún era limitada. Y, por último, no hay soporte para Android 4.x y dispositivos anteriores. Afortunadamente, la proporción de esos dispositivos más antiguos que aún se utilizan para el desarrollo está disminuyendo rápidamente.

  • adb exec-out funciona bien en Windows sin necesidad dos2unix. entonces tu respuesta es redundante

    – Álex P.

    9 de julio de 2017 a las 20:32

  • Sí, pero extrañamente solo exec-out no funciona en mi computadora.

    – Sebastián247

    20 de julio de 2017 a las 10:06

  • Prueba con adb de lo último platform-tools versión. Si no funciona, significa que su teléfono no admite el comando correctamente.

    – Álex P.

    21 de julio de 2017 a las 17:20


  • funciona para mí, pero solo cuando uso dos2unix dos veces, porque no tengo exec-out. adb shell screencap -p | dos2unix -f | dos2unix -f > Screencap.png Gracias por el tipp con dos2unix

    – Radón8472

    7 sep 2021 a las 12:48


Sí, en Unix/Linux/Mac OS X, puede recibir una salida binaria de adb shell anteponiendo “stty -onlcr;” a tu mando ( NO~~ necesita ser un Android rooteado).

1.Descargue el archivo ejecutable “stty”.
http://www.busybox.net/downloads/binaries/latest/

Para Android antiguo, use busybox-armv5l, otros usan busybox-armv7l.
cambiar el nombre del archivo a “stty”

2.Sube el archivo “stty” a Android y establece el permiso adecuado.

adb push somelocaldir/stty /data/local/tmp/   
adb shell chmod 777 /data/local/tmp/stty 

3.Anteponga “stty -onlcr;” a tu mando así;

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

¡Hecho!

Pero para el sistema operativo Windows, de forma predeterminada, LF de Android se convertirá en CR CR LF.
Incluso si hiciste el paso anterior, aún obtienes CR LF.
Esto “parece” porque adb.exe local usa fwrite, lo que hace que CR se anteponga.
No tengo forma de hacerlo, excepto convertir CR LF a LF manualmente en el sistema operativo Windows.

  • Esto es fantástico. ¡Muchas gracias! Estoy escribiendo algunas herramientas para hacer una copia de seguridad de un dispositivo Android adb (github.com/dlenski/tetherback) y esto realmente es útil. Mucho más directo que el ncbasado en el enfoque que otros han sugerido.

    – Dan Lensky

    18 de marzo de 2016 a las 2:06

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad