Les API de projection multimédia ajoutées 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.
Une projection de contenu multimédia implique trois représentations de l'écran de l'appareil :

Surface
fournie par l'application.
Une projection de contenu multimédia capture le contenu d'un écran d'appareil, 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 SurfaceView
ou ImageReader
, qui consomme le contenu de l'écran capturé. L'élément OnImageAvailableListener
d'un objet ImageReader
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.
MediaProjection
Pour démarrer une session de projection multimédia, vous avez besoin d'un jeton permettant à l'application de capturer le contenu à afficher et/ou l'audio de l'appareil. Ce jeton est représenté par une instance de la classe MediaProjection
. Vous pouvez créer une instance de cette classe lorsque vous démarrez une nouvelle activité.
Ancienne approche
Pour vous procurer un jeton de projection multimédia à l'aide de l'ancienne approche, appelez startActivityForResult()
avec un intent renvoyé par la méthode createScreenCaptureIntent()
du service système MediaProjectionManager
:
Kotlin
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION)
Java
startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
L'appel affiche une boîte de dialogue de confirmation informant l'utilisateur que la projection multimédia capture toutes les informations affichées, y compris les informations sensibles ou personnelles.
Si l'utilisateur fournit une confirmation, startActivityForResult()
transmet un code de résultat et des données au rappel onActivityResult()
.
Vous pouvez ensuite transmettre ces données et le code de résultat à la méthode getMediaProjection()
à partir de MediaProjectionManager
pour créer une instance MediaProjection
:
Kotlin
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData)
Java
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, resultData);
Approche recommandée
L'approche recommandée pour obtenir un jeton de projection multimédia repose sur les API de la bibliothèque Jetpack Activity :
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]; ActivityResultLauncher<Intent> startMediaProjection = registerForActivityResult( new StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { mediaProjection[0] = mediaProjectionManager .getMediaProjection(result.getResultCode(), result.getData()); } } );
É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 la largeur et la hauteur de l'écran virtuel. Pour obtenir des valeurs correspondant à la largeur et à la hauteur de la projection multimédia, utilisez les API WindowMetrics
ajoutées dans Android 11 (niveau d'API 30).
WindowMetrics
Que l'application qui crée la projection multimédia s'exécute en plein écran ou en mode multifenêtre, la projection multimédia capture l'intégralité de l'écran.
Pour obtenir les dimensions d'une projection multimédia, utilisez WindowManager#getMaximumWindowMetrics()
, qui renvoie un objet WindowMetrics
correspondant à l'intégralité de l'écran, même si l'application de projection multimédia est en mode multifenêtre et qu'elle n'occupe donc qu'une partie de l'écran.
Pour assurer la compatibilité des versions remontant jusqu'au niveau d'API 14, utilisez WindowMetricsCalculator#computeMaximumWindowMetrics()
de la bibliothèque Jetpack WindowManager.
Appelez WindowMetrics#getBounds()
pour obtenir la largeur et la hauteur appropriées de l'écran virtuel pour la projection multimédia (voir la section Écran virtuel).
Les applications de projection multimédia doivent toujours être redimensionnables. 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 récupérer la valeur WindowMetrics
de la zone d'affichage maximale disponible pour l'application à l'aide de WindowManager#getMaximumWindowMetrics()
:
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();
Surface
Vous devez dimensionner la surface de projection multimédia pour que la sortie générée ait la résolution souhaitée. Faites en sorte que la taille 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 la version 12L (niveau d'API 32), lorsque le système affiche un écran virtuel sur la surface, la taille de cet écran est adaptée à la surface grâce à un processus semblable à l'option centerInside
d'ImageView
.
Cette nouvelle approche de mise à l'échelle, qui améliore la diffusion de contenu sur les écrans de télévision et autres grands écrans, maximise la taille d'image de la surface, tout en garantissant des proportions correctes.
Recommandations
Pour obtenir des résultats optimaux avec la projection multimédia, suivez ces recommandations :
- Faites en sorte que votre application puisse être redimensionnée. 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). Dans le fichier manifeste de votre application, spécifiez
resizeableActivity="true"
. Sur Android 7.0 (niveau d'API 24) ou version ultérieure, ce paramètre est défini sur "true" par défaut. - Autorisez les applications à accepter les orientations paysage et portrait, car elles sont courantes sur les téléphones, les tablettes et les appareils pliables.
- Utilisez
WindowManager#getMaximumWindowMetrics()
pour déterminer les limites d'une projection multimédia. Pour assurer la compatibilité des versions remontant jusqu'au niveau d'API 14, utilisez la bibliothèque Jetpack WindowManager. Consultez la section WindowMetrics. - Si votre application n'est pas redimensionnable, déterminez les limites de projection multimédia dans le contexte d'une fenêtre. Consultez la section WindowMetrics.
Ressources supplémentaires
Pour en savoir plus sur la projection multimédia, consultez la section Capturer la lecture vidéo et audio.