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 !