Contrôler des contenus multimédias via MediaSession

Dernière mise à jour : 09/09/2020

Quel avantage y a-t-il à ajouter MediaSession pour la lecture de vidéos ?

Les sessions multimédias constituent un lien essentiel entre la plate-forme Android et les applications multimédias. Elles permettent non seulement d'informer Android que le contenu multimédia est en cours de lecture (de sorte qu'il puisse transmettre les actions multimédias vers la bonne session), mais aussi d'indiquer à la plate-forme le contenu en cours de lecture et la façon dont il peut être contrôlé.

La présentation d'une MediaSession via votre application peut présenter divers avantages pour les utilisateurs. Découvrez ci-dessous quelques exemples intéressants.

Assistant Google

Les utilisateurs peuvent facilement interagir avec les contenus multimédias dans votre application grâce aux commandes vocales, comme "Mets en pause", "Reprends la lecture" ou "Suivant". Les métadonnées de votre contenu multimédia peuvent aussi être utilisées pour en savoir plus sur le contenu en cours de lecture.

Android TV

Pour diffuser un contenu multimédia sur un téléviseur, l'utilisateur peut contrôler votre application Android TV à l'aide de sa télécommande classique, si son téléviseur est compatible HDMI-CEC. Les commandes envoyées par les boutons "Lecture/Pause", "Arrêt", "Suivant" et "Précédent" sont transmises à votre application.

Commandes multimédias à l'écran

À partir d'Android 4.0 (niveau d'API 14), le système peut accéder à l'état de lecture et aux métadonnées d'une session multimédia. Cette fonctionnalité permet à l'écran de verrouillage d'afficher des commandes multimédias et des illustrations. Ce comportement varie selon la version d'Android.

Éléments multimédias en arrière-plan

Le contenu multimédia peut être contrôlé dans n'importe lequel de ces scénarios, même si l'application qui le diffuse s'exécute en arrière-plan.

Informatique ambiante

Le fait de présenter vos contenus multimédias avec des données portant sur le contenu en cours de lecture et sur la façon dont il peut être contrôlé peut permettre de créer des liaisons entre les différents appareils. Ainsi, les utilisateurs peuvent interagir avec vos contenus multimédias de plusieurs manières.

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez rendre des sessions multimédias compatibles dans l'exemple ExoPlayer existant. Ainsi, votre application :

  • reflétera correctement l'état actif de la session multimédia ;
  • relaiera les commandes multimédias à ExoPlayer ;
  • transmettra à la session multimédia les métadonnées des éléments de la file d'attente.

Points abordés

  • Pourquoi les sessions multimédias enrichissent-elles l'expérience utilisateur ?
  • Créer une session multimédia et gérer son état
  • Connecter une session multimédia à ExoPlayer
  • Inclure à la session multimédia des métadonnées d'éléments dans la file d'attente de lecture
  • Ajouter des actions (personnalisées)

Cet atelier de programmation est consacré au SDK MediaSession. Les concepts et les blocs de code non pertinents (y compris des détails sur la mise en œuvre d'ExoPlayer) ne sont pas abordés, mais vous sont fournis afin que vous puissiez simplement les copier et les coller.

Prérequis

  • Une version récente d'Android Studio (3.5 ou version ultérieure)
  • Connaissances de base du développement d'applications Android

Quel est notre point de départ ?

Notre point de départ est la version de démonstration principale d'ExoPlayer. Celle-ci contient des vidéos avec des commandes de lecture à l'écran, mais elle n'utilise pas de sessions multimédias prêtes à l'emploi. C'est donc la version idéale pour se lancer et en ajouter !

Obtenir l'exemple ExoPlayer

Commençons par l'exemple ExoPlayer. Clonez le dépôt GitHub depuis le lien ci-dessous.

Cloner l'exemple ExoPlayer

Ouvrir la version de démonstration

Dans Android Studio, ouvrez le projet de démo principal situé sous demos/main.

Android Studio vous invitera à spécifier le chemin d'accès au SDK. Si vous rencontrez des problèmes, vous pouvez suivre les recommandations concernant la mise à jour de l'IDE et des SDK Tools.

10e3b5c652186d57.png

Mettez Gradle à jour si vous êtes invité à utiliser la dernière version.

Prenez quelques instants pour vous familiariser avec les principes de conception de l'application. Notez qu'il existe deux activités : SampleChooserActivity et PlayerActivity. Nous allons consacrer le reste de l'atelier de programmation à PlayerActivity, dans lequel le contenu multimédia est réellement diffusé. Ouvrez ce cours et passez à la section suivante.

Créer la session multimédia

Ouvrez PlayerActivity.java. Cette classe crée ExoPlayer et gère ses fonctions, telles que le rendu des vidéos à l'écran. Dans cette activité, nous allons connecter ExoPlayer à une session multimédia.

Déclarez les deux champs suivants en haut de la classe. Nous les utiliserons tout au long de cette section.

private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;

Vous devez ajouter la dépendance du projet "extension-mediasession" au fichier build.gradle au niveau du module pour "Module: demo" :

implementation project(path: ':extension-mediasession')

Notez qu'Android Studio peut vous aider à ajouter automatiquement cette dépendance si vous passez la souris sur l'erreur liée à la résolution de MediaSessionConnector :

60055e4ad54fbb97.png

Enfin, résolvez les importations de classes en ajoutant le code suivant :

import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;

Une fois l'activité générée, nous devons créer une session multimédia et un connecteur de session multimédia servant d'intermédiaire entre la session multimédia et ExoPlayer.

Le meilleur endroit pour l'insérer est là où ExoPlayer est également créé. Dans notre application de démonstration, nous pouvons ajouter notre code à la fin de initializePlayer(). Veillez à ajouter cette logique après que le lecteur est instancié.

private void initializePlayer() {
  if (player == null) {
    ...
    player = ...
    ...
    mediaSession = new MediaSessionCompat(this, "sample");
    mediaSessionConnector = new MediaSessionConnector(mediaSession);
    mediaSessionConnector.setPlayer(player);
  }
  ...
}

Débloquer la session multimédia

Débloquez la session multimédia lorsqu'elle n'est plus nécessaire. Lorsque nous débloquons ExoPlayer dans releasePlayer(), nous pouvons également inclure le code suivant pour cela :

private void releasePlayer() {
  if (mediaSession != null) {
    mediaSession.release();
  }
  ...
}

Gérer l'état de la session multimédia

Maintenant que nous avons instancié la session multimédia, nous devons nous assurer que son état est correctement pris en compte lorsque l'utilisateur interagit avec l'activité.

Lorsque l'utilisateur démarre l'activité, la session multimédia doit s'activer :

@Override
public void onStart() {
  ...
  if (mediaSession != null) {
    mediaSession.setActive(true);
  }
}

Comme notre application ne lit pas de contenus multimédias en arrière-plan, il est important de s'assurer que la session multimédia se désactive lorsque l'utilisateur quitte l'activité :

@Override
public void onStop() {
  super.onStop();
  if (mediaSession != null) {
    mediaSession.setActive(false);
  }
  ...
}

Exécuter la version de démonstration

  1. Associez un appareil Android ou démarrez un émulateur.
  2. Assurez-vous que "demo" est sélectionné pour s'exécuter depuis la barre d'outils d'Android Studio cb1ec4e50886874f.png.
  3. Cliquez sur 9d8fb3a9ddf12827.png dans la barre d'outils d'Android Studio.
  4. Une fois l'application lancée sur votre appareil, sélectionnez un flux vidéo à lire.
  5. Lorsque la lecture a commencé, essayez les commandes adb suivantes pour contrôler la session multimédia : adb shell media dispatch pauseadb shell media dispatch playadb shell media dispatch play-pauseadb shell media dispatch fast-forwardadb shell media dispatch rewind.
  1. Examinez également comment Android voit votre session multimédia en exécutant le code suivant : adb shell dumpsys media_session.
  2. Si vous utilisez un appareil physique doté d'un micro, essayez d'appeler l'Assistant Google et d'utiliser des commandes vocales comme "Mets en pause", "Reprends la lecture" ou "Avance rapide de 1 minute".

b8dda02a6fb0f6a4.pngExemple d'ExoPlayer s'exécutant sur Android TV

Nous pouvons maintenant utiliser les fonctionnalités compatibles de notre session multimédia là où nous avions créé notre MediasessionConnector dans initializePlayer().

Ajouter TimelineQueueNavigator

ExoPlayer représente la structure des contenus multimédias sous la forme d'une chronologie. Pour en savoir plus sur son fonctionnement, consultez ces informations sur l'objet Timeline d'ExoPlayer. Cette structure nous permet de rester informés de l'évolution du contenu et de présenter les métadonnées du contenu en cours de lecture lorsque nous y sommes invités.

Pour ce faire, nous allons définir TimelineQueueNavigator. Localisez l'instanciation de MediaSessionConnector dans initializePlayer() et ajoutez une implémentation de TimelineQueueNavigator après l'initialisation de mediaSession.

mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
  @Override
  public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
    return new MediaDescriptionCompat.Builder()
            .setTitle("MediaDescription title")
            .setDescription("MediaDescription description for " + windowIndex)
            .setSubtitle("MediaDescription subtitle")
            .build();
  }
});

Résolvez les importations de classes en ajoutant le code suivant :

import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;

Notez que le paramètre windowIndex correspond à l'élément de cet index dans la file d'attente de lecture.

Maintenant que vous avez ajouté des métadonnées, vous pouvez vérifier que l'Assistant identifie le contenu en cours de lecture. Lancez une vidéo sur Android TV, appelez l'Assistant et demandez "Qu'est-ce qui est diffusé ?".

6c7fc0cb853cbc38.png

Votre lecteur n'accepte pas certaines actions ou vous souhaitez en inclure d'autres ? Regardons de plus près la session multimédia dans laquelle nous avons créé notre MediaSessionConnector dans initializePlayer().

Déclarer des actions acceptées

Utilisez mediaSessionConnector.setEnabledPlaybackActions() pour personnaliser les actions que la session multimédia doit accepter.

Voici l'ensemble des actions disponibles :

mediaSessionConnector.setEnabledPlaybackActions(
        PlaybackStateCompat.ACTION_PLAY_PAUSE
                | PlaybackStateCompat.ACTION_PLAY
                | PlaybackStateCompat.ACTION_PAUSE
                | PlaybackStateCompat.ACTION_SEEK_TO
                | PlaybackStateCompat.ACTION_FAST_FORWARD
                | PlaybackStateCompat.ACTION_REWIND
                | PlaybackStateCompat.ACTION_STOP
                | PlaybackStateCompat.ACTION_SET_REPEAT_MODE
                | PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);

Voyons à nouveau comment ces données sont présentées sur la plate-forme :

  1. Comme tout à l'heure, lancez une vidéo.
  2. Examinez comment Android voit les métadonnées de votre session multimédia en exécutant la commande suivante : adb shell dumpsys media_session.
  3. Recherchez la ligne contenant les métadonnées, puis vérifiez que le titre et la description sont inclus et associés à com.google.android.exoplayer2.demo/sample.

Ajouter des actions

Nous pouvons ajouter quelques actions à notre session multimédia. Dans cette section, nous n'ajouterons que la compatibilité des sous-titres.

Rendre les sous-titres compatibles

En ajoutant la compatibilité des sous-titres aux sessions multimédias, vous permettrez aux utilisateurs de les activer par commande vocale. À l'endroit où vous avez initialisé le connecteur de session multimédia, ajoutez le code suivant :

mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
      @Override
      public void onSetCaptioningEnabled(Player player, boolean enabled) {
        Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
      }

      @Override
      public boolean hasCaptions(Player player) {
        return true;
      }

      @Override
      public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
        return false;
      }
    }
);

Enfin, résolvez toutes les importations manquantes.

Vous pouvez effectuer un essai en appelant l'Assistant Google sur Android TV et en disant "Active les sous-titres". Consultez Logcat pour voir comment cet appel est intégré dans votre code.

Félicitations, vous avez correctement ajouté des sessions multimédias à l'exemple !

Vous pouvez bénéficier de très nombreuses fonctionnalités :

  • en ajoutant une session multimédia ;
  • en connectant des sessions multimédias à une instance d'ExoPlayer ;
  • en ajoutant des métadonnées et des actions.

Vous connaissez maintenant les étapes clés requises pour enrichir une application multimédia et proposer aux utilisateurs une expérience plus variée.

Dernière remarque

Cet atelier de programmation s'appuie sur un exemple issu du code source d'ExoPlayer. Il n'est pas nécessaire d'utiliser ExoPlayer à partir de la source. À la place, nous vous recommandons d'extraire les dépendances d'ExoPlayer et de MediaSessionConnector afin de recevoir plus facilement les dernières versions.

Pour ce faire, remplacez simplement les dépendances du projet, par exemple :

implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')

pour effectuer une extraction depuis les dépôts Maven, par exemple :

implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'

Documents de référence