Interruzioni pubblicitarie
L'SDK Android Sender fornisce supporto per interruzioni pubblicitarie e annunci companion all'interno di un un determinato stream multimediale.
Consulta le Panoramica delle interruzioni pubblicitarie di Web receiver per saperne di più informazioni sul funzionamento delle interruzioni pubblicitarie.
Anche se le interruzioni possono essere specificate sia sul mittente sia sul destinatario, è consigliabile che specificato sul WebRicevitore e Ricevitore Android TV per garantire coerenza il comportamento degli utenti sulle varie 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 azioni personalizzate o eseguirne l'override. Se hai implementato
proprio MediaIntentReceiver
, devi aggiungerlo al file manifest e impostare anche
nome in CastMediaOptions
. Questo esempio fornisce azioni personalizzate
sostituisci la riproduzione di contenuti multimediali da remoto premendo il pulsante dei contenuti multimediali 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 possa comunicare con l'app del destinatario, l'app deve
per creare un canale personalizzato. Il mittente può utilizzare il canale personalizzato per inviare la stringa
i messaggi al destinatario. Ogni canale personalizzato è definito da un
spazio dei nomi e deve iniziare con il prefisso urn:x-cast:
, ad esempio
urn:x-cast:com.example.custom
. È possibile avere più query
ciascuno con uno spazio dei nomi univoco. L'app ricevente può anche
inviare e ricevere messaggi
utilizzando lo stesso spazio dei nomi.
Il canale personalizzato è implementato con
Cast.MessageReceivedCallback
dell'interfaccia:
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 è collegata all'app del destinatario, il canale personalizzato può
da creare utilizzando
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
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 Riproduzione automatica e API di accodamento.
Sostituisci la selezione delle immagini per i widget UX
I vari componenti del framework (ovvero la finestra di dialogo Trasmetti, il
e UIMediaController, se configurato) mostreranno
per i contenuti multimediali attualmente trasmessi. Gli URL dell'artwork dell'immagine sono in genere
incluso in MediaMetadata
per i contenuti multimediali, ma l'app del mittente potrebbe avere un
sorgente alternativa per gli URL.
La
ImagePicker
definisce un mezzo per selezionare un'immagine appropriata dall'elenco di immagini
in un MediaMetadata
, in base all'uso dell'immagine, ad esempio, notifica
una miniatura o uno sfondo a schermo intero. L'implementazione predefinita di ImagePicker
sceglie sempre la prima immagine, oppure restituisce null se non è disponibile nessuna immagine
MediaMetadata
. La tua app può eseguire la sottoclasse ImagePicker
e sostituire il
onPickImage(MediaMetadata, ImageHints)
per fornire un'implementazione alternativa, quindi seleziona quella sottoclasse
con
setImagePicker
di CastMediaOptions.Builder
.
ImageHints
fornisce suggerimenti a ImagePicker
sul tipo e sulle dimensioni di un'immagine
selezionate per la visualizzazione nell'interfaccia utente.
Personalizzazione delle finestre di dialogo di trasmissione
Gestione del ciclo di vita delle sessioni
SessionManager
è il punto centrale per la gestione
del ciclo di vita delle sessioni. SessionManager
ascolti
ad Android
MediaRouter
lo stato di selezione del percorso viene modificato per iniziare, riprendere e terminare le sessioni. Quando un percorso viene
selezionata, SessionManager
creerà un
Session
e tenta di avviarlo o riprenderlo. Quando un percorso non è selezionato,
SessionManager
terminerà la sessione corrente.
Di conseguenza, per assicurarti che SessionManager
gestisca correttamente i cicli di vita delle sessioni,
devi assicurarti che:
- Nella finestra di dialogo del selettore del percorso,
chiamata
MediaRouter.selectRoute(MediaRouter.RouteInfo)
: quando un utente seleziona un dispositivo. - Nella finestra di dialogo del controller di route (nella sezione
o
trasmissione
),
chiamata
MediaRouter.unselect(int)
Quando l'utente interrompe la trasmissione.
A seconda di come crei le finestre di dialogo Trasmetti, potrebbero essere necessarie ulteriori azioni Fine:
- Se crei finestre di dialogo Trasmetti utilizzando
MediaRouteChooserDialog
eMediaRouteControllerDialog
, queste finestre di dialogo aggiorneranno automaticamente la selezione del percorso inMediaRouter
, quindi non occorre fare nulla. - Se configuri il pulsante Trasmetti utilizzando
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
oCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
, le finestre di dialogo creato utilizzandoMediaRouteChooserDialog
eMediaRouteControllerDialog
, quindi anche nulla deve essere fatto. - In altri casi, dovrai creare finestre di dialogo di trasmissione personalizzate, quindi dovrai
segui le istruzioni riportate sopra per aggiornare lo stato di selezione del percorso in
MediaRouter
.
Stato zero dispositivi
Se crei finestre di dialogo di trasmissione personalizzate, i tuoi
MediaRouteChooserDialog
deve gestire correttamente la presenza di zero dispositivi
trovato. La finestra di dialogo dovrebbe contenere indicatori che indicano chiaramente agli utenti quando
L'app sta ancora cercando di trovare dispositivi e quando il tentativo di rilevamento non ha esito positivo
più attivo.
Se utilizzi il valore predefinito MediaRouteChooserDialog
, lo stato zero dei dispositivi
è già gestita.
Passaggi successivi
Con questo si concluderanno le funzionalità che puoi aggiungere all'app Android Sender. Ora puoi creare un'app mittente per un'altra piattaforma (iOS o web) oppure creare un'app WebRicevitore.