web-dev-qa-db-fra.com

Comment faire une capture d'écran d'une autre application par programme sans autorisation root, comme Screenshot UX Trial?

Comment faire une capture d'écran d'une autre application par programme sans autorisation root, comme Screenshot UX Trial?

  1. Je sais que je peux capturer le bitmap de la vue racine dans mon application. Mais je ne peux pas obtenir la vue racine de l'autre application lorsque mon application s'exécute en arrière-plan

    bitmap = Bitmap.createBitmap(rootview.getDrawingCache());

  2. Il existe une autorisation pour capturer le tampon de trame actuel dans le manifeste: Android.permission.READ_FRAME_BUFFER. Mais certains sites Web disent que c'est uniquement pour l'application de signature.

    Cochez Android - Niveaux de protection

Après avoir essayé la version d'essai de Screenshot UX, j'ai lu l'autorisation:

  • INTERNET: pour se connecter au serveur de capture d'écran localhost pour le téléphone rooté.
  • SYSTEM_ALERT_WINDOW: pour le bouton de caméra le plus haut.
  • VIBRATE: pour une rétroaction vibrante.
  • WRITE_EXTERNAL_STORAGE: pour enregistrer la capture d'écran.
  • GET_TASKS: pour détecter l'activité de réglage de développement de premier plan pour la méthode de capture non enracinée et non préchargée.

Il semble soit SYSTEM_ALERT_WINDOW ou GET_TASKS autorise l'application à prendre une capture d'écran. J'ai deux hypothèses sur la façon dont cela fonctionne:

  1. Il peut être en mesure d'accéder au Activity de l'activité de premier plan, il obtient la vue racine du Activity, capture sa capture d'écran.
  2. Appel de glreadpixels

Si vous essayez une de mes suppositions, faites-moi savoir le résultat.

53
Victor Chang

C'est extrêmement difficile. J'ai passé plusieurs années à essayer de le faire. J'ai finalement réussi, mais toute solution impliquera des efforts commerciaux et techniques.


Mise à jour mars 2015

La plupart des éléments ci-dessous ne sont plus à jour. Il y a maintenant, après toutes ces années, un package Android.media.projectionhttps://developer.Android.com/reference/Android/media/projection/package-summary.html qui permet enfin ce vous avez besoin!


Capture de l'image d'écran de votre propre application

Pour être complet, je veux inclure votre propre commentaire selon lequel vous pouvez capturer une image de votre propre application en utilisant Bitmap.createBitmap(rootview.getDrawingCache()); et des mécanismes similaires.

Capture de l'écran d'une autre application en arrière-plan

Utilisation de l'autorisation READ_FRAMEBUFFER

Premièrement, vous avez raison de dire qu'une application normale ne peut pas utiliser l'autorisation READ_FRAMEBUFFER, Car c'est le niveau "signature". Cela signifie que vous devez être signé avec la même clé que le système Android ROM) pour pouvoir prendre une telle capture d'écran.

Je pensais que c'était un peu triste, donc en 2009, j'ai fait un Android soumission de projet open-source pour demander qu'il soit ouvert 1 . La réponse de Dianne Hackborn, l'architecte Android était:

Um non. Absolument pas.

Alors ça s'est bien passé! Par conséquent, cette autorisation est toujours au niveau signature- à ce jour.

Si vous aviez cette autorisation, cependant, vous pourriez appeler le membre captureScreen de ISurfaceComposer2 . Vous auriez besoin d'écrire du code natif pour accéder à cette fonction, en utilisant le Android NDK et aussi quelques API non documentées. Cependant, c'est possible.

En interne dans le sous-système graphique Android, cela utilise un appel glReadPixels pour récupérer les pixels du GPU vers le CPU. (Le GPU est utilisé pour la plupart des compositing sur Android . En fait Android 4.0+ prend en charge des compositeurs matériels supplémentaires, et le Surface Flinger doit faire encore plus de travail pour ramener ces pixels vers le CPU.)

Cet appel fonctionne à merveille, à l'exception de quelques petits problèmes:

  • Le risque d'utiliser une API non prise en charge qui pourrait se casser à tout moment;
  • Les tracas de l'appeler en C++
  • Cela provoque le blocage des pipelines GPU, ce qui peut déranger les concepteurs de GPU mais ne cause pas vraiment de problèmes en réalité
  • Il s'appuie sur une large bande passante du GPU de retour au CPU. Cela est parfois problématique car les architectures de mémoire sont conçues pour envoyer des données dans la direction opposée. Cependant, il me semble que toutes les architectures de chipset modernes Android partagent directement la mémoire entre le GPU et le CPU, sauf une (il peut s'agir de Broadcom? - Je ne me souviens pas) où cela peut provoquer ce mécanisme sera très lent.

... et un gros problème ...

  • Plus important encore, en tant que rédacteur d'application normal, vous ne pouvez même pas appeler cette API en raison des autorisations au niveau de la signature requises.

Pourtant, sur la plupart des appareils Android Android, vous pouvez obtenir 10 images par seconde. Mieux encore, cette API prend en charge la mise à l'échelle de l'image résultante dans le matériel sur le GPU , donc si vous êtes intelligent, vous pouvez pré-redimensionner l'image à la taille dont vous avez besoin, avant même que les pixels n'atteignent le CPU. Cela peut donc être extrêmement performant.

Notez bien sûr qu'en tant que rédacteur d'applications, vous ne pouvez pas appeler glReadPixels car vous n'avez pas accès au contexte OpenGL approprié. Il appartient au déflecteur de surface.

Utilisation de /dev/graphics/fb0 Et similaire

Certains sont tentés d'essayer de lire ces fichiers de périphériques Linux qui représentent le framebuffer. Cependant, il y a trois problèmes:

  • Vous avez besoin de root.
  • Parfois, ils ne sont même pas là.
  • Souvent, ils ne représentent pas l'image réelle de l'écran. Rappelez-vous sur Android que les graphiques sont composés sur le GPU. Il n'y a donc aucune raison pour que le processeur ait accès à une copie de l'image d'écran composite complète, et ce n'est souvent pas le cas. Ce fichier contient parfois des déchirures (au mieux) et une image poubelle (au pire). Fait intéressant, certains des outils pour les téléphones rootés utilisent cette méthode, ce qui, je pense, est une erreur. Si vous avez root, vous avez par définition tout = Android autorisations et peut donc appeler l'API captureScreen ci-dessus pour obtenir une image correcte.

Utilisation de partenaires matériels

Nous entrons maintenant dans les solutions qui nécessitent une action commerciale.

Parler avec les fabricants de chipsets Android présente souvent une solution. Comme ils conçoivent le matériel, ils ont accès au framebuffer - et ils sont souvent capables de fournir des bibliothèques qui évitent complètement le Android modèle d'autorisations en accédant simplement à leurs pilotes de noyau personnalisés directement.

Si vous visez un modèle de téléphone spécifique, c'est souvent une bonne voie à suivre. Bien sûr, les chances sont que vous devrez coopérer avec le fabricant de téléphones ainsi qu'avec le fabricant de silicium.

Parfois, cela peut fournir des résultats exceptionnels . Par exemple, j'ai entendu dire qu'il est possible sur certains matériels de diriger le tampon de trame matériel du téléphone directement dans l'encodeur vidéo H.264 du matériel du téléphone, et de récupérer un flux vidéo pré-encodé de tout ce qui est sur l'écran du téléphone. Exceptionnel. (Malheureusement, je sais seulement que cela est possible sur les puces TI OMAP, qui se retirent progressivement du marché du téléphone ).

Utilisation de trous de sécurité

Android applique de manière rigide son modèle d'autorisation et présente quelques failles de sécurité. Cependant, les OEM Android peuvent parfois être plus négligents.

Par exemple, un grand OEM dont le nom commence par S a mis en place un moyen de capturer l'écran à l'aide d'une touche. Il l'enregistre dans un fichier lisible par le monde sur la carte SD. En théorie, vous pourriez trouver ce qui intercepte ces clés et voir comment cela fonctionne. Vous pourriez peut-être faire quelque chose de similaire.

Et il y a peut-être un moyen pour un autre grand OEM dont le nom commence également par S.

Non, je ne vais pas entrer dans les détails de cette section. Pour savoir comment faire ces choses, j'aurais besoin d'un logiciel de rétro-ingénierie, ce qui pourrait être illégal. Bonne chance cependant.

Travailler avec les fabricants de téléphones

Comme décrit précédemment, les fabricants de téléphones ont un accès facile à une API qui fonctionne . Et les fabricants de téléphones ont les autorisations de niveau signature requises.

Donc, tout ce que vous devez faire est de faire signer votre logiciel par le fabricant de téléphone.

C'est cependant difficile . En signant le logiciel, le fabricant de téléphones garantit sa qualité - il devrait donc vouloir auditer votre code source. De plus, en raison de la nature de Android - s'ils signent le logiciel, ils doivent être ceux qui le distribuent. Vous ne pouvez pas le mettre sur le marché s'il est signé par la signature de quelqu'un d'autre) .

Cependant, l'OEM n'a pas besoin de l'inclure sur le ROM - ils peuvent toujours le distribuer sur le marché Android. Mais vous ne pouvez pas.

Une bonne solution serait que chaque fournisseur signe une petite bibliothèque à laquelle il serait alors possible d'accéder par un SDK commun. Ce qui m'amène à ...

Travailler avec des partenaires logiciels qui ont déjà résolu ce problème

J'en sais beaucoup parce que je travaillais chez RealVNC. Nous avons travaillé avec tous les principaux fournisseurs de téléphones Android pour obtenir l'accès à ces API au niveau de la signature. Je ne saurais trop insister sur les nombreuses années-hommes d'efforts (commerciaux et techniques) nécessaires pour y parvenir. Certains OEM ont rendu public ce travail - par exemple 4 .

Je ne travaille plus chez RealVNC, je n'ai donc rien à gagner à faire la publicité de leur logiciel. Mais si vous voulez vraiment vraiment pouvoir capturer l'écran sur plusieurs appareils Android Android, vous voudrez peut-être vous approcher les sur la réutilisation de leur service de contrôle à distance ou Android SDK VNC 5 . Ce n'est pas open-source, vous devez donc vous attendre à payer, et croyez-moi, c'est juste) assez étant donné l'effort épique impliqué dans le travail avec tous ces OEM Android OEM.

Dans un souci d'équilibre, je dois souligner que d'autres fournisseurs ont également travaillé avec les fabricants de téléphones à ce sujet - par exemple Soti. Mais je pense qu'ils offrent tous des solutions de gestion de périphériques spécifiques, plutôt qu'un SDK général de contrôle à distance/injection d'événements.

Via USB

Une autre option - le démon adb qui écoute le débogage des connexions via USB a légèrement plus de privilèges qu'une application normale, c'est pourquoi il est capable de saisir l'écran (vous pouvez voir son image en utilisant le ddms outil). Si vous pouvez exécuter n'importe quelle commande en utilisant adb, vous pouvez également obtenir ces privilèges (selon la bibliothèque de captures d'écran Android liée précédemment).

Contribuer au projet open-source Android

Finalement, ce problème m'a réduit en poussière, et je suis parti pour des pâturages plus verts qui n'impliquaient pas d'essayer d'extraire les pixels de Android téléphones.

Avant de quitter RealVNC, nous avons à nouveau essayé de contribuer ces API au projet open-source Android. Cette fois, nous avons eu une réaction plus positive 6 . En bref, il a été suggéré que notre approche de la sécurité était presque la bonne, mais que le système graphique était trop perturbé pour accepter nos correctifs. Eh bien, la grande nouvelle est que le système graphique n'est plus en ébullition - en fait, il a maintenant que captureScreen API ce qui signifie qu'aucune modification du système graphique n'est nécessaire, il peut donc être possible de soumettre un nouveau mécanisme de sécurité à l'AOSP autour de cette API qui résout finalement ce problème.

Bonne chance!

107
Adrian Taylor

Peut-être que Android-screenshot-library peut vous aider. Mais bien sur leur page d'utilisation, il dit qu'il a besoin d'un service natif démarré avec adb (à partir du sdk Android)).

PS: N'oubliez pas que Screenshot UX ne fonctionne pas pour tous les téléphones non rootés.

3
DNax