Présentation de MediaRouteProvider

Le framework du routeur multimédia Android permet aux fabricants d'activer la lecture sur leurs appareils. via une interface standardisée appelée MediaRouteProvider. Un fournisseur de routes définit une interface commune pour lire des contenus multimédias sur un appareil récepteur, ce qui possible de lire des contenus multimédias sur votre équipement à partir de n'importe quelle application Android compatible routes.

Ce guide explique comment créer un fournisseur de routage multimédia pour un appareil récepteur et le rendre pour les autres applications de lecture de contenus multimédias fonctionnant sous Android. Pour utiliser cette API, vous devez vous devez connaître les classes clés MediaRouteProvider, MediaRouteProviderDescriptor RouteController

Présentation

Le framework du routeur multimédia Android permet aux développeurs d'applications multimédias et aux appareils de lecture de contenus multimédias aux fabricants de se connecter via une API et une interface utilisateur communes. Les développeurs d'applications qui implémenter une interface MediaRouter peut alors se connecter un framework et de lire du contenu sur les appareils qui participent au cadre du routeur multimédia. Multimédia Les fabricants d'appareils de lecture peuvent participer au framework en publiant un MediaRouteProvider qui permet à d'autres applications de se connecter à lire des contenus multimédias sur les récepteurs. La figure 1 montre comment une application se connecte à un récepteur via le framework de routeur multimédia.

Figure 1 : Présentation de la manière dont les classes du fournisseur d'itinéraires multimédias permettent la communication depuis une application multimédia vers un appareil récepteur.

Lorsque vous créez un fournisseur de routage multimédia pour votre appareil récepteur, le fournisseur diffuse le aux fins suivantes:

  • Décrire et publier les fonctionnalités de l'appareil récepteur afin que d'autres applications puissent le découvrir et utiliser ses fonctionnalités de lecture.
  • Encapsuler l'interface de programmation du dispositif récepteur et ses communications des mécanismes de transport pour rendre le périphérique compatible avec le cadre du routeur multimédia.

Répartition des fournisseurs d'itinéraires

Un fournisseur de routage multimédia est distribué dans le cadre d'une application Android. Votre fournisseur d'itinéraires peut être à d'autres applications en étendant MediaRouteProviderService ou encapsuler votre implémentation de MediaRouteProvider avec votre propre service et déclarer un intent. filtre pour le fournisseur de routage multimédia. Ces étapes permettent à d'autres applications de découvrir et d'utiliser votre route multimédia.

Remarque:L'application contenant le fournisseur de routage multimédia peut également inclure un l'interface MediaRouter au via un fournisseur d'itinéraires, mais ce n'est pas obligatoire.

Bibliothèque Support MediaRouter

Les API de routeur multimédia sont définies dans Bibliothèque AndroidX MediaRouter Vous devez ajouter cette bibliothèque à votre projet de développement d'applications. Pour en savoir plus sur l'ajout de bibliothèques Support à votre consultez Configuration de la bibliothèque Support.

Attention:Veillez à utiliser l'AndroidX la mise en œuvre du cadre du routeur multimédia. N'utilisez pas l'ancien package android.media.

Créer un service de fournisseur

Le framework du routeur multimédia doit pouvoir détecter votre fournisseur de routage multimédia et s'y connecter pour permettre à d’autres applications d’utiliser votre route. Pour ce faire, le framework de routeur multimédia recherche les applications qui déclarent une action d'intent du fournisseur de routage multimédia. Lorsqu'une autre application souhaite se connecter à votre fournisseur, le framework doit pouvoir l'appeler et s'y connecter. Votre fournisseur doit être encapsulé dans un Service.

L'exemple de code suivant montre la déclaration d'un service de fournisseur d'itinéraires multimédias et un filtre d'intent dans un fichier manifeste, ce qui permet au routeur multimédia de le découvrir et de l'utiliser framework:

<service android:name=".provider.SampleMediaRouteProviderService"
    android:label="@string/sample_media_route_provider_service"
    android:process=":mrp">
    <intent-filter>
        <action android:name="android.media.MediaRouteProviderService" />
    </intent-filter>
</service>

Cet exemple de fichier manifeste déclare un service qui encapsule les classes réelles du fournisseur de routage multimédia. Le framework du routeur multimédia Android fournit MediaRouteProviderService à utiliser comme wrapper de service pour et des fournisseurs d'itinéraires multimédias. L'exemple de code suivant montre comment utiliser ce wrapper classe:

Kotlin

class SampleMediaRouteProviderService : MediaRouteProviderService() {

    override fun onCreateMediaRouteProvider(): MediaRouteProvider {
        return SampleMediaRouteProvider(this)
    }
}

Java

public class SampleMediaRouteProviderService extends MediaRouteProviderService {

    @Override
    public MediaRouteProvider onCreateMediaRouteProvider() {
        return new SampleMediaRouteProvider(this);
    }
}

Spécifier des fonctionnalités de routage

Les applications qui se connectent au routeur multimédia peuvent détecter votre routage multimédia via votre les déclarations du fichier manifeste de l'application, mais elles doivent également connaître les capacités des routages multimédias fournissent. Les routes multimédias peuvent être de différents types et avoir différentes fonctionnalités, ainsi que d'autres applications doivent pouvoir découvrir ces informations pour déterminer s'ils sont compatibles avec votre itinéraire.

Le framework de routeur multimédia vous permet de définir et de publier les fonctionnalités de votre contenu multimédia via des objets IntentFilter, des objets MediaRouteDescriptor et un MediaRouteProviderDescriptor. Cette section explique comment utiliser ces pour publier les détails de votre route multimédia pour d'autres applications.

Catégories de routes

Dans la description programmatique de votre fournisseur de routage multimédia, vous devez spécifier si votre fournisseur prend en charge la lecture à distance, la sortie secondaire ou les deux. Voici l'itinéraire catégories fournies par le framework de routeur multimédia:

  • CATEGORY_LIVE_AUDIO : sortie du contenu audio sur un périphérique de sortie secondaire, tel qu'un système de musique sans fil
  • CATEGORY_LIVE_VIDEO — Sortie de la vidéo sur un périphérique de sortie secondaire, comme un appareil d'affichage sans fil
  • CATEGORY_REMOTE_PLAYBACK : lit des vidéos ou des fichiers audio sur un appareil distinct qui gère les contenus multimédias de récupération, de décodage et de lecture, Appareils Chromecast.

Pour inclure ces paramètres dans la description de votre routage multimédia, vous devez les insérer dans Un objet IntentFilter, que vous ajouterez par la suite Objet MediaRouteDescriptor:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            arrayListOf(this)
        }
    }
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
}

Si vous spécifiez l'intent CATEGORY_REMOTE_PLAYBACK, vous devez également définir quels types de médias et quels les commandes de lecture sont compatibles avec votre fournisseur de routage multimédia. La section suivante explique comment spécifiez ces paramètres pour votre appareil.

Types de médias et protocoles

Un fournisseur d'itinéraires multimédias pour un appareil de lecture à distance doit spécifier les types de contenus multimédias et le transfert qu'il prend en charge. Vous spécifiez ces paramètres à l'aide de l'IntentFilter ainsi que addDataScheme() et addDataType() de cet objet. La L'extrait de code suivant montre comment définir un filtre d'intent pour prendre en charge des vidéos distantes. HTTP, HTTPS et RTSP (Real Time Streaming Protocol):

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {

        private fun IntentFilter.addDataTypeUnchecked(type: String) {
            try {
                addDataType(type)
            } catch (ex: IntentFilter.MalformedMimeTypeException) {
                throw RuntimeException(ex)
            }
        }

        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            addAction(MediaControlIntent.ACTION_PLAY)
            addDataScheme("http")
            addDataScheme("https")
            addDataScheme("rtsp")
            addDataTypeUnchecked("video/*")
            arrayListOf(this)
        }
    }
    ...
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {

    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;

    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
        videoPlayback.addDataScheme("http");
        videoPlayback.addDataScheme("https");
        videoPlayback.addDataScheme("rtsp");
        addDataTypeUnchecked(videoPlayback, "video/*");
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
    ...

    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
        try {
            filter.addDataType(type);
        } catch (MalformedMimeTypeException ex) {
            throw new RuntimeException(ex);
        }
    }
}

Commandes de lecture

Un fournisseur d'itinéraires multimédias qui propose la lecture à distance doit spécifier les types de commandes multimédias qu'il prend en charge. Voici les principaux types de contrôle que les routes multimédias peuvent fournir:

  • Commandes de lecture, comme lecture, pause, retour arrière et avance rapide
  • Les fonctionnalités de mise en file d'attente, qui permettent à l'application émettrice d'ajouter et de supprimer des éléments à partir d'une liste de lecture gérée par le dispositif récepteur.
  • Les fonctionnalités de session, qui empêchent l'envoi d'applications d'interférer avec chacune en demandant à l'appareil récepteur de fournir un identifiant de session à l'application à l'origine de la demande, puis en vérifiant lors de chaque nouvelle requête de commande de lecture.

L'exemple de code suivant montre comment créer un filtre d'intent pour prendre en charge commandes de lecture de l'itinéraire multimédia de base:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        ...
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = run {
            val videoPlayback: IntentFilter = ...
            ...
            val playControls = IntentFilter().apply {
                addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                addAction(MediaControlIntent.ACTION_SEEK)
                addAction(MediaControlIntent.ACTION_GET_STATUS)
                addAction(MediaControlIntent.ACTION_PAUSE)
                addAction(MediaControlIntent.ACTION_RESUME)
                addAction(MediaControlIntent.ACTION_STOP)
            }
            arrayListOf(videoPlayback, playControls)
        }
    }
    ...
}

Java

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        ...
        IntentFilter playControls = new IntentFilter();
        playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        playControls.addAction(MediaControlIntent.ACTION_SEEK);
        playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
        playControls.addAction(MediaControlIntent.ACTION_PAUSE);
        playControls.addAction(MediaControlIntent.ACTION_RESUME);
        playControls.addAction(MediaControlIntent.ACTION_STOP);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
        CONTROL_FILTERS_BASIC.add(playControls);
    }
    ...
}

Pour en savoir plus sur les intents de commande de lecture disponibles, consultez les MediaControlIntent.

MediaRouteProviderDescriptor

Après avoir défini les fonctionnalités de votre routage multimédia à l'aide d'objets IntentFilter, vous pouvez créer un objet descripteur à publier dans le framework de routeur multimédia Android. Cet objet descripteur contient les caractéristiques de votre contenu multimédia. pour permettre à d'autres applications de déterminer comment interagir avec votre contenu multimédia. via un routage réseau.

L'exemple de code suivant montre comment ajouter les filtres d'intent créés précédemment à un MediaRouteProviderDescriptor et définir le descripteur à utiliser par le framework du routeur multimédia:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    init {
        publishRoutes()
    }

    private fun publishRoutes() {
        val resources = context.resources
        val routeName: String = resources.getString(R.string.variable_volume_basic_route_name)
        val routeDescription: String = resources.getString(R.string.sample_route_description)
        // Create a route descriptor using previously created IntentFilters
        val routeDescriptor: MediaRouteDescriptor =
                MediaRouteDescriptor.Builder(VARIABLE_VOLUME_BASIC_ROUTE_ID, routeName)
                        .setDescription(routeDescription)
                        .addControlFilters(CONTROL_FILTERS_BASIC)
                        .setPlaybackStream(AudioManager.STREAM_MUSIC)
                        .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
                        .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
                        .setVolumeMax(VOLUME_MAX)
                        .setVolume(mVolume)
                        .build()
        // Add the route descriptor to the provider descriptor
        val providerDescriptor: MediaRouteProviderDescriptor =
                MediaRouteProviderDescriptor.Builder()
                        .addRoute(routeDescriptor)
                        .build()

        // Publish the descriptor to the framework
        descriptor = providerDescriptor
    }
    ...
}

Java

public SampleMediaRouteProvider(Context context) {
    super(context);
    publishRoutes();
}

private void publishRoutes() {
    Resources r = getContext().getResources();
    // Create a route descriptor using previously created IntentFilters
    MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
            VARIABLE_VOLUME_BASIC_ROUTE_ID,
            r.getString(R.string.variable_volume_basic_route_name))
            .setDescription(r.getString(R.string.sample_route_description))
            .addControlFilters(CONTROL_FILTERS_BASIC)
            .setPlaybackStream(AudioManager.STREAM_MUSIC)
            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
            .setVolumeMax(VOLUME_MAX)
            .setVolume(mVolume)
            .build();
    // Add the route descriptor to the provider descriptor
    MediaRouteProviderDescriptor providerDescriptor =
            new MediaRouteProviderDescriptor.Builder()
            .addRoute(routeDescriptor)
            .build();

    // Publish the descriptor to the framework
    setDescriptor(providerDescriptor);
}

Pour en savoir plus sur les paramètres de descripteur disponibles, consultez la documentation de référence. pour MediaRouteDescriptor et MediaRouteProviderDescriptor.

Contrôler les routes

Lorsqu'une application se connecte à votre fournisseur de routage multimédia, celui-ci reçoit la lecture via le framework de routeur multimédia envoyées sur votre route par d'autres applications. Pour gérer ces vous devez fournir une implémentation d'une classe MediaRouteProvider.RouteController, qui traite les commandes et gère la communication réelle avec votre récepteur.

Le framework du routeur multimédia appelle onCreateRouteController() de votre fournisseur d'itinéraires pour obtenir une instance de cette classe et y acheminer les requêtes. Voici les principales méthodes de la classe MediaRouteProvider.RouteController, que vous devez implémenter pour votre fournisseur de routage multimédia:

  • onSelect() : appelé lorsqu'une application sélectionne votre itinéraire pour la lecture. Cette méthode vous permet d'effectuer les éventuels travaux de préparation nécessaires avant le début de la lecture du contenu multimédia.
  • onControlRequest() : envoie des commandes de lecture spécifiques à l'appareil récepteur.
  • onSetVolume() : envoie une requête à l'appareil récepteur pour régler le volume de lecture sur un une valeur spécifique.
  • onUpdateVolume() : envoie une requête à l'appareil récepteur pour modifier la lecture. le volume d'un volume spécifié.
  • onUnselect() : appelé lorsqu'une application désélectionne une route.
  • onRelease() : appelé lorsque le framework n'a plus besoin de la route, ce qui lui permet de libérer son ressources.

Toutes les demandes de commandes de lecture, à l'exception des changements de volume, sont dirigées vers le onControlRequest() . Votre mise en œuvre de cette méthode doit analyser les requêtes de contrôle et y répondre. en conséquence. Voici un exemple d'implémentation de cette méthode, qui traite les commandes pour une itinéraire multimédia de lecture à distance:

Kotlin

private class SampleRouteController : MediaRouteProvider.RouteController() {
    ...

    override fun onControlRequest(
            intent: Intent,
            callback: MediaRouter.ControlRequestCallback?
    ): Boolean {
        return if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            val action = intent.action
            when (action) {
                MediaControlIntent.ACTION_PLAY -> handlePlay(intent, callback)
                MediaControlIntent.ACTION_ENQUEUE -> handleEnqueue(intent, callback)
                MediaControlIntent.ACTION_REMOVE -> handleRemove(intent, callback)
                MediaControlIntent.ACTION_SEEK -> handleSeek(intent, callback)
                MediaControlIntent.ACTION_GET_STATUS -> handleGetStatus(intent, callback)
                MediaControlIntent.ACTION_PAUSE -> handlePause(intent, callback)
                MediaControlIntent.ACTION_RESUME -> handleResume(intent, callback)
                MediaControlIntent.ACTION_STOP -> handleStop(intent, callback)
                MediaControlIntent.ACTION_START_SESSION -> handleStartSession(intent, callback)
                MediaControlIntent.ACTION_GET_SESSION_STATUS ->
                    handleGetSessionStatus(intent, callback)
                MediaControlIntent.ACTION_END_SESSION -> handleEndSession(intent, callback)
                else -> false
            }.also {
                Log.d(TAG, sessionManager.toString())
            }
        } else {
            false
        }
    }
    ...
}

Java

private final class SampleRouteController extends
        MediaRouteProvider.RouteController {
    ...

    @Override
    public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {

        String action = intent.getAction();

        if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            boolean success = false;
            if (action.equals(MediaControlIntent.ACTION_PLAY)) {
                success = handlePlay(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
                success = handleEnqueue(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
                success = handleRemove(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
                success = handleSeek(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
                success = handleGetStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
                success = handlePause(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
                success = handleResume(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
                success = handleStop(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
                success = handleStartSession(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
                success = handleGetSessionStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
                success = handleEndSession(intent, callback);
            }

            Log.d(TAG, sessionManager.toString());
            return success;
        }
        return false;
    }
    ...
}

Il est important de comprendre que la classe MediaRouteProvider.RouteController est destinée à agir comme un wrapper. pour l'API à votre équipement de lecture multimédia. L'implémentation des méthodes de cette classe est dépend entièrement de l'interface de programmation fournie par votre appareil récepteur.

Exemple de code

Le MediaRouter montre comment créer un fournisseur de routage multimédia personnalisé.