Per utilizzare il framework MediaRouter nella tua app, devi ottenere un'istanza
dell'oggetto MediaRouter
e collega un
Oggetto MediaRouter.Callback
per ascoltare gli eventi di routing.
I contenuti inviati su un percorso multimediale passano attraverso il percorso
associato a MediaRouteProvider
(tranne in alcuni casi speciali,
come un dispositivo di output Bluetooth). La Figura 1 fornisce una panoramica generale dello
utilizzate per indirizzare i contenuti tra dispositivi.
Nota: se vuoi che la tua app supporti Dispositivi Google Cast dovresti utilizzare l'SDK Cast e creare l'app come mittente di trasmissione. Segui le istruzioni nella Documentazione relativa a Cast anziché usare direttamente il framework MediaRouter.
Il pulsante Percorso multimediale
Le app Android devono utilizzare un pulsante Percorso multimediale per controllare il routing dei contenuti multimediali. Il framework MediaRouter Fornisce un'interfaccia standard per il pulsante, che consente agli utenti di riconoscere e utilizzare il routing quando sono disponibili. Il pulsante del percorso multimediale si trova in genere sul lato destro di barra delle azioni dell'app, come mostrato nella Figura 2.
Quando l'utente preme il pulsante del percorso multimediale, i percorsi multimediali disponibili vengono visualizzati in un elenco come mostrato nella figura 3.
Per creare un pulsante del percorso multimediale:
- Utilizzo di un'attività AppCompatActivity
- Definisci la voce di menu del pulsante di route multimediale
- Crea un MediaRouteSelector
- Aggiungi il pulsante del percorso multimediale alla barra delle azioni
- Creare e gestire i metodi MediaRouter.Callback nel ciclo di vita della tua attività
In questa sezione vengono descritti i primi quattro passaggi. La sezione successiva descrive i metodi di callback.
Utilizzo di un'attività AppCompatActivity
Quando utilizzi il framework Media router in un'attività, devi estendere
l'attività da AppCompatActivity
e importa
pacchetto androidx.appcompat.app
. Devi aggiungere il parametro
androidx.appcompat:appcompat
e androidx.mediarouter:mediarouter
e supportare le librerie nel progetto di sviluppo dell'app. Per ulteriori informazioni sull'aggiunta di librerie di supporto
al tuo progetto, consulta la Guida introduttiva ad Android Jetpack.
Attenzione: assicurati di utilizzare androidx
dell'implementazione del framework Media router. Non utilizzare il pacchetto android.media
precedente.
Definisci la voce di menu del pulsante di route multimediale
Crea un file XML che definisce una voce di menu per il pulsante di routing multimediale.
L'azione dell'elemento deve essere la classe MediaRouteActionProvider
.
Ecco un file di esempio:
// myMediaRouteButtonMenuItem.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/media_route_menu_item" android:title="@string/media_route_menu_title" app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider" app:showAsAction="always" /> </menu>
Crea un MediaRouteSelector
I percorsi visualizzati nel menu dei pulsanti del percorso multimediale sono determinati da un MediaRouteSelector
.
Estendi l'attività da AppCompatActivity
e crea il selettore quando viene creata l'attività chiamando MediaRouteSelector.Builder
dal metodo onCreate() come mostrato
nel seguente esempio di codice. Tieni presente che il selettore viene salvato in una variabile di classe e sono specificati i tipi di route consentiti
aggiungendo MediaControlIntent
oggetti:
Kotlin
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mSelector: MediaRouteSelector? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create a route selector for the type of routes your app supports. mSelector = MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build() } }
Java
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouteSelector mSelector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create a route selector for the type of routes your app supports. mSelector = new MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build(); } }
Per la maggior parte delle applicazioni,
il tipo di percorso richiesto è CATEGORY_REMOTE_PLAYBACK
. Questo tipo di percorso considera il dispositivo su cui è in esecuzione la tua app come un telecomando.
Il dispositivo ricevitore connesso gestisce il recupero, la decodifica e la riproduzione di tutti i dati sui contenuti.
Ecco come le app che supportano Google Cast, ad esempio
Chromecast, al lavoro.
Alcuni produttori supportano una speciale opzione di routing chiamata "output secondario". Con questo routing,
l'app multimediale recupera, esegue il rendering e trasmette in streaming video o musica direttamente sullo schermo e/o sugli altoparlanti del dispositivo ricevitore remoto selezionato.
Utilizza l'uscita secondaria per inviare contenuti a sistemi musicali wireless o display video. Per abilitare il rilevamento e
dispositivi selezionati, devi aggiungere
CATEGORY_LIVE_AUDIO
o
CATEGORY_LIVE_VIDEO
categorie di controllo a MediaRouteSelector. Devi anche creare e gestire la tua finestra di dialogo Presentation
.
Aggiungi il pulsante del percorso multimediale alla barra delle azioni
Dopo aver definito il menu del percorso multimediale e MediaRouteSelector, ora puoi aggiungere il pulsante del percorso multimediale a un'attività.
Sostituisci il metodo onCreateOptionsMenu()
per ogni attività per aggiungere opzioni
o dal menu Fogli Google.
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) // Inflate the menu and configure the media router action provider. menuInflater.inflate(R.menu.sample_media_router_menu, menu) // Attach the MediaRouteSelector to the menu item val mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item) val mediaRouteActionProvider = MenuItemCompat.getActionProvider(mediaRouteMenuItem) as MediaRouteActionProvider // Attach the MediaRouteSelector that you built in onCreate() selector?.also(mediaRouteActionProvider::setRouteSelector) // Return true to show the menu. return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Inflate the menu and configure the media router action provider. getMenuInflater().inflate(R.menu.sample_media_router_menu, menu); // Attach the MediaRouteSelector to the menu item MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider)MenuItemCompat.getActionProvider( mediaRouteMenuItem); // Attach the MediaRouteSelector that you built in onCreate() mediaRouteActionProvider.setRouteSelector(selector); // Return true to show the menu. return true; }
Per ulteriori informazioni sull'implementazione della barra delle azioni nell'app, Visualizza la barra delle azioni guida per gli sviluppatori.
Puoi anche aggiungere un pulsante del percorso multimediale come MediaRouteButton
in qualsiasi
vista. Devi collegare un MediaRouteSelector al pulsante utilizzando il metodo setRouteSelector()
. Consulta le
Elenco di controllo per la progettazione di Google Cast
per le linee guida sull'incorporamento del pulsante relativo al percorso multimediale nella tua applicazione.
Callback di MediaRouter
Tutte le app in esecuzione sullo stesso dispositivo condividono una singola istanza MediaRouter
e i relativi percorsi
(filtrato per app in base al MediaRouteSelector dell'app). Ogni attività comunica con MediaRouter
utilizzando la propria implementazione di MediaRouter.Callback
di machine learning. MediaRouter chiama i metodi di callback ogni volta che l'utente seleziona, modifica o disconnette una route.
Esistono diversi metodi nel callback su cui puoi eseguire l'override per ricevere informazioni
eventi di routing. Come minimo, l'implementazione della classe MediaRouter.Callback
dovrebbe sostituire
onRouteSelected()
e
onRouteUnselected()
.
Poiché MediaRouter è una risorsa condivisa, la tua app deve gestire i callback MediaRouter in risposta ai consueti callback del ciclo di vita delle attività:
- Quando viene creata l'attività (
onCreate(Bundle)
), recupera un puntatore allaMediaRouter
e tienilo premuto per tutta la durata dell'app. - Collega callback a MediaRouter quando l'attività diventa visibile (
onStart()
) e scollegali quando è nascosta (onStop()
).
Il seguente esempio di codice mostra come
crea e salva l'oggetto callback, come
ottenere un'istanza di MediaRouter
e come gestire i callback.
Nota l'utilizzo del flag CALLBACK_FLAG_REQUEST_DISCOVERY
quando si allegano i callback in onStart()
.
In questo modo, MediaRouteSelector può aggiornare la posizione del pulsante
delle route disponibili.
Kotlin
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mediaRouter: MediaRouter? = null private var mSelector: MediaRouteSelector? = null // Variables to hold the currently selected route and its playback client private var mRoute: MediaRouter.RouteInfo? = null private var remotePlaybackClient: RemotePlaybackClient? = null // Define the Callback object and its methods, save the object in a class variable private val mediaRouterCallback = object : MediaRouter.Callback() { override fun onRouteSelected(router: MediaRouter, route: MediaRouter.RouteInfo) { Log.d(TAG, "onRouteSelected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Stop local playback (if necessary) // ... // Save the new route mRoute = route // Attach a new playback client remotePlaybackClient = RemotePlaybackClient(this@MediaRouterPlaybackActivity, mRoute) // Start remote playback (if necessary) // ... } } override fun onRouteUnselected( router: MediaRouter, route: MediaRouter.RouteInfo, reason: Int ) { Log.d(TAG, "onRouteUnselected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Changed route: tear down previous client mRoute?.also { remotePlaybackClient?.release() remotePlaybackClient = null } // Save the new route mRoute = route when (reason) { MediaRouter.UNSELECT_REASON_ROUTE_CHANGED -> { // Resume local playback (if necessary) // ... } } } } } // Retain a pointer to the MediaRouter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Get the media router service. mediaRouter = MediaRouter.getInstance(this) ... } // Use this callback to run your MediaRouteSelector to generate the // list of available media routes override fun onStart() { mSelector?.also { selector -> mediaRouter?.addCallback(selector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY) } super.onStart() } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. override fun onStop() { mediaRouter?.removeCallback(mediaRouterCallback) super.onStop() } ... }
Java
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouter mediaRouter; private MediaRouteSelector mSelector; // Variables to hold the currently selected route and its playback client private MediaRouter.RouteInfo mRoute; private RemotePlaybackClient remotePlaybackClient; // Define the Callback object and its methods, save the object in a class variable private final MediaRouter.Callback mediaRouterCallback = new MediaRouter.Callback() { @Override public void onRouteSelected(MediaRouter router, RouteInfo route) { Log.d(TAG, "onRouteSelected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Stop local playback (if necessary) // ... // Save the new route mRoute = route; // Attach a new playback client remotePlaybackClient = new RemotePlaybackClient(this, mRoute); // Start remote playback (if necessary) // ... } } @Override public void onRouteUnselected(MediaRouter router, RouteInfo route, int reason) { Log.d(TAG, "onRouteUnselected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Changed route: tear down previous client if (mRoute != null && remotePlaybackClient != null) { remotePlaybackClient.release(); remotePlaybackClient = null; } // Save the new route mRoute = route; if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) { // Resume local playback (if necessary) // ... } } } } // Retain a pointer to the MediaRouter @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get the media router service. mediaRouter = MediaRouter.getInstance(this); ... } // Use this callback to run your MediaRouteSelector to generate the list of available media routes @Override public void onStart() { mediaRouter.addCallback(mSelector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); super.onStart(); } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. @Override public void onStop() { mediaRouter.removeCallback(mediaRouterCallback); super.onStop(); } ... }
Il framework Media router offre anche
MediaRouteDiscoveryFragment
corso, che si occupa di aggiungere e
rimuovendo il callback per un'attività.
Nota: se stai scrivendo un'app per la riproduzione di musica e vuoi riprodurre l'app
musica in background, devi creare un Service
per la riproduzione
e richiamare il framework del router multimediale dai callback del ciclo di vita del servizio.
Controllo di un percorso di riproduzione remoto
Quando selezioni un percorso di riproduzione remoto, l'app funge da telecomando. Il dispositivo all'altra estremità del percorso.
gestisce tutte le funzioni di recupero, decodifica e riproduzione dei dati sui contenuti. I controlli nell'UI dell'app comunicano con il dispositivo destinatario tramite un
RemotePlaybackClient
oggetto.
Il corso RemotePlaybackClient
fornisce metodi aggiuntivi
per gestire la riproduzione dei contenuti. Ecco alcuni dei principali metodi di riproduzione della classe RemotePlaybackClient
:
play()
: riproduci un contenuto specifico file multimediale, specificato da unUri
.pause()
: metti in pausa traccia multimediale in riproduzione.resume()
- Continua la traccia corrente dopo un comando di pausa.seek()
: passa a una sezione specifica posizione nella traccia corrente.release()
: elimina connessione dalla tua app al dispositivo di riproduzione remoto.
Puoi utilizzare questi metodi per collegare azioni ai controlli di riproduzione che fornisci nei tuoi dell'app. La maggior parte di questi metodi consente anche di includere un oggetto di callback in modo da poter monitorare l'avanzamento dell'attività di riproduzione o della richiesta di controllo.
La classe RemotePlaybackClient
supporta anche l'accodamento di
più elementi multimediali per la riproduzione e la gestione della coda multimediale.
Codice di esempio
L'app Android BasicMediaRouter e MediaRouter esempi dimostrano ulteriormente l'uso dell'API MediaRouter.