Bad Daemons

Visualizar y controlar un Android desde el ordenador

Hace unos días vi en Menéame que alguien había hecho un programa para controlar un móvil Android desde el ordenador, y justo coincidió con que me había comprado un móvil nuevo. Si hay algo que odio es usar el móvil, y más aún para configurarlo. El motivo es que me resulta muy incómodo tener que estar escribiendo con un teclado táctil. Así que este programa parece caído del cielo para mi. Antes de entrar en materia, se ve así:

scrcpy.png

Este programa funciona tanto en Windows, como Mac, como GNU/Linux. Las instrucciones servirán solo para el ñú, lógicamente, pero como he creado una imagen docker para facilitar el uso de scrcpy, se podrá utilizar en cualquier plataforma. Al lío:

sudo apt install -y ffmpeg libsdl2-2.0.0 adb git wget make gcc \
    openjdk-8-jdk pkg-config meson zip libavcodec-dev libavformat-dev \
    libavutil-dev libsdl2-dev hicolor-icon-theme libgl1-mesa-dri \
    libgl1-mesa-glx libpango1.0-0 libpulse0 libv4l-0 fonts-symbola
export ANDROID_HOME=$HOME/android-sdk SCRCPY_DIR=$HOME/scrcpy
mkdir $ANDROID_HOME
cd $ANDROID_HOME
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
unzip sdk*
rm sdk*
yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses

git clone https://github.com/Genymobile/scrcpy   $SCRCPY
cd $SCRCPY_DIR/scrcpy
meson x --buildtype release --strip -Db_lto=true
cd $SCRCPY_DIR/x
ninja
ninja install

Y ya. No entraré en que hace exactamente cada orden por que de algunas dudo y tampoco me interesa. Me basta con saber que compilamos un binario en java cuyo trabajo consiste en hacer accesible la pantalla del móvil, que en el ordenador se reproduce con ffmpeg.

Para usarlo, ya solo tenemos que activar las herramientas del desarrollador1 en el móvil y ejecutar scrcpy.

Esta es la opción viejuna, la más moderna y que enguarra menos el ordenador es usar docker. No cubriré la instalación de docker2, pero si que veremos un ejemplo práctico de como dockerizar una aplicación con una interfaz gráfica y que además necesita acceso a los dispositivos conectados por USB. Y lo mejor es que es estúpidamente fácil, una vez se sabe como hacer, se puede usar con cualquier aplicación con GUI sin problemas.

Como ya tengo un registry, descargar la imagen es tan simple como ejecutar:

docker pull registry.daemons.it/scrcpy

Y para usar la imagen:

docker run -ti --privileged -v /dev/bus/usb:/dev/bus/usb -v \
       ~/.android:/root/.android -v /tmp/.X11-unix:/tmp/.X11-unix -e \
       DISPLAY=unix$DISPLAY -p 5037:5037 -v $HOME/.Xauthority:/root/.Xauthority \
       --net=host scrcpy

Esta orden lo que hace exactamente es:

  • -ti: Ejecutar el contenedor de forma interactiva.
  • --privileged: Ejecutar de modo privilegiado. En general esto no es recomendable, sobretodo si el contenedor está expuesto a internet. Pero siendo como es un repositorio que se ejecuta en local, no pasa nada.
  • -v /dev/bus/usb:/dev/bus/usb: Hacemos accesibles el USB al contenedor.
  • -v ~/.android:/root/.android: Hacemos accesible este directorio para poder guardar la huella digital de nuestro móvil. Es una medida de seguridad de android, la primera vez que nos conectamos por adb a un móvil, nos pide que la confirmemos.
  • -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY -v $HOME/.Xauthority:/root/.Xauthority: Aquí está la magia que hace accesible la interfaz gráfica del contenedor en nuestro host. En teoría no hace falta montar el .Xauthority, pero no he logrado hacerlo funcionar sin ello.
  • -p 5037:5037: Hacer accesible el puerto que usa adb.
  • --net=host: Se usa la red del host y no la subred típica de docker.

Para que nos resulte transparente el uso de docker, recomiendo crear un fichero llamado scrcpy en algún punto del $PATH para que se pueda llamar como a cualquier otro programa.

El dockerfile lo referencio aquí, pero aún no tengo claro como gestionar mis dockerfiles, así que es posible que cambie en el futuro. Por cierto, este dockerfile está hecho con multi-stage3:

FROM debian AS build

ENV ANDROID_HOME=/android-sdk LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
RUN apt update && apt install -y ffmpeg libsdl2-2.0.0 adb git wget make gcc \
    openjdk-8-jdk pkg-config meson zip libavcodec-dev libavformat-dev \
    libavutil-dev libsdl2-dev hicolor-icon-theme libgl1-mesa-dri \
    libgl1-mesa-glx libpango1.0-0 libpulse0 libv4l-0 fonts-symbola locales \
    && sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    locale-gen && mkdir $ANDROID_HOME && cd $ANDROID_HOME && wget \
    https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip \
    && unzip sdk* && rm sdk* && yes | $ANDROID_HOME/tools/bin/sdkmanager \
    --licenses && cd / && git clone https://github.com/Genymobile/scrcpy

RUN useradd -ms /bin/bash tmp && chown -R tmp /scrcpy /android-sdk
USER tmp
RUN cd scrcpy && meson x --buildtype release --strip -Db_lto=true && cd \
    /scrcpy/x && ninja
USER root
RUN cd /scrcpy/x && ninja install

FROM debian:stretch-slim
COPY --from=build /usr/local/bin/scrcpy /usr/local/bin/scrcpy
COPY --from=build /usr/local/share/scrcpy/ /usr/local/share/scrcpy/
RUN apt update && mkdir /usr/share/man/man1 && apt install -y \
    --no-install-recommends libgl1-mesa-dri ffmpeg libsdl2-2.0.0 adb

CMD ["scrcpy"]

Ya solo queda ejecutar scrcpy (telita el nombre) y a volar.

Referencias: Repositorio de dotfiles de Jess Frazz: Es una crack. Todos sus repositorios y su blog (enlazado en su cuenta de Gitsux) valen la pena.

Nota al pie de página:

1

Igual depende del móvil, pero en la mayoría estas se activan yendo a Ajustes, Acerca del dispositivo, Info de software y ahí presionamos varias veces el botón Número de compilación. Creo que son seis, pero no estoy seguro. Cuando se activen saldrá un mensaje y al ir a Ajustes, habrá una sección de Opciones del desarrollador. Y por fin, ahí estará el botón de Depuración de USB. Es recomendable desactivarlo cuando no se use.

2

Pero si comentaré que aquí hay un playbook, por si queréis usarlo.

3

Es el primer dockerfile multi-stage que hago, mola lo suyo. Aquí se pueden ver los motivos por los cuales utilizarlo.