android - screenshots - descargar screenshot ux
¿Cómo tomar una captura de pantalla de otra aplicación mediante programación sin permiso de root, como Screenshot UX Trial? (3)
Esto es extremadamente dificil Pasé varios años tratando de hacerlo. Finalmente tuve éxito, pero cualquier solución implicará esfuerzo comercial y técnico.
Actualización de marzo de 2015
La mayoría de las cosas a continuación ya no están actualizadas. Ahora, después de todos estos años, hay un paquete android.media.projection
https://developer.android.com/reference/android/media/projection/package-summary.html que finalmente permite lo que necesita.
Captura de la imagen de la pantalla de su propia aplicación
Para completar, quiero incluir su propio comentario de que puede capturar una imagen de su propia aplicación usando Bitmap.createBitmap(rootview.getDrawingCache());
y mecanismos similares.
Captura la pantalla de otra aplicación mientras estás en segundo plano
Uso del permiso READ_FRAMEBUFFER
En primer lugar, tiene razón en que una aplicación normal no puede hacer uso del permiso READ_FRAMEBUFFER
, porque es "signature" -level. Eso significa que debe estar firmado con la misma clave que la ROM del sistema Android para poder tomar una captura de pantalla.
Pensé que esto era un poco triste, así que en 2009 hice una presentación de proyecto de código abierto de Android para pedir que se abriera 1 . La respuesta de Dianne Hackborn, el arquitecto de Android fue:
Mmm no. Absolutamente positivamente no.
Entonces, eso fue bien, entonces! Por lo tanto, este permiso sigue siendo de nivel de signature
hasta el día de hoy.
Sin embargo, si tuviera este permiso, podría llamar al miembro ISurfaceComposer
de ISurfaceComposer
2 . Tendrá que escribir algún código nativo para acceder a esta función, utilizando el NDK de Android y también algunas API no documentadas. Sin embargo, es posible.
Internamente, dentro del subsistema de gráficos de Android, utiliza una llamada glReadPixels
para recuperar los píxeles de la GPU a la CPU. (La GPU se usa para la mayoría de las composiciones en Android. De hecho, Android 4.0+ es compatible con compositores de hardware adicionales, y Surface Flinger tiene que hacer aún más trabajo para devolver esos píxeles a la CPU).
Esta llamada funciona muy bien, excepto por algunos pequeños problemas:
- El riesgo de usar una API no compatible que podría romperse en cualquier momento;
- La molestia de llamarlo en C ++
- Hace que las tuberías de la GPU se detengan, lo que puede molestar a los diseñadores de la GPU, pero en realidad no causa problemas en la realidad.
- Se basa en un gran ancho de banda desde la GPU a la CPU. Esto a veces es problemático porque las arquitecturas de memoria están diseñadas para enviar datos en la dirección opuesta. Sin embargo, parece recordar que todas las arquitecturas modernas de chipset de Android comparten directamente la memoria entre la GPU y la CPU, a excepción de una (¿puede ser Broadcom? No lo recuerdo) donde esto puede causar que este mecanismo sea muy lento.
... y un gran problema ...
- Lo que es más importante, como escritor de aplicaciones normal, ni siquiera puede llamar a esta API debido a los permisos de nivel de firma requeridos.
Aún así, en la mayoría de los dispositivos Android, puede obtener 10 cuadros por segundo de esto. Mejor aún, esta API realmente permite escalar la imagen resultante en hardware en la GPU , por lo que si eres inteligente puedes escalar previamente la imagen hasta el tamaño que necesites, incluso antes de que los píxeles lleguen a la CPU. Por lo tanto, puede ser un rendimiento extremadamente alto.
Tenga en cuenta, por supuesto, que usted como escritor de la aplicación no puede llamar a glReadPixels
porque no tiene acceso al contexto de OpenGL correspondiente. Es propiedad del flinger de superficie.
Usando /dev/graphics/fb0
y similar
Algunos están tentados de intentar leer estos archivos de dispositivos Linux que representan el framebuffer. Sin embargo, hay tres problemas:
- Necesitas root
- A veces ni siquiera están allí.
- A menudo, no representan la imagen real de la pantalla. Recuerde en Android que los gráficos están compuestos en la GPU. Por lo tanto, no hay ninguna razón por la que la CPU deba tener acceso a una copia de la imagen de la pantalla completa compuesta, y a menudo no lo hace. Este archivo a veces contiene rasgado (en el mejor de los casos) y una imagen basura (en el peor de los casos). Curiosamente, algunas de las herramientas para teléfonos rooteados usan este método, que creo que es un error. Si tienes root, por definición tienes todos los permisos de Android y, por lo tanto, puedes llamar a la API
captureScreen
anterior para obtener una imagen correcta.
Uso de socios de hardware
Ahora entramos en las soluciones que requieren acción comercial.
Hablar con los fabricantes de chipset de Android a menudo presenta una solución. Desde que diseñan el hardware, tienen acceso al framebuffer, y a menudo pueden proporcionar bibliotecas que evitan por completo el modelo de permisos de Android simplemente accediendo directamente a sus controladores kernel personalizados.
Si apunta a un modelo de teléfono específico, esta es una buena manera de avanzar. Por supuesto, lo más probable es que deba cooperar con el fabricante del teléfono y con el fabricante del silicio.
A veces esto puede proporcionar resultados sobresalientes . Por ejemplo, he escuchado que es posible en algunos hardware conectar el framebuffer de hardware del teléfono directamente al codificador de video H.264 del hardware del teléfono, y recuperar un flujo de video precodificado de lo que esté en la pantalla del teléfono. Excepcional. (Desafortunadamente, solo sé que esto es posible en los chips TI OMAP, que se retiran gradualmente del mercado de teléfonos 3 ).
Usando agujeros de seguridad
Android impone rígidamente su modelo de permisos y tiene pocos agujeros de seguridad. Sin embargo, los OEM de Android a veces pueden ser más descuidados.
Por ejemplo, un OEM importante cuyo nombre comienza con S ha implementado una forma de capturar la pantalla con una pulsación de tecla. Lo guarda en un archivo legible en todo el mundo en la tarjeta SD. Hipotéticamente, es posible que pueda encontrar lo que intercepta esas teclas y ver cómo funciona. Quizás podrías hacer algo similar.
Y tal vez haya una forma para otro OEM principal cuyo nombre también comienza con S.
No, no voy a entrar en más detalles sobre esta sección. Para averiguar cómo hacer esas cosas, necesitaría tener un software de ingeniería inversa, y eso podría ser ilegal. Buena suerte, sin embargo.
Trabajando con los fabricantes de teléfonos
Como se describió anteriormente, los fabricantes de teléfonos tienen acceso rápido a una API que funciona . Y los fabricantes de teléfonos tienen los permisos de nivel de signature
requeridos.
Entonces, todo lo que necesita hacer es hacer arreglos para que su software sea firmado por el fabricante del teléfono.
Esto es, sin embargo, difícil . Al firmar el software, el fabricante del teléfono está garantizando su calidad, por lo que deberían querer auditar su código fuente. Además, debido a la naturaleza de Android, si firman el software, deben ser ellos quienes lo distribuyan. No puede ponerlo en el mercado si está firmado por la firma de otra persona.
Sin embargo, el OEM no necesita incluirlo en la ROM, todavía pueden distribuirlo en el mercado de Android. Pero no puedes.
Una buena solución sería si cada proveedor firmara una pequeña biblioteca a la que un SDK común podría acceder. Lo que me lleva a ...
Trabaja con socios de software que ya han resuelto esto
Sé mucho sobre esto porque solía trabajar en RealVNC. Trabajamos con los principales proveedores de teléfonos Android para obtener acceso a estas API de nivel de firma. No puedo exagerar los muchos, muchos años-hombre de esfuerzo (comercial y técnico) requeridos para lograr esto. Algunos de los OEM han publicado este trabajo, por ejemplo 4 .
Ya no trabajo en RealVNC, así que no tengo nada que ganar publicitando su software. Pero si realmente desea poder capturar la pantalla en múltiples dispositivos Android, puede acercarse a ellos para volver a utilizar su Servicio de control remoto o Android VNC SDK 5 . No es de código abierto, por lo que debe esperar pagar, y créame, esto es bastante justo dado el esfuerzo épico que implica trabajar con todos estos OEM de Android.
En aras del equilibrio, debo señalar que otros proveedores también han trabajado con los fabricantes de teléfonos en esto, por ejemplo, Soti. Pero creo que todos ofrecen soluciones de administración de dispositivos específicas, en lugar de un SDK general de control remoto / inyección de eventos.
Sobre USB
Otra opción: el adb
daemon que escucha las conexiones de depuración a través de USB tiene un poco más de privilegios que una aplicación normal, por lo que es capaz de capturar la pantalla (puede ver su imagen con la herramienta ddms
). Si puede ejecutar cualquier comando usando adb
, también puede obtener esos privilegios (según la biblioteca android-screenshot-library vinculada anteriormente).
Contribuir al proyecto de código abierto de Android
Eventualmente, este problema me redujo al polvo, y me fui a pastos más verdes que no implicaban tratar de extraer píxeles de los teléfonos Android.
Sin embargo, antes de salir de RealVNC, intenté nuevamente contribuir con estas API al proyecto de código abierto de Android. Esta vez obtuvimos una reacción más positiva 6 . En resumen, se sugirió que nuestro enfoque de seguridad era casi correcto, pero que el sistema de gráficos estaba en demasiada confusión como para aceptar nuestros parches. Bueno, la gran noticia es que el sistema de gráficos ya no está en crisis, de hecho ahora tiene esa API captureScreen
que significa que no se necesitan cambios en el sistema de gráficos en absoluto. Por lo tanto, es posible enviar un nuevo mecanismo de seguridad a AOSP en torno a esta API, que finalmente resuelve este problema.
¡La mejor de las suertes!
¿Cómo tomar una captura de pantalla de otra aplicación mediante programación sin permiso de root, como Screenshot UX Trial?
Sé que puedo capturar el mapa de bits de la vista raíz en mi aplicación. Pero no puedo obtener la vista raíz de la otra aplicación cuando mi aplicación se ejecuta en segundo plano
bitmap = Bitmap.createBitmap(rootview.getDrawingCache());
Existe un permiso para capturar el búfer de trama actual en Manifest:
android.permission.READ_FRAME_BUFFER
. Pero algunos sitios web dicen que es solo para aplicaciones exclusivas.
Después de probar Screenshot UX Trial, leo el permiso:
- INTERNET: para conectarse al servidor de captura de pantalla de localhost para el teléfono rooteado.
- SYSTEM_ALERT_WINDOW: para el botón de la cámara superior.
- VIBRAR: para vibrar retroalimentación.
- WRITE_EXTERNAL_STORAGE: para guardar la captura de pantalla.
- GET_TASKS: para detectar actividad de configuración de desarrollo en primer plano para método de captura no arraigado y no precargado.
Parece que SYSTEM_ALERT_WINDOW
o GET_TASKS
permiten que la aplicación tome una captura de pantalla. Tengo dos conjeturas sobre cómo funciona:
- Puede acceder a la
Activity
de la actividad en primer plano, obtiene la vista raíz de laActivity
, captura su captura de pantalla. - Llamando
glreadpixels
Si intenta uno de mis conjeturas, por favor, hágamelo saber el resultado.
No creo que Android te permita acceder al búfer de cuadros de otra aplicación. Esto es solo parte de la seguridad de Android. Cada aplicación debe mantener sus propios recursos.
Si realmente necesita obtener una captura de pantalla de cualquier aplicación, le sugiero que utilice el "gesto" de captura de pantalla nativo. Para el Nexus 7, por ejemplo, simplemente "... mantenga pulsado el botón de encendido y el botón de bajar volumen al mismo tiempo durante aproximadamente 2 segundos".
Una búsqueda en Google generalmente encontrará el truco con su dispositivo.
Tal vez la android-screenshot-library puede ayudar. Pero bien en su página de Uso dice que necesita un servicio nativo iniciado con adb (del sdk de Android).
PD: Recuerda que Screenshot UX no funciona para todos los teléfonos sin rootear.