Probar una app Android online significa que el teléfono está en otro lugar. Llegas a él por la red, instalas tu build, miras la pantalla en un navegador y sacas logs con adb como si hubiera un cable conectado. Bien hecho, reemplaza casi todo lo que te da un cajón de teléfonos de prueba. Mal hecho, es un emulador lento con pasos de más.
Esta guía lleva una build del APK a los logs de cierres inesperados en tres versiones de Android. Usa los comandos que ejecuto cada semana, enumera los errores de instalación con los que te vas a encontrar y termina con los casos en los que un teléfono físico sigue siendo la mejor herramienta.
Prepara la build
Empieza con una build que puedas instalar desde la línea de comandos. Para una primera pasada, una build de depuración sirve:
./gradlew assembleDebug ls app/build/outputs/apk/debug/
Dos comprobaciones ahorran tiempo después. La primera es la ABI. Si tu app incluye código nativo, asegúrate de que el APK contenga bibliotecas arm64-v8a. Los teléfonos creados a partir de modelos reales son arm64 y, a diferencia de las imágenes de emulador x86 de tu laptop, no traducen el código compilado para otra arquitectura.
unzip -l app/build/outputs/apk/debug/app-debug.apk | grep "lib/"
La segunda es el indicador testOnly. Cuando pulsas Run en Android Studio, el IDE marca el APK con android:testOnly="true", y un adb install simple lo rechaza. Las builds de assembleDebug no llevan ese indicador. Si solo tienes una build del IDE, instálala con adb install -t.
Si tu artefacto de release es un app bundle, conviértelo en un conjunto de APK para el teléfono conectado con bundletool:
bundletool build-apks --bundle=app-release.aab --output=app.apks --connected-device bundletool install-apks --apks=app.apks
Sin --ks, bundletool firma con la clave de depuración. Eso basta para probar, pero el resultado no se instalará encima de una copia firmada con tu clave de release.
Elige tres versiones de Android, no una
Un solo teléfono oculta la mayoría de los bugs de compatibilidad, porque Android cambia el comportamiento de dos maneras. Algunos cambios afectan a todas las apps en la nueva versión. Otros solo se activan cuando subes el targetSdkVersion. Tres versiones atrapan la mayor parte de ambos:
- La versión más antigua que todavía soportas, o la más cercana a la que puedas llegar. Android 12 es un piso razonable para la mayoría de las apps en 2026.
- La versión con más cuota en tus propias analíticas, a menudo 14 o 15.
- La versión más reciente, 16 o 17, donde aparecen primero los cambios ligados al target, como el edge-to-edge obligatorio y el gesto atrás predictivo.
La lista completa de lo que cambia entre cada par es larga. Probar una app en distintas versiones de Android tiene la lista de control versión por versión.
Paso 1: crea los teléfonos
En un servicio de teléfonos en la nube eliges una versión de Android y un modelo, y el teléfono está listo en cerca de un minuto. Ponle a cada uno el nombre de su versión, por ejemplo qa-12, qa-14 y qa-16, para que los logs y las capturas sigan siendo legibles una semana después. Si lo automatizas desde el CI, tu primer dispositivo muestra los mismos pasos con la API.
Elige modelos que tus usuarios realmente tienen. Un teléfono económico con pantalla de 720p y uno de gama alta de 1440p rompen diseños distintos, así que mezclar densidades de pantalla entre las tres versiones te da más cobertura con el mismo tiempo.
Paso 2: instala la build
Hay tres formas de llevar el APK al teléfono: subirlo en el panel del navegador, enviarlo por la API REST o ejecutar adb install a través del relé de ADB. La guía de apps cubre las dos primeras. Para adb, activa el relé para tu dirección IP como se describe en la documentación de ADB y conéctate:
adb connect HOST:PORT adb -s HOST:PORT install -r app-debug.apk
Los fallos de instalación casi siempre son uno de estos cinco, y el texto del error te dice cuál:
| Error | Causa | Solución |
|---|---|---|
INSTALL_FAILED_NO_MATCHING_ABIS | no hay bibliotecas nativas para la ABI del teléfono | agrega arm64-v8a a abiFilters |
INSTALL_FAILED_TEST_ONLY | APK generado con el botón Run del IDE | adb install -t, o compila con Gradle |
INSTALL_FAILED_UPDATE_INCOMPATIBLE | hay instalada una copia firmada con otra clave | primero adb uninstall de la copia anterior |
INSTALL_FAILED_DEPRECATED_SDK_VERSION | target por debajo de la API 23 en Android 14, por debajo de la 24 en 15 y posteriores | sube el targetSdkVersion |
INSTALL_PARSE_FAILED_MANIFEST_MALFORMED | un componente con intent filter sin android:exported en 12 y posteriores | declara exported en cada uno de esos componentes |
Paso 3: haz una prueba de humo repetible
Haz la misma pasada de la misma forma en cada versión, para que las diferencias que veas sean de Android y no de cómo tocaste. La mía cubre seis cosas:
- Arranque en frío.
am start -WimprimeTotalTimeen milisegundos. Compáralo entre versiones, no con un teléfono físico de gama alta. - Primer uso. Instala sin
-g, para que cada aviso de permiso en tiempo de ejecución aparezca como lo ve un usuario nuevo. - Segundo plano y vuelta. Pulsa Inicio, abre otras dos apps y vuelve.
- Muerte del proceso. Con la app en segundo plano,
am killtermina el proceso como lo hace el sistema cuando falta memoria. Al volver a la app, la pantalla y su estado tienen que restaurarse. - Configuración. Modo oscuro, una fuente más grande, otro tamaño de pantalla.
- Navegación hacia atrás. El gesto atrás desde cada pantalla de primer nivel.
Los comandos, con S como dirección del dispositivo:
S=HOST:PORT adb -s $S shell am force-stop com.example.app adb -s $S shell am start -W -n com.example.app/.MainActivity adb -s $S shell input keyevent KEYCODE_HOME adb -s $S shell am kill com.example.app adb -s $S shell cmd uimode night yes adb -s $S shell settings put system font_scale 1.3 adb -s $S shell wm density 560 adb -s $S shell wm density reset
Antes de la siguiente pasada, deshaz la escala de fuente con settings put system font_scale 1.0 y el modo oscuro con cmd uimode night no, o restablece el teléfono.
Paso 4: lee los logs
Limpia el búfer antes de cada escenario y luego lee solo tu propio proceso:
adb -s $S logcat -c adb -s $S shell am start -W -n com.example.app/.MainActivity adb -s $S logcat -d --pid=$(adb -s $S shell pidof -s com.example.app)
El pid cambia cada vez que el proceso se reinicia, así que un cierre durante el arranque no aparecerá con el pid nuevo. Lee entonces el búfer de cierres inesperados. Guarda los cierres de Java y nativos de todos los procesos:
adb -s $S logcat -d -b crash adb -s $S logcat -d AndroidRuntime:E "*:S"
Para un ANR, el logcat solo te da el titular. adb bugreport report.zip reúne las trazas de los hilos de ese momento junto con el estado del sistema. Tarda uno o dos minutos, y es el archivo que hay que adjuntar al ticket.
Pon los tres logs lado a lado. Una advertencia que solo aparece en la versión más nueva suele ser un cambio ligado al target. Un cierre en las tres es tu código.
Paso 5: restablece entre ejecuciones
pm clear borra los datos de tu app y deja todo lo demás en su lugar: otras apps, los ajustes que cambiaste, la cuenta de Google. Para una comparación limpia entre suites, restablece el teléfono a un estado limpio, y reserva pm clear para repeticiones rápidas dentro de una misma suite.
Cuando la pasada sea estable, su lugar es el CI. La página de pruebas de apps muestra los mismos pasos como llamadas a la API. Las pruebas de instrumentación son comandos de adb normales, así que corren en cualquier dispositivo al que llegue adb:
adb -s $S shell am instrument -w -e class com.example.LoginTest \ com.example.app.test/androidx.test.runner.AndroidJUnitRunner
Dónde se detiene una prueba online
Hay que ser honesto sobre lo que no puede decirte un teléfono en un centro de datos:
- La calidad de la cámara, el autoenfoque, la deriva real del GPS y los sensores biométricos.
- El rendimiento gráfico. Un Android virtualizado renderiza con drivers traducidos o por software, así que los tiempos de fotograma y los tirones no se trasladan a un teléfono físico.
- El consumo de batería y el throttling térmico.
- El software de los fabricantes. Los optimizadores de batería y los ajustes de inicio automático de algunas marcas detienen el trabajo en segundo plano de formas que el Android de serie no hace.
- Las radios: pagos por NFC, emparejamiento por Bluetooth, funciones del operador.
Conserva dos o tres teléfonos físicos para esas pruebas y corre la matriz amplia online.
Formas gratis de empezar
“Pruebas en dispositivos reales online gratis” suele significar una de tres cosas. El Android Emulator en tu propia máquina no cuesta nada y es el lugar indicado para el ciclo de editar y ejecutar. Las nubes públicas de dispositivos ofrecen pequeñas cuotas gratis de teléfonos físicos, sobre todo para ejecuciones automatizadas. Los servicios de teléfonos en la nube suelen ofrecer una prueba: Clousd da los primeros 30 minutos gratis sin tarjeta, suficiente para instalar una build y hacer una primera prueba de humo; mira la prueba gratis.


