[android] ¿Captura de pantalla del Nexus One de adb?


Answers

En realidad, hay otra habilidad muy simple para capturar capturas de pantalla de su dispositivo Android: escriba un guion simple 1.script como este:

# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()

# Takes a screenshot
result = device.takeSnapshot()

# Writes the screenshot to a file
result.writeToFile('1.png','png')

y llame a monkeyrunner 1.script .

Question

Mi objetivo es poder escribir un comando de una palabra y obtener una captura de pantalla de un Nexus One conectado por USB.

Hasta ahora, puedo obtener el framebuffer que creo que es una imagen en bruto de 32bit xRGB888 tirando de él de esta manera:

adb pull /dev/graphics/fb0 fb0

A partir de ahí, estoy teniendo dificultades para convertirlo a png. Estoy intentando con ffmpeg así:

ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb8888 -s 480x800 -i fb0 -f image2 -vcodec png image.png

Eso crea una imagen púrpura hermosa que tiene partes que se asemejan vagamente a la pantalla, pero de ninguna manera es una captura de pantalla limpia.




Un poco complicado / excesivo, pero maneja tanto el escenario screencap como el framebuffer (así como también descifrar la resolución).

#!/bin/bash
#
# adb-screenshot - simple script to take screenshots of android devices
#
# Requires: 'ffmpeg' and 'adb' to be somewhere in the PATH
#
# Author: Kevin C. Krinke <kevin@krinke.ca>
# License: Public Domain

# globals / constants
NAME=$(basename $0)
TGT=~/Desktop/${NAME}.png
SRC=/sdcard/${NAME}.png
TMP=/tmp/${NAME}.$$
RAW=/tmp/${NAME}.raw
FFMPEG=$(which ffmpeg)
ADB=$(which adb)
DD=$(which dd)
USB_DEVICE=""

# remove transitory files if exist
function cleanup () {
    [ -f "${RAW}" ] && rm -f "${RAW}"
    [ -f "${TMP}" ] && rm -f "${TMP}"
    [ -z "$1" ] && die "aborting process now."
    exit 0
}

# exit with an error
function die () {
    echo "Critical Error: $@"
    exit 1
}

# catch all signals and cleanup / dump
trap cleanup \
    SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABRT SIGEMT SIGFPE \
    SIGKILL SIGBUS SIGSEGV SIGSYS SIGPIPE SIGALRM SIGTERM SIGURG \
    SIGSTOP SIGTSTP SIGCONT SIGCHLD SIGTTIN SIGTTOU SIGIO SIGXCPU \
    SIGXFSZ SIGVTALRM SIGPROF SIGWINCH SIGINFO SIGUSR1 SIGUSR2

# adb is absolutely required
[ -x "${ADB}" ] || die "ADB is missing!"

# cheap getopt
while [ $# -gt 0 ]
do
    case "$1" in
        "-h"|"--help")
            echo "usage: $(basename $0) [-h|--help] [-s SERIAL] [/path/to/output.png]"
            exit 1
            ;;
        "-s")
            [ -z "$2" ] && die "Missing argument for option \"-s\", try \"${NAME} --help\""
            HAS_DEVICE=$(${ADB} devices | grep "$2" )
            [ -z "${HAS_DEVICE}" ] && die "No device found with serial $2"
            USB_DEVICE="$2"
            ;;
        *)
            [ -n "$1" -a -d "$(dirname $1)" ] && TGT="$1"
            ;;
    esac
    shift
done

# prep target with fire
[ -f "${TGT}" ] && rm -f "${TGT}"

# tweak ADB command line
if [ -n "${USB_DEVICE}" ]
then
    ADB="$(which adb) -s ${USB_DEVICE}"
fi

# calculate resolution
DISPLAY_RAW=$(${ADB} shell dumpsys window)
HRES=$(echo "${DISPLAY_RAW}" | grep SurfaceWidth  | head -1 | perl -pe 's/^.*\bSurfaceWidth\:\s*(\d+)px\b.*$/$1/')
VRES=$(echo "${DISPLAY_RAW}" | grep SurfaceHeight | head -1 | perl -pe 's/^.*\bSurfaceHeight\:\s*(\d+)px\b.*$/$1/')
RES=${HRES}x${VRES}

# check for screencap binary
HAS_SCREENCAP=$(${ADB} shell "[ -x /system/bin/screencap ] && echo 1 || echo 0" | perl -pe 's/\D+//g')
if [ "$HAS_SCREENCAP" == "1" ]
then # use screencap to get the image easy-peasy
    echo -n "Getting ${RES} screencap... "
    ( ${ADB} shell /system/bin/screencap ${SRC} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to execute screencap"
    ( ${ADB} pull ${SRC} ${TMP} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to pull png image"
    ( ${ADB} shell rm ${SRC} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to remove png image"
    mv ${TMP} ${TGT}
    echo "wrote: ${TGT}"
else # fetch a framebuffer snapshot
    # ffmpeg is only needed if device is pre-ICS
    [ -x "${FFMPEG}" ] || die "FFMPEG is missing!"
    [ -x "${DD}" ] || die "DD is missing!"
    echo -n "Getting ${RES} framebuffer... "
    ( ${ADB} pull /dev/graphics/fb0 ${RAW} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to pull raw image data"
    # calculate dd parameters
    COUNT=$((HRES*4))
    BLOCKSIZE=$((VRES))
    ( ${DD} bs=${BLOCKSIZE} count=${COUNT} if=${RAW} of=${TMP} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to realign raw image data"
    ( ${FFMPEG} -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s ${RES} -i ${TMP} -f image2 -vcodec png ${TGT} 2>&1 ) > /dev/null
    [ "$?" != "0" ] && die "Failed to encode PNG image"
    echo "wrote: ${TGT}"
fi

# exit app normal
cleanup 1



En el MyTouch Slide 3G, terminé con los canales rojo y azul intercambiados en mis capturas de pantalla. Aquí está el encantamiento ffmpeg correcto para cualquier otra persona en esa situación: (la parte notable: -pix_fmt bgr32 )

ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt bgr32 -s 320x480 -i fb0 -f image2 -vcodec png image.png

¡Gracias a Patola por el útil script de shell! Al menos para mi teléfono, no es necesaria ninguna mogrificación para orientarme correctamente para el modo vertical (320x480), por lo que el final de su secuencia de comandos se convierte en:

# assuming 'down' is towards the keyboard or usb jack 
# in landscape and protrait modes respectively
(( ${PORTRAIT} )) || mogrify -rotate 270 "${outputfile}"

/bin/rm -f fb0.$$ fb0b.$$



Usar mi HTC Hero (y por lo tanto ajustar desde 480x800 a 320x480), esto funciona si uso rgb565 en lugar de 8888:

ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb565 -s 320x480 -i fb0 -f image2 -vcodec png image.png



Ahora tenemos un comando de una sola línea para tomar una captura de pantalla. El comando de la siguiente manera:

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png

Escriba el comando de arriba en su terminal y presione enter. Si desea que la captura de pantalla se almacene en cualquier ubicación específica, proporcione el directorio de ruta (o) antes de screen.png .

Source




Una forma de automatizar por completo este proceso es crear una secuencia de comandos que agregue la marca de tiempo curada al nombre del archivo. De esta manera, no tiene que escribir el nombre del archivo usted mismo, todas las capturas de pantalla tienen un nombre diferente, y las capturas de pantalla están ordenadas por tiempo.

Ejemplo de script bash:

#! /bin/bash

filename=$(date +"_%Y-%m-%d-%H:%M")

/PATH_TO_ANDROID_SDK/platform-tools/adb -d shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screenshot$filename.png

Esto creará un archivo llamado como screenshot_2014-01-07-10: 31.png




Creo que rgb32torgb888.py debería ser

 sys.stdout.write(colour[0])
 sys.stdout.write(colour[1])
 sys.stdout.write(colour[2])





Links