Les API android.media.projection
introduites dans Android 5 (niveau d'API 21) vous permettent de capturer le contenu d'un écran d'appareil en tant que flux multimédia que vous pouvez lire, enregistrer ou caster sur d'autres appareils, comme les téléviseurs.
Android 14 (niveau d'API 34) introduit le partage d'écran d'application, qui permet aux utilisateurs de partager une seule fenêtre d'application au lieu de l'ensemble de l'écran de l'appareil, quel que soit le mode de fenêtrage. Le partage d'écran de l'application exclut la barre d'état, la barre de navigation, les notifications et d'autres éléments d'interface utilisateur du système de l'écran partagé, même lorsque le partage d'écran de l'application est utilisé pour capturer une application en plein écran. Seuls les contenus de l'application sélectionnée sont partagés.
Le partage d'écran de l'application garantit la confidentialité des utilisateurs, améliore leur productivité et améliore le multitâche en leur permettant d'exécuter plusieurs applications, mais en limitant le partage de contenu à une seule application.
Trois représentations d'affichage
Une projection de contenu multimédia capture le contenu d'un écran d'appareil ou d'une fenêtre d'application, puis projette l'image capturée sur un écran virtuel qui affiche l'image sur une Surface
.
L'application fournit cette Surface
au moyen d'un élément MediaRecorder
, SurfaceTexture
ou ImageReader
, qui consomme le contenu de l'écran capturé et vous permet de gérer les images affichées sur la Surface
en temps réel. Vous pouvez conserver les images sous forme d'enregistrement ou les caster sur un téléviseur ou un autre appareil.
Affichage réel
Pour démarrer une session de projection multimédia, vous avez besoin d'un jeton permettant à votre application de capturer le contenu de l'écran de l'appareil ou de la fenêtre de l'application. Le jeton est représenté par une instance de la classe MediaProjection
.
Utilisez la méthode getMediaProjection()
du service système MediaProjectionManager
pour créer une instance MediaProjection
lorsque vous démarrez une nouvelle activité. Démarrez l'activité avec un intent à partir de la méthode createScreenCaptureIntent()
pour spécifier une opération de capture d'écran:
Kotlin
val mediaProjectionManager = getSystemService(MediaProjectionManager::class.java) var mediaProjection : MediaProjection
val startMediaProjection = registerForActivityResult( StartActivityForResult() ) { result -> if (result.resultCode == RESULT_OK) { mediaProjection = mediaProjectionManager .getMediaProjection(result.resultCode, result.data!!) } }
startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent())
Java
final MediaProjectionManager mediaProjectionManager = getSystemService(MediaProjectionManager.class); final MediaProjection[] mediaProjection = new MediaProjection[1];
ActivityResultLauncherstartMediaProjection = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { mediaProjection[0] = mediaProjectionManager .getMediaProjection(result.getResultCode(), result.getData()); } } );
startMediaProjection.launch(mediaProjectionManager.createScreenCaptureIntent());
Écran virtuel
La pièce maîtresse d'une projection multimédia est l'écran virtuel, que vous créez en appelant createVirtualDisplay()
sur une instance MediaProjection
:
Kotlin
virtualDisplay = mediaProjection.createVirtualDisplay( "ScreenCapture", width, height, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null)
Java
virtualDisplay = mediaProjection.createVirtualDisplay( "ScreenCapture", width, height, screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, surface, null, null);
Les paramètres width
et height
spécifient les dimensions de l'écran virtuel. Pour obtenir des valeurs de largeur et de hauteur, utilisez les API WindowMetrics
introduites dans Android 11 (niveau d'API 30). (Pour en savoir plus, consultez la section Taille de la projection multimédia.)
Surface
Dimensionnez la surface de projection multimédia pour que la sortie générée ait la résolution appropriée. Faites en sorte que la surface soit grande (basse résolution) pour caster du contenu sur des écrans de téléviseur ou d'ordinateur, et petite (haute résolution) pour enregistrer le contenu sur l'écran de l'appareil.
Depuis Android 12L (niveau d'API 32), lorsque le système affiche le contenu capturé sur la surface, il le redimensionne de manière uniforme, en conservant le format, de sorte que les deux dimensions du contenu (largeur et hauteur) soient égales ou inférieures aux dimensions correspondantes de la surface. Le contenu capturé est ensuite centré sur la surface.
L'approche de mise à l'échelle d'Android 12L améliore la diffusion de contenu sur les écrans de télévision et autres grands écrans, en maximisant la taille de l'image de la surface, tout en garantissant des proportions correctes.
Autorisation de service de premier plan
Si votre application cible Android 14 ou version ultérieure, le fichier manifeste de l'application doit inclure une déclaration d'autorisation pour le type de service de premier plan mediaProjection
:
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<application ...>
<service
android:name=".MyMediaProjectionService"
android:foregroundServiceType="mediaProjection"
android:exported="false">
</service>
</application>
</manifest>
Démarrez le service de projection multimédia en appelant startForeground()
.
Si vous ne spécifiez pas le type de service de premier plan dans l'appel, le type est défini par défaut sur un entier au niveau du bit des types de services de premier plan définis dans le fichier manifeste. Si le fichier manifeste ne spécifie aucun type de service, le système génère MissingForegroundServiceTypeException
.
Consentement de l'utilisateur
Votre application doit demander le consentement de l'utilisateur avant chaque session de projection multimédia. Une session correspond à un seul appel à createVirtualDisplay()
. Un jeton MediaProjection
ne doit être utilisé qu'une seule fois pour passer l'appel.
Sous Android 14 ou version ultérieure, la méthode createVirtualDisplay()
génère une exception SecurityException
si votre application effectue l'une des opérations suivantes:
- Transmet une instance
Intent
renvoyée decreateScreenCaptureIntent()
àgetMediaProjection()
plusieurs fois - Appels de
createVirtualDisplay()
plusieurs fois sur la même instanceMediaProjection
Taille de la projection multimédia
Une projection multimédia peut capturer l'intégralité de l'écran de l'appareil ou une fenêtre d'application, quel que soit le mode de fenêtrage.
Taille initiale
Avec la projection multimédia en plein écran, votre application doit déterminer la taille de l'écran de l'appareil. Dans le partage d'écran de l'application, votre application ne pourra pas déterminer la taille de l'écran capturé tant que l'utilisateur n'aura pas sélectionné la région de capture. Par conséquent, la taille initiale de toute projection multimédia correspond à la taille de l'écran de l'appareil.
Utilisez la méthode WindowManager
getMaximumWindowMetrics()
de la plate-forme pour renvoyer un objet WindowMetrics
pour l'écran de l'appareil, même si l'application hôte de projection multimédia est en mode multifenêtre et qu'elle n'occupe qu'une partie de l'écran.
Pour assurer la compatibilité des versions remontant jusqu'au niveau d'API 14, utilisez la méthode WindowMetricsCalculator
computeMaximumWindowMetrics()
de la bibliothèque Jetpack WindowManager
.
Appelez la méthode WindowMetrics
getBounds()
pour obtenir la largeur et la hauteur de l'écran de l'appareil.
Changements de taille
La taille de la projection multimédia peut changer lorsque l'appareil est pivoté ou que l'utilisateur sélectionne une fenêtre d'application comme région de capture dans le partage d'écran de l'application. La projection multimédia peut être au format letterbox si le contenu capturé est d'une taille différente des métriques de fenêtre maximales obtenues lors de la configuration de la projection multimédia.
Pour vous assurer que la projection multimédia s'aligne précisément sur la taille du contenu capturé pour toute région capturée et lors des rotations de l'appareil, utilisez le rappel onCapturedContentResize()
pour redimensionner la capture. (Pour en savoir plus, consultez la section Personnalisation ci-dessous.)
Personnalisation
Votre application peut personnaliser l'expérience utilisateur de la projection multimédia à l'aide des API MediaProjection.Callback
suivantes:
onCapturedContentVisibilityChanged()
: permet à l'application hôte (l'application qui a lancé la projection multimédia) d'afficher ou de masquer le contenu partagé.Utilisez ce rappel pour personnaliser l'UI de votre application en fonction de la visibilité de la région capturée par l'utilisateur. Par exemple, si votre application est visible par l'utilisateur et affiche le contenu capturé dans l'UI de l'application, et que l'application capturée est également visible par l'utilisateur (comme indiqué par ce rappel), l'utilisateur voit le même contenu deux fois. Utilisez le rappel pour mettre à jour l'interface utilisateur de votre application afin de masquer le contenu capturé et de libérer de l'espace de mise en page dans votre application pour d'autres contenus.
onCapturedContentResize()
: permet à l'application hôte de modifier la taille de la projection multimédia sur l'écran virtuel et la projection multimédiaSurface
en fonction de la taille de la région d'affichage capturée.Se déclenche chaque fois que le contenu capturé (une seule fenêtre d'application ou l'écran complet de l'appareil) change de taille (en raison de la rotation de l'appareil ou de l'entrée de l'application capturée dans un autre mode de fenêtrage). Utilisez cette API pour redimensionner à la fois l'écran virtuel et la surface afin de vous assurer que le format correspond au contenu capturé et que la capture n'est pas au format letterbox.
Récupération de ressources
Votre application doit enregistrer le rappel MediaProjection
onStop()
pour être informé lorsque la session de projection multimédia est arrêtée et devient non valide. Lorsque la session est arrêtée, votre application doit libérer les ressources qu'elle détient, telles que l'écran virtuel et la surface de projection. Une session de projection multimédia arrêtée ne peut plus créer d'écran virtuel, même si votre application n'a pas encore créé d'écran virtuel pour cette projection multimédia.
Le système appelle le rappel lorsque la projection multimédia se termine. Cette résiliation peut se produire pour plusieurs raisons, par exemple:
- l'utilisateur arrête la session à l'aide de l'UI de l'application ou du chip de barre d'état de la projection multimédia du système ;
- l'écran est verrouillé ;
- une autre session de projection multimédia démarre ;
- le processus de l'application est arrêté
Si votre application n'enregistre pas le rappel, tout appel à createVirtualDisplay()
génère une exception IllegalStateException
.
Désactiver
Android 14 ou version ultérieure active le partage d'écran de l'application par défaut. Chaque session de projection multimédia permet aux utilisateurs de partager une fenêtre d'application ou l'intégralité de l'écran.
Votre application peut désactiver le partage d'écran en appelant la méthode createScreenCaptureIntent(MediaProjectionConfig)
avec un argument MediaProjectionConfig
renvoyé à partir d'un appel à createConfigForDefaultDisplay()
.
Un appel à createScreenCaptureIntent(MediaProjectionConfig)
avec un argument MediaProjectionConfig
renvoyé à partir d'un appel à createConfigForUserChoice()
est identique au comportement par défaut, c'est-à-dire un appel à createScreenCaptureIntent()
.
Applications redimensionnables
Les applications de projection multimédia doivent toujours être redimensionnables (resizeableActivity="true"
). En effet, les applications redimensionnables sont compatibles avec les modifications de configuration des appareils et le mode multifenêtre (voir Compatibilité avec le mode multifenêtre).
Si votre application n'est pas redimensionnable, elle doit déterminer les limites de l'écran dans le contexte d'une fenêtre et utiliser getMaximumWindowMetrics()
pour récupérer la valeur WindowMetrics
de la zone d'affichage maximale disponible pour l'application :
Kotlin
val windowContext = context.createWindowContext(context.display!!, WindowManager.LayoutParams.TYPE_APPLICATION, null) val projectionMetrics = windowContext.getSystemService(WindowManager::class.java) .maximumWindowMetrics
Java
Context windowContext = context.createWindowContext(context.getDisplay(), WindowManager.LayoutParams.TYPE_APPLICATION, null); WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class) .getMaximumWindowMetrics();
Chip de la barre d'état et arrêt automatique
Les failles de projection d'écran exposent des données utilisateur privées telles que des informations financières, car les utilisateurs ne se rendent pas compte que l'écran de leur appareil est partagé.
Android 15 (niveau d'API 35) et versions ultérieures affichent un chip de barre d'état de grande taille et bien visible pour alerter les utilisateurs de toute projection d'écran en cours. Les utilisateurs peuvent appuyer sur le chip pour empêcher le partage, la diffusion ou l'enregistrement de leur écran. De plus, la projection d'écran s'arrête automatiquement lorsque l'écran de l'appareil est verrouillé.
Testez la disponibilité du chip de la barre d'état de la projection multimédia en démarrant le partage d'écran, la diffusion ou l'enregistrement. Le chip doit s'afficher dans la barre d'état.
Pour vous assurer que votre application libère des ressources et met à jour son UI lorsque la projection d'écran est arrêtée par l'interaction de l'utilisateur avec le chip de la barre d'état ou par l'activation de l'écran de verrouillage, procédez comme suit:
Créez une instance de
MediaProjection.Callback
.Implémentez la méthode de rappel
onStop()
. La méthode est appelée lorsque la projection d'écran s'arrête. Libérez toutes les ressources détenues par votre application et mettez à jour l'UI de l'application si nécessaire.
Pour tester le rappel, appuyez sur le chip de la barre d'état ou verrouillez l'écran de l'appareil pour arrêter la projection d'écran. Vérifiez que la méthode onStop()
est appelée et que votre application répond comme prévu.
Ressources supplémentaires
Pour en savoir plus sur la projection multimédia, consultez la section Capturer la lecture vidéo et audio.