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 au sein d'une un flux multimédia donné.

Consultez le Présentation des coupures publicitaires Web receiver pour d'autres sur le fonctionnement des coupures publicitaires.

Bien que les coupures puissent être spécifiées à la fois au niveau de l'expéditeur et du destinataire, il est recommandé d'utiliser spécifiées sur Web Receiver et Android TV Receiver pour assurer la cohérence sur toutes les plates-formes.

Sur Android, spécifiez les coupures publicitaires dans une commande de chargement à l'aide de AdBreakClipInfo et 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 d'expéditeur peut étendre MediaIntentReceiver pour gérer des actions personnalisées ou remplacer son comportement. Si vous avez mis en œuvre votre propre MediaIntentReceiver, vous devez l'ajouter au fichier manifeste et définir son nom dans CastMediaOptions. Cet exemple fournit des actions personnalisées ignorer, activer/désactiver la lecture multimédia à distance, appuyer 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 émettrice puisse communiquer avec l'application réceptrice, celle-ci doit créer un critère personnalisé. L'expéditeur peut utiliser le canal personnalisé pour envoyer la chaîne les messages au destinataire. Chaque critère personnalisé est défini par un espace de noms et doit commencer par le préfixe urn:x-cast:, par exemple : urn:x-cast:com.example.custom Vous pouvez avoir plusieurs canaux personnalisés, chacun avec un espace de noms unique. L'application réceptrice peut également envoyer et recevoir des messages utilisant le même espace de noms.

Le critère personnalisé est implémenté à l'aide du Cast.MessageReceivedCallback interface:

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 émettrice connectée à l'application réceptrice, le canal personnalisé peut être créées à l'aide de setMessageReceivedCallbacks méthode:

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 critère personnalisé créé, l'expéditeur peut utiliser le 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);
        }
    }
}

Compatibilité avec la lecture automatique

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

Forcer la sélection d'une image pour les widgets d'expérience utilisateur

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

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

Personnaliser les boîtes de dialogue Cast

Gérer le cycle de vie d'une session

SessionManager est l'emplacement central pour gérer le cycle de vie des sessions. SessionManager écoutes vers Android MediaRouter l'état de la sélection d'itinéraire change pour démarrer, reprendre et terminer les sessions. Lorsqu’un itinéraire est sélectionné, SessionManager créera un Session et tente de le démarrer ou de le réactiver. Lorsqu'un itinéraire est dé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 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 terminé:

État "Aucun appareil"

Si vous créez des boîtes de dialogue Cast personnalisées, votre MediaRouteChooserDialog personnalisée doit gérer correctement le cas où aucun appareil n'est détecté. La boîte de dialogue doit comporter des indicateurs indiquant clairement aux utilisateurs à quel moment votre l'application tente toujours de trouver des appareils alors que la tentative de détection n'est pas plus actifs.

Si vous utilisez le MediaRouteChooserDialog par défaut, l'état zéro pour les appareils est déjà traitée.

Étapes suivantes

Voici 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 créer une application Web Receiver ;