57 votes

Comment prendre une capture d'écran d'une autre application de manière programmatique sans la permission de Root, comme le procès Screenshot UX ?

Comment prendre une capture d'écran d'une autre application de manière programmatique sans la permission de Root, comme le procès Screenshot UX ?

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

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

  2. Il y a une permission pour capturer le tampon de l'image actuelle dans Manifest : android.permission.READ_FRAME_BUFFER . Mais certains sites web disent que c'est uniquement pour l'application de signature.

    Vérifier les autorisations Android - Niveaux de protection

Après avoir essayé l'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 le retour d'information par vibration.
  • WRITE_EXTERNAL_STORAGE : pour sauvegarder la capture d'écran.
  • GET_TASKS : pour détecter l'activité de développement de premier plan pour les méthodes de capture non enracinées et non préchargées.

Il semble que soit SYSTEM_ALERT_WINDOW ou GET_TASKS permettre à l'application de faire des captures d'écran. J'ai deux idées sur la façon dont cela fonctionne :

  1. Il peut être en mesure d'accéder au Activity de l'activité d'avant-plan, il obtient la vue Racine de la Activity capturer sa capture d'écran.
  2. Appel à glreadpixels

Si vous essayez l'une de mes suggestions, faites-moi part du résultat.

118voto

Adrian Taylor Points 1754

C'est extrêmement difficile. J'ai passé plusieurs années à essayer de le faire. J'ai fini par y parvenir, mais toute solution nécessitera des efforts commerciaux et techniques.

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 à l'aide de Bitmap.createBitmap(rootview.getDrawingCache()); et des mécanismes similaires.

Capture de l'écran d'une autre application pendant que vous êtes en arrière-plan

Utilisation de la READ_FRAMEBUFFER autorisation

Tout d'abord, vous avez raison de dire qu'une application normale ne peut pas utiliser l'outil de gestion de l'information. READ_FRAMEBUFFER parce qu'il s'agit d'une permission de niveau "signature". Cela signifie que vous devez être signé par la même clé que la ROM du système Android afin de pouvoir effectuer une telle capture d'écran.

Je trouvais cela un peu triste, alors en 2009, j'ai soumis un projet Android à code source ouvert pour demander son ouverture. 1 . La réponse de Dianne Hackborn, l'architecte Android, a été la suivante :

Um, non. Absolument positivement non.

Donc, ça s'est bien passé, alors ! Donc cette permission est toujours signature -à ce jour.

Cependant, si vous aviez cette permission, vous pourriez appeler la fonction captureScreen membre de ISurfaceComposer 2 . Vous devrez écrire du code natif pour accéder à cette fonction, en utilisant le NDK Android et certaines API non documentées. Cependant, c'est possible.

En interne, dans le sous-système graphique d'Android, cela utilise une fonction glReadPixels pour récupérer les pixels du GPU et les renvoyer au CPU. (Le GPU est utilisé pour la plupart des composites sur Android. En fait, Android 4.0+ supporte 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 peut se briser à tout moment ;
  • La difficulté de l'appeler en C++
  • Cela provoque le blocage des pipelines du GPU, ce qui peut contrarier les concepteurs du GPU mais ne pose pas vraiment de problèmes en réalité.
  • Il s'appuie sur une large bande passante du GPU. arrière à l'unité centrale. Ceci est parfois problématique car les architectures de mémoire sont conçues pour envoyer les données dans la direction opposée. Cependant, je crois me souvenir que toutes les architectures de chipset Android modernes partagent directement la mémoire entre le GPU et le CPU, à l'exception d'une (c'est peut-être Broadcom ? - je ne me souviens plus) où cela peut rendre ce mécanisme 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 de niveau signature requises.

Néanmoins, sur la plupart des appareils Android, vous pouvez obtenir 10 images par seconde. Mieux encore, cette API prend en charge la mise à l'échelle de l'image résultante. en matériel sur le GPU Ainsi, si vous êtes malin, vous pouvez prédimensionner l'image à la taille dont vous avez besoin, avant même que les pixels n'atteignent le CPU. Les performances peuvent donc être extrêmement élevées.

Notez, bien sûr, que vous, en tant que rédacteur d'application, ne pouvez pas appeler glReadPixels parce que vous n'avez pas accès au contexte OpenGL approprié. Il est détenu par la surface flinger.

Utilisation de /dev/graphics/fb0 et similaires

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

  • Tu as 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 que sur Android, les graphiques sont composés sur le GPU. Il n'y a donc aucune raison pour que le CPU ait accès à une copie de l'image complète de l'écran composite, et ce n'est souvent pas le cas. Ce fichier contient parfois des déchirures (au mieux) et une image poubelle (au pire). Il est intéressant de noter que certains outils pour les téléphones rootés utilisent cette méthode, ce qui est à mon avis une erreur. Si vous avez Root, vous avez par définition toutes les permissions Android et pouvez donc appeler l'outil ci-dessus captureScreen API pour obtenir une image correcte.

Utilisation de partenaires matériels

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

S'adresser aux fabricants de puces Android présente souvent une solution. Comme ils conçoivent le matériel, ils ont accès au framebuffer - et ils sont souvent en mesure de fournir des bibliothèques qui évitent entièrement le modèle de permissions Android en accédant simplement et directement à leurs pilotes de noyau personnalisés.

Si vous visez un modèle de téléphone spécifique, c'est souvent une bonne solution. Bien sûr, il est probable que vous devrez coopérer avec le fabricant du téléphone ainsi qu'avec le fabricant du silicium.

Parfois, cela peut fournir exceptionnel résultats. Par exemple, j'ai entendu dire qu'il était possible, sur certains matériels, de faire passer le framebuffer du téléphone directement dans l'encodeur vidéo H.264 du téléphone, et de récupérer un flux vidéo pré-encodé de ce qui est sur l'écran du téléphone. Remarquable. (Malheureusement, je n'ai connaître cela est possible avec les puces TI OMAP, qui se retirent progressivement du marché des téléphones. 3 ).

Utilisation des failles de sécurité

Android applique rigoureusement son modèle de permission et présente peu de failles de sécurité. Cependant, les équipementiers Android peuvent parfois être plus négligents.

Par exemple, un grand équipementier dont le nom commence par S a mis en place un moyen de capturer l'écran à l'aide d'une frappe au clavier. Il l'enregistre dans un fichier lisible par tous sur la carte SD. Hypothétiquement, vous pourriez être en mesure de trouver ce qui intercepte ces touches 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 équipementier dont le nom commence aussi par S.

Non, je ne vais pas entrer dans les détails de cette section. Pour savoir comment faire ces choses, il faudrait que je fasse de la rétro-ingénierie logicielle, 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 fait le travail . Et les fabricants de téléphones ont le signature -Les autorisations de niveau supérieur sont requises.

Il vous suffit donc de faire signer votre logiciel par le fabricant du téléphone.

C'est pourtant le cas, dur . En signant le logiciel, le fabricant du téléphone garantit sa qualité - il devrait donc vouloir vérifier votre code source. De plus, en raison de la nature d'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 quelqu'un d'autre.

Cependant, l'équipementier n'est pas obligé de l'inclure dans la ROM - il peut toujours la distribuer sur le marché Android. Mais vous ne pouvez pas.

Une bonne solution consisterait à ce que chaque fournisseur signe une petite bibliothèque à laquelle on pourrait ensuite accéder par un SDK commun. Ce qui m'amène à...

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

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

I ne fonctionnent pas à RealVNC, je n'ai donc rien à gagner à faire de la publicité pour leur logiciel. Mais si vous vraiment vraiment vous souhaitez pouvoir capturer l'écran de plusieurs appareils Android, vous pouvez leur demander de réutiliser leur service de contrôle à distance ou leur kit SDK Android VNC. 5 . Il ne s'agit pas d'un logiciel libre, vous devez donc vous attendre à payer, et croyez-moi, c'est assez juste étant donné l'effort épique impliqué dans la collaboration avec tous ces OEM Android.

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

Par USB

Une autre option - le adb qui écoute les connexions de débogage via USB a un peu plus de privilèges qu'une application normale, c'est pourquoi il est capable de saisir l'écran (vous pouvez voir son image à l'aide de la commande ddms ). Si vous êtes en mesure d'exécuter n'importe quelle commande en utilisant adb alors vous pouvez vous aussi obtenir ces privilèges (comme dans la bibliothèque Android-screenshot-library liée précédemment).

Contribuer au projet open-source Android

Ce problème a fini par me réduire en poussière, et je suis parti vers des pâturages plus verts qui n'impliquaient pas d'essayer d'extraire des pixels de téléphones Android.

Avant que je ne quitte RealVNC, nous avons essayé une nouvelle fois de contribuer à ces API dans le cadre du 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 correcte, mais que le système graphique était trop chamboulé pour accepter nos correctifs. Eh bien, la bonne nouvelle, c'est que le système graphique n'est plus en proie à l'agitation - en fait, il a maintenant ce qu'il fallait. captureScreen ce qui signifie qu'aucune modification du système graphique n'est nécessaire. Il pourrait donc être possible de soumettre à l'AOSP un nouveau mécanisme de sécurité autour de cette API qui résoudrait enfin ce problème.

Bonne chance !

3voto

DNax Points 414

Peut-être que le Android-screenshot-library peut aider. Mais bon, dans leur page d'utilisation il est dit qu'il faut un service natif démarré avec adb (à partir du sdk Android).

PS : Rappelez-vous que Screenshot UX ne fonctionne pas pour tous les téléphones non enracinés.

0voto

Diederik Points 985

Je ne pense pas qu'Android vous permettra d'accéder au frame buffer d'une autre application. Cela fait partie de la sécurité d'Android. Chaque application doit garder ses propres ressources.

Si vous avez vraiment besoin d'obtenir une capture d'écran d'une application, je vous suggère d'utiliser le "geste" natif de capture d'écran. Pour le Nexus 7 par exemple, il suffit de "... maintenir le bouton d'alimentation et le bouton de réduction du volume en même temps pendant environ 2 secondes".

Une recherche sur Google permet généralement de trouver le truc avec votre appareil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X