Interruzioni pubblicitarie
L'SDK Android Sender fornisce assistenza per le interruzioni pubblicitarie e gli annunci companion all'interno di un determinato stream multimediale.
Per saperne di più su come funzionano le interruzioni pubblicitarie, consulta la panoramica sulle interruzioni pubblicitarie per il ricevitore web.
Sebbene sia possibile specificare interruzioni sia per il mittente che per il destinatario, è consigliabile specificarle sul ricevitore web e nel destinatario di Android TV per mantenere un comportamento coerente su più piattaforme.
Su Android, specifica le interruzioni pubblicitarie in un comando di caricamento utilizzando AdBreakClipInfo
e 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);
Aggiungi azioni personalizzate
Un'app mittente può estendere
MediaIntentReceiver
per gestire le azioni personalizzate o ignorarne il comportamento. Se hai implementato
il tuo MediaIntentReceiver
, devi aggiungerlo al manifest e impostare anche il relativo
nome in CastMediaOptions
. Questo esempio fornisce azioni personalizzate che sostituiscono la riproduzione di contenuti multimediali da remoto, premendo il pulsante multimediale e altri tipi di azioni.
// 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) { } }
Aggiungi un canale personalizzato
Affinché l'app del mittente comunichi con l'app del destinatario, è necessario creare un canale personalizzato. Il mittente può utilizzare il canale personalizzato per inviare messaggi stringa al destinatario. Ogni canale personalizzato è definito da uno spazio dei nomi univoco e deve iniziare con il prefisso urn:x-cast:
, ad esempio urn:x-cast:com.example.custom
. È possibile avere più canali personalizzati, ciascuno con uno spazio dei nomi univoco. L'app del destinatario può anche
inviare e ricevere messaggi
utilizzando lo stesso spazio dei nomi.
Il canale personalizzato viene implementato con l'interfaccia 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); } }
Una volta che l'app del mittente è connessa all'app di ricezione, il canale personalizzato può essere creato utilizzando il metodo 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); }
Una volta creato il canale personalizzato, il mittente può utilizzare il metodo sendMessage
per inviare messaggi stringa al destinatario su quel canale:
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); } } }
Supporto della riproduzione automatica
Consulta la sezione API di riproduzione automatica e coda.
Ignora la selezione dell'immagine per i widget UX
Diversi componenti del framework (ovvero la finestra di dialogo Trasmetti, il mini controller e l'UIMediaController, se configurato) mostrano la grafica per i contenuti multimediali attualmente trasmessi. Gli URL della grafica dell'immagine sono in genere inclusi nel MediaMetadata
per i contenuti multimediali, ma l'app del mittente potrebbe avere un'origine alternativa per gli URL.
La classe ImagePicker
definisce un mezzo per selezionare un'immagine appropriata dall'elenco di immagini in un MediaMetadata
, in base all'uso dell'immagine, ad esempio la miniatura della notifica o lo sfondo a schermo intero. L'implementazione predefinita di ImagePicker
sceglie sempre la prima immagine oppure restituisce null se non è disponibile alcuna immagine in MediaMetadata
. La tua app può eseguire la sottoclasse ImagePicker
e sostituire il metodo
onPickImage(MediaMetadata, ImageHints)
per fornire un'implementazione alternativa, quindi selezionare la sottoclasse
con il metodo
setImagePicker
di CastMediaOptions.Builder
.
ImageHints
fornisce suggerimenti a un ImagePicker
sul tipo e sulle dimensioni di un'immagine da selezionare per la visualizzazione nell'interfaccia utente.
Personalizzazione delle finestre di dialogo Trasmetti
SessionManager
è il punto centrale per la gestione del ciclo di vita delle sessioni. SessionManager
ascolta
Android
MediaRouter
cambia lo stato della selezione del percorso per avviare, riprendere e terminare le sessioni. Quando viene selezionata una route, SessionManager
crea un oggetto Session
e tenta di avviarlo o ripristinarlo. Se un percorso non è selezionato,
SessionManager
terminerà la sessione corrente.
Pertanto, per garantire che SessionManager
gestisca correttamente i cicli di vita delle sessioni, devi assicurarti che:
- Nella finestra di dialogo del selettore di percorso, chiama
MediaRouter.selectRoute(MediaRouter.RouteInfo)
quando un utente seleziona un dispositivo. - Nella finestra di dialogo del controller di percorso (in stato connesso o in
stato di trasmissione),
chiama
MediaRouter.unselect(int)
quando l'utente smette di trasmettere.
A seconda di come crei le finestre di dialogo di trasmissione, potrebbero essere necessarie ulteriori azioni:
- Se crei finestre di dialogo Trasmetti utilizzando
MediaRouteChooserDialog
eMediaRouteControllerDialog
, queste finestre di dialogo aggiornano automaticamente la selezione del percorso inMediaRouter
, quindi non è necessario fare nulla. - Se configuri il pulsante Trasmetti utilizzando
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
oCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
, le finestre di dialogo vengono effettivamente create utilizzandoMediaRouteChooserDialog
eMediaRouteControllerDialog
, quindi non è necessario fare nulla. - In altri casi, verranno create finestre di dialogo personalizzate di Cast, pertanto devi seguire le istruzioni precedenti per aggiornare lo stato di selezione del percorso in
MediaRouter
.
Passaggi successivi
Questo conclude le funzionalità che puoi aggiungere all'app Mittente di Android. Ora puoi creare un'app di invio per un'altra piattaforma (iOS o Web) o creare un'app di ricezione web.