Ajouter des fonctionnalités avancées à votre application Android

Coupures publicitaires

Le SDK Android Sender est compatible avec les coupures publicitaires et les annonces associées dans un flux multimédia donné.

Pour en savoir plus sur le fonctionnement des coupures publicitaires, consultez l'article Présentation des coupures publicitaires Web Receiver.

Bien que les pauses puissent être spécifiées à la fois sur l'expéditeur et sur le récepteur, il est recommandé de les spécifier sur le destinataire Web et sur le récepteur Android TV afin de maintenir un comportement cohérent sur toutes les plates-formes.

Sur Android, spécifiez les coupures publicitaires dans une commande de chargement à l'aide de AdBreakClipInfo et de AdBreakInfo:

Kotlin
val breakClip1: AdBreakClipInfo =
    AdBreakClipInfo.Builder("bc0")
        .setTitle("Clip title")
        .setPosterUrl("https://www.some.url")
        .setDuration(60000)
        .setWhenSkippableInMs(5000)  // Set this field so that the ad is skippable
        .build()

val breakClip2: AdBreakClipInfo = …
val breakClip3: AdBreakClipInfo = …

val break1: AdBreakClipInfo =
    AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000)
        .setId("b0")
        .setBreakClipIds({"bc0","bc1","bc2"})
        …
        .build()

val mediaInfo: MediaInfo = MediaInfo.Builder()
    …
    .setAdBreaks({break1})
    .setAdBreakClips({breakClip1, breakClip2, breakClip3})
    .build()

val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder()
    …
    .setMediaInfo(mediaInfo)
    .build()

remoteMediaClient.load(mediaLoadRequestData)
Java
AdBreakClipInfo breakClip1 =
    new AdBreakClipInfo.Builder("bc0")
        .setTitle("Clip title")
        .setPosterUrl("https://www.some.url")
        .setDuration(60000)
        .setWhenSkippableInMs(5000)  // Set this field so that the ad is skippable
        .build();

AdBreakClipInfo breakClip2 = …
AdBreakClipInfo breakClip3 = …

AdBreakInfo break1 =
    new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000)
        .setId("b0")
        .setBreakClipIds({"bc0","bc1","bc2"})
        …
        .build();

MediaInfo mediaInfo = new MediaInfo.Builder()
    …
    .setAdBreaks({break1})
    .setAdBreakClips({breakClip1, breakClip2, breakClip3})
    .build();

MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder()
    …
    .setMediaInfo(mediaInfo)
    .build();

remoteMediaClient.load(mediaLoadRequestData);

Ajouter des actions personnalisées

Une application émettrice peut étendre MediaIntentReceiver pour gérer des actions personnalisées ou ignorer son comportement. Si vous avez implémenté votre propre MediaIntentReceiver, vous devez l'ajouter au fichier manifeste et définir son nom dans CastMediaOptions. Cet exemple fournit des actions personnalisées qui remplacent la lecture à distance des contenus multimédias en appuyant sur le bouton multimédia et d'autres types d'actions.

// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
Kotlin
// In your OptionsProvider
var mediaOptions = CastMediaOptions.Builder()
    .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name)
    .build()

// Implementation of MyMediaIntentReceiver
internal class MyMediaIntentReceiver : MediaIntentReceiver() {
    override fun onReceiveActionTogglePlayback(currentSession: Session) {
    }

    override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) {
    }

    override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) {
    }
}
Java
// In your OptionsProvider
CastMediaOptions mediaOptions = new CastMediaOptions.Builder()
        .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName())
        .build();

// Implementation of MyMediaIntentReceiver
class MyMediaIntentReceiver extends MediaIntentReceiver {
    @Override
    protected void onReceiveActionTogglePlayback(Session currentSession) {
    }

    @Override
    protected void onReceiveActionMediaButton(Session currentSession, Intent intent) {
    }

    @Override
    protected void onReceiveOtherAction(Context context, String action, Intent intent) {
    }
}

Ajouter un critère personnalisé

Pour que l'application expéditeur communique avec l'application destinataire, elle doit créer un canal personnalisé. L'expéditeur peut utiliser le canal personnalisé pour envoyer des messages de chaîne au destinataire. Chaque canal personnalisé est défini par un espace de noms unique et doit commencer par le préfixe urn:x-cast:, par exemple urn:x-cast:com.example.custom. Il est possible d'avoir plusieurs critères personnalisés, chacun avec un espace de noms unique. L'application récepteur peut également envoyer et recevoir des messages à l'aide du même espace de noms.

Le canal personnalisé est implémenté avec l'interface Cast.MessageReceivedCallback:

Kotlin
class HelloWorldChannel : MessageReceivedCallback {
    val namespace: String
        get() = "urn:x-cast:com.example.custom"

    override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) {
        Log.d(TAG, "onMessageReceived: $message")
    }
}
Java
class HelloWorldChannel implements Cast.MessageReceivedCallback {
    public String getNamespace() {
        return "urn:x-cast:com.example.custom";
    }
    @Override
    public void onMessageReceived(CastDevice castDevice, String namespace, String message) {
        Log.d(TAG, "onMessageReceived: " + message);
    }
}

Une fois l'application expéditeur connectée à l'application récepteur, vous pouvez créer le canal personnalisé à l'aide de la méthode setMessageReceivedCallbacks:

Kotlin
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
Java
try {
    mCastSession.setMessageReceivedCallbacks(
            mHelloWorldChannel.getNamespace(),
            mHelloWorldChannel);
} catch (IOException e) {
    Log.e(TAG, "Exception while creating channel", e);
}

Une fois le canal personnalisé créé, l'expéditeur peut utiliser la méthode sendMessage pour envoyer des messages de chaîne au destinataire via ce canal:

Kotlin
private fun sendMessage(message: String) {
    if (mHelloWorldChannel != null) {
        try {
            mCastSession.sendMessage(mHelloWorldChannel.namespace, message)
                .setResultCallback { status ->
                    if (!status.isSuccess) {
                        Log.e(TAG, "Sending message failed")
                    }
                }
        } catch (e: Exception) {
            Log.e(TAG, "Exception while sending message", e)
        }
    }
}
Java
private void sendMessage(String message) {
    if (mHelloWorldChannel != null) {
        try {
            mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message)
                .setResultCallback( status -> {
                    if (!status.isSuccess()) {
                        Log.e(TAG, "Sending message failed");
                    }
                });
        } catch (Exception e) {
            Log.e(TAG, "Exception while sending message", e);
        }
    }
}

Lecture automatique compatible

Consultez la section API de lecture automatique et de mise en file d'attente.

Remplacer la sélection d'images pour les widgets d'expérience utilisateur

Différents composants du framework (à savoir la boîte de dialogue Cast, le mini-contrôleur et l'UIMediaController, le cas échéant) afficheront une pochette pour le contenu multimédia en cours de diffusion. Les URL de l'illustration sont généralement incluses dans MediaMetadata pour le média, mais l'application d'expéditeur peut disposer d'une autre source pour les URL.

La classe ImagePicker définit un moyen de sélectionner une image appropriée dans la liste d'images d'un élément MediaMetadata, en fonction de l'utilisation de l'image (par exemple, une vignette de notification ou un arrière-plan plein écran). L'implémentation ImagePicker par défaut choisit toujours la première image ou renvoie la valeur "null" si aucune image n'est disponible dans MediaMetadata. Votre application peut sous-classer ImagePicker et remplacer la méthode onPickImage(MediaMetadata, ImageHints) pour fournir une autre implémentation, puis sélectionner cette sous-classe avec la méthode setImagePicker de CastMediaOptions.Builder. ImageHints fournit à un ImagePicker des indications sur le type et la taille d'une image à afficher dans l'interface utilisateur.

Personnaliser les boîtes de dialogue Cast

SessionManager est l'emplacement centralisé pour gérer le cycle de vie de la session. SessionManager écoute les changements de l'état de sélection de la route Android MediaRouter pour démarrer, reprendre et terminer des sessions. Lorsqu'une route est sélectionnée, SessionManager crée un objet Session et tente de le démarrer ou de le reprendre. Lorsqu'un itinéraire n'est pas sélectionné, SessionManager met fin à la session en cours.

Par conséquent, pour vous assurer que SessionManager gère correctement les cycles de vie des sessions, vous devez vous assurer que:

Selon la façon dont vous créez les boîtes de dialogue Cast, des actions supplémentaires peuvent être nécessaires:

Étapes suivantes

Voilà qui conclut les fonctionnalités que vous pouvez ajouter à votre application Android Sender. Vous pouvez désormais créer une application émettrice pour une autre plate-forme (iOS ou Web) ou une application Web Receiver.