Projection multimédia

android.media.projection Les API introduites dans Android 5 (niveau d'API 21) vous permettent de capturer le contenu d'un appareil s'affiche sous forme de flux multimédia sur lequel vous pouvez lire, enregistrer ou caster d'autres appareils, tels que des 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 plutôt que l'intégralité de l'écran de l'appareil, quel que soit le mode fenêtrage. Le partage d'écran d'une appli exclut les éléments suivants : barre d'état, barre de navigation, notifications et autres éléments d'UI du système à partir de l'écran partagé, Lorsque le partage d'écran d'une application est utilisé pour capturer une application en plein écran. Seul le contenu de l'appli sélectionnée est partagé.

Le partage d'écran des applications garantit la confidentialité des utilisateurs, augmente leur productivité et améliore le multitâche en permettant aux utilisateurs d'exécuter plusieurs applications tout en limitant le partage de contenu à une seule application.

Trois représentations d'affichage

Une projection multimédia capture le contenu de l'écran d'un appareil ou de la fenêtre d'une application et projette ensuite l'image capturée sur un écran virtuel qui affiche l'image sur Un Surface.

É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 ou fenêtre de l'application projetée sur un affichage virtuel. Écran virtuel écrit sur l'écran fourni par l'application Surface

L'application fournit le Surface au moyen d'un MediaRecorder, SurfaceTexture ou ImageReader, qui consomme le contenu de l'écran capturé et vous permet de gérer les images affichées sur le Surface en temps réel. Vous pouvez sauvegarder les images en tant qu'enregistrement ou les caster. vers un téléviseur ou un autre appareil.

Affichage réel

Démarrez une session de projection multimédia en obtenant un jeton qui accorde à votre application le Possibilité de capturer le contenu de l'écran de l'appareil ou de la fenêtre de l'application Le jeton est représentée par une instance MediaProjection .

Utilisez la méthode getMediaProjection() de la 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 Méthode createScreenCaptureIntent() pour spécifier un écran opération de capture:

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());
        }
    }
);

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'instance l'écran. Pour obtenir les valeurs de largeur et de hauteur, utilisez les API WindowMetrics introduites sous Android 11 (niveau d'API 30). Pour en savoir plus, consultez les section Taille de la projection multimédia.)

Surface

Dimensionnez la surface de projection multimédia pour produire une sortie de la façon appropriée. la résolution de problèmes. Agrandissez la surface (basse résolution) pour caster du contenu sur un écran écrans d'ordinateur et de petite taille (haute résolution) pour l'enregistrement de l'écran d'un appareil.

À partir d'Android 12L (niveau d'API 32), lors de l'affichage du contenu capturé sur la le système adapte le contenu de manière uniforme, afin que les deux dimensions du contenu (largeur et hauteur) soient égales ou inférieures que les dimensions correspondantes de la surface. Le contenu capturé est ensuite centré sur la surface.

L'approche de scaling d'Android 12L améliore la diffusion d'écran sur les téléviseurs et d'autres grands écrans en maximisant la taille de l'image de la surface tout en garantissant au bon format.

Autorisation de service de premier plan

Si votre application cible Android 14 ou une version ultérieure, son fichier manifeste doit inclure un déclaration d'autorisation pour 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 à un entier bit à 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

Votre application doit demander le consentement de l'utilisateur avant chaque session de projection multimédia. A "session" est un appel unique à createVirtualDisplay(). Un jeton MediaProjection doit être utilisé une seule fois pour passer l'appel.

Sur Android 14 ou version ultérieure, la méthode createVirtualDisplay() génère une SecurityException si votre l'application effectue l'une des opérations suivantes:

  • Transmet plusieurs fois une instance Intent renvoyée par createScreenCaptureIntent() à getMediaProjection().
  • Appelle createVirtualDisplay() plusieurs fois sur le même MediaProjection. Instance

Taille de projection multimédia

Une projection multimédia peut capturer l'intégralité de l'écran de l'appareil ou la fenêtre d'une 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 l'écran de l'appareil. Dans le partage d'écran d'une appli, celle-ci ne pourra pas déterminer la taille de l'écran capturé jusqu'à ce que l'utilisateur sélectionne la région de capture. Ainsi, la taille initiale d'une projection multimédia est la taille de l'écran de l'appareil.

Utiliser la plate-forme WindowManager méthode getMaximumWindowMetrics() pour renvoyer une WindowMetrics pour écran de l'appareil, même si l'application hôte de projection multimédia est en mode multifenêtre et n'occupe qu'une partie de l'écran.

Pour assurer la compatibilité jusqu'au niveau d'API 14, utilisez l'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 vous faites pivoter l'appareil. ou bien l'utilisateur sélectionne une fenêtre d'application comme région de capture lors du partage d'écran de l'application. La projection multimédia peut être au format letterbox si le contenu capturé est un de taille différente de celle des métriques de fenêtre maximale obtenues lorsque le média la projection a été configurée.

Pour que la projection multimédia s'aligne précisément sur la taille de l'image capturée pour chaque zone capturée et lors des rotations d'appareil, utilisez la Rappel onCapturedContentResize() pour redimensionner la capture. (Pour plus d'informations informations, consultez la section Personnalisation ci-dessous).

Personnalisation

Votre application peut personnaliser l'expérience utilisateur de la projection multimédia à l'aide des éléments suivants : API MediaProjection.Callback:

  • onCapturedContentVisibilityChanged(): Permet à l'application hôte (celle qui a démarré la projection multimédia) d'afficher ou de masquer le contenu partagé.

    Utilisez ce rappel pour personnaliser l'interface utilisateur de votre application en fonction de la est visible par l'utilisateur. Par exemple, si votre application est visible utilisateur et qui affiche le contenu capturé dans l'interface utilisateur de l'application. application capturée est également visible par l'utilisateur (comme indiqué dans ce ), l'utilisateur voit le même contenu deux fois. Utiliser le rappel pour mettre à jour l'interface utilisateur de votre application pour masquer le contenu capturé et libérer de l'espace de mise en page dans votre pour d'autres contenus.

  • onCapturedContentResize(): Permet à l'application hôte de modifier la taille de la projection multimédia sur l'appareil d'affichage et de projection multimédia Surface en fonction de la taille de l'élément capturé la région d'affichage.

    Déclenchement à chaque fois que le contenu capturé est affiché (une fenêtre d'application unique ou complète) l'écran de l'appareil : change de taille (en raison de la rotation de l'appareil ou de la capture l'application qui passe dans un autre mode de fenêtrage). Cette API vous permet de redimensionner la surface et l'écran virtuels pour garantir que le format correspond à celui et que la capture n'est pas au format letterbox.

Récupération des ressources

Votre application doit enregistrer MediaProjection onStop() rappel pour être informé lorsque la session de projection multimédia est arrêtée et qu'elle devient non valide. Lorsque la session est arrêtée, votre application doit libérer les ressources qu'il contient, comme l'écran virtuel et la surface de projection. A arrêté la session de projection multimédia 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 rappel est appelé lorsque la projection multimédia se termine, soit parce que le l'utilisateur met fin manuellement à la session, ou parce que le système l'arrête pour une raison quelconque.

Si votre application n'enregistre pas le rappel, tout appel à createVirtualDisplay() lance IllegalStateException

Désactiver

Android 14 ou version ultérieure active le partage d'écran des applications par défaut. Chaque support permet aux utilisateurs de partager une fenêtre d'application ou la l'intégralité de l'écran.

Votre application peut désactiver le partage d'écran des applications en appelant la méthode Méthode createScreenCaptureIntent(MediaProjectionConfig) avec un argument MediaProjectionConfig renvoyé par un appel à createConfigForDefaultDisplay()

Un appel à createScreenCaptureIntent(MediaProjectionConfig) avec une L'argument MediaProjectionConfig renvoyé par un appel à createConfigForUserChoice() est identique comme comportement par défaut, c'est-à-dire un appel createScreenCaptureIntent().

Applications redimensionnables

Vos applications de projection multimédia doivent toujours être redimensionnables (resizeableActivity="true"). Redimensionnable sont compatibles avec les modifications de configuration de l'appareil et le mode multifenêtre (voir Compatibilité avec le mode multifenêtre).

Si votre application n'est pas redimensionnable, elle doit interroger les limites d'affichage dans une fenêtre. et utiliser getMaximumWindowMetrics() pour récupérer le 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();

Ressources supplémentaires

Pour en savoir plus sur la projection multimédia, consultez la section Capturer la lecture vidéo et audio.