Projection multimédia

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

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 :

Écran réel de l'appareil projeté sur l'écran virtuel Contenu de l'écran virtuel écrit sur la "surface" fournie par l'application
Figure 1. Écran réel de l'appareil projeté sur l'écran virtuel. Contenu de l'écran virtuel écrit dans la 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);

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.