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 leur fonctionnement, consultez la page Présentation des coupures publicitaires Web Receiver.
Bien que les coupures puissent être spécifiées à la fois sur l'émetteur et sur le récepteur, il est recommandé de le faire sur le Web Receiver et le récepteur Android TV afin de maintenir un comportement cohérent sur l'ensemble des plates-formes.
Sur Android, spécifiez les coupures publicitaires dans une commande de chargement à l'aide de AdBreakClipInfo
et AdBreakInfo
:
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)
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 l'activation/la désactivation de la lecture multimédia à distance, l'appui sur le bouton multimédia et d'autres types d'actions.
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// 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) { } }
// 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, 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éceptrice 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
:
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") } }
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éé à l'aide de la méthode setMessageReceivedCallbacks
:
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
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:
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) } } }
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 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 Caster, le mini-contrôleur et UIMediaController, s'ils sont configurés) affichent des illustrations pour le contenu multimédia en cours de diffusion. Les URL de l'illustration de l'image sont généralement incluses dans le MediaMetadata
du contenu multimédia, mais l'application émettrice 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 la vignette de notification ou l'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 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 des indications à une ImagePicker
sur le type et la taille d'une image à sélectionner pour l'afficher dans l'interface utilisateur.
Personnaliser les boîtes de dialogue Cast
Gérer le cycle de vie d'une session
SessionManager
est l'emplacement centralisé pour gérer le cycle de vie d'une session. SessionManager
écoute les changements d'état de sélection de routes Android MediaRouter
pour démarrer, reprendre et terminer les 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 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 assurer que:
- Dans la boîte de dialogue du sélecteur de routes, appelez
MediaRouter.selectRoute(MediaRouter.RouteInfo)
lorsqu'un utilisateur sélectionne un appareil. - Dans la boîte de dialogue du contrôleur de routage (en état connecté ou en état de diffusion), appelez
MediaRouter.unselect(int)
lorsque l'utilisateur arrête la diffusion.
Selon la manière dont vous créez les boîtes de dialogue Cast, des actions supplémentaires peuvent être nécessaires:
- Si vous créez des boîtes de dialogue Cast à l'aide de
MediaRouteChooserDialog
etMediaRouteControllerDialog
, ces boîtes de dialogue mettent automatiquement à jour la sélection d'itinéraires dansMediaRouter
. Vous n'avez donc rien à faire. - Si vous configurez l'icône Cast à l'aide de
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
ouCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
, les boîtes de dialogue sont en fait créées à l'aide deMediaRouteChooserDialog
etMediaRouteControllerDialog
. Vous n'avez donc rien à faire non plus. - Dans les autres cas, vous allez créer des boîtes de dialogue Cast personnalisées. Vous devez donc suivre les instructions ci-dessus pour mettre à jour l'état de sélection de la route dans
MediaRouter
.
État "Aucun appareil"
Si vous créez des boîtes de dialogue Cast personnalisées, votre MediaRouteChooserDialog
personnalisé devrait gérer correctement le cas où aucun appareil ne serait trouvé. La boîte de dialogue doit comporter des indicateurs indiquant clairement aux utilisateurs que votre application tente toujours de trouver des appareils et que la tentative de découverte n'est plus active.
Si vous utilisez l'état MediaRouteChooserDialog
par défaut, l'état zéro d'appareil est déjà géré.
Étapes suivantes
Vous êtes arrivé à la fin des 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.