Jetpack Media3 definisce un'interfaccia Player
che delinea le funzionalità di base
per la riproduzione di file video e audio. ExoPlayer
è l'implementazione predefinita
di questa interfaccia in Media3. Ti consigliamo di utilizzare ExoPlayer, in quanto fornisce un
insieme completo di funzionalità che coprono la maggior parte dei casi d'uso della riproduzione ed è
personalizzabile per gestire eventuali casi d'uso aggiuntivi. ExoPlayer astrae anche la frammentazione di dispositivi e sistemi operativi, in modo che il codice funzioni in modo coerente nell'intero ecosistema Android. ExoPlayer include:
- Supporto per le playlist
- Supporto di una serie di formati di streaming progressivo e adattivo
- Supporto dell'inserimento di annunci lato client e lato server
- Supporto per la riproduzione protetta da DRM
Questa pagina illustra alcuni dei passaggi chiave per la creazione di un'app di riproduzione. Per maggiori dettagli, puoi consultare le nostre guide complete su Media3 ExoPlayer.
Per iniziare
Per iniziare, aggiungi una dipendenza dai moduli ExoPlayer, UI e Common di Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.7.1" implementation "androidx.media3:media3-ui:1.7.1" implementation "androidx.media3:media3-common:1.7.1"
A seconda del caso d'uso, potresti aver bisogno anche di moduli aggiuntivi di Media3,
come exoplayer-dash
per riprodurre stream nel formato DASH.
Assicurati di sostituire 1.7.1
con la tua versione preferita della
libreria. Per visualizzare l'ultima versione, consulta le note di rilascio.
Creare un media player
Con Media3, puoi utilizzare l'implementazione inclusa dell'interfaccia Player
ExoPlayer
o creare la tua implementazione personalizzata.
Creazione di un ExoPlayer
Il modo più semplice per creare un'istanza ExoPlayer
è il seguente:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
Puoi creare il tuo media player nel metodo del ciclo di vita onCreate()
di
Activity
, Fragment
o Service
in cui si trova.
La Builder
include
una serie di opzioni di personalizzazione che potrebbero interessarti, ad esempio:
setAudioAttributes()
per configurare la gestione del focus audiosetHandleAudioBecomingNoisy()
per configurare il comportamento di riproduzione quando un dispositivo di uscita audio viene disconnessosetTrackSelector()
per configurare la selezione delle tracce
Media3 fornisce un componente UI PlayerView
che puoi includere nel file di layout della tua app. Questo componente include un PlayerControlView
per i controlli di riproduzione, un SubtitleView
per la visualizzazione dei sottotitoli codificati e un Surface
per il rendering del video.
Preparazione del lettore
Aggiungi elementi multimediali a una playlist per la riproduzione con metodi come setMediaItem()
e addMediaItem()
.
Poi chiama prepare()
per
iniziare a caricare i contenuti multimediali e acquisire le risorse necessarie.
Non devi eseguire questi passaggi prima che l'app sia in primo piano. Se il tuo
player si trova in un Activity
o Fragment
, significa prepararlo nel
metodo del ciclo di vita onStart()
sul livello API 24 e versioni successive o nel metodo del ciclo di vita onResume()
sul livello API 23 e versioni precedenti. Per un giocatore che si trova in un Service
,
puoi prepararlo in onCreate()
.
Controllare il player
Dopo aver preparato il player, puoi controllare la riproduzione chiamando i metodi sul player, ad esempio:
play()
epause()
per avviare e mettere in pausa la riproduzioneseekTo()
per spostarti in una posizione all'interno dell'elemento multimediale correnteseekToNextMediaItem()
eseekToPreviousMediaItem()
per navigare nella playlist.
I componenti UI come PlayerView
o PlayerControlView
verranno aggiornati
di conseguenza quando sono associati a un player.
Rilasciare il giocatore
La riproduzione può richiedere risorse con disponibilità limitata, come i decoder video, pertanto è importante chiamare release()
sul player per liberare risorse quando il player non è più necessario.
Se il lettore si trova in uno stato Activity
o Fragment
, rilascia il lettore nel metodo del ciclo di vita
onStop()
sul livello API 24 e versioni successive o nel metodo onPause()
sul livello API 23 e versioni precedenti. Per un giocatore che si trova in un Service
, puoi
rilasciarlo in onDestroy()
.
Gestione della riproduzione con una sessione multimediale
Su Android, le sessioni multimediali forniscono un modo standardizzato per interagire con un lettore multimediale oltre i limiti del processo. Il collegamento di una sessione multimediale al tuo player ti consente di pubblicizzare la riproduzione dei contenuti multimediali esternamente e di ricevere comandi di riproduzione da fonti esterne, ad esempio per l'integrazione con i controlli multimediali di sistema su dispositivi mobili e con schermi di grandi dimensioni.
Per utilizzare le sessioni multimediali, aggiungi una dipendenza dal modulo Session di Media3:
implementation "androidx.media3:media3-session:1.7.1"
Crea una sessione media
Puoi creare un MediaSession
dopo aver inizializzato un player nel seguente modo:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 sincronizza automaticamente lo stato di Player
con lo stato di MediaSession
. Funziona con qualsiasi implementazione di Player
, inclusi
ExoPlayer
, CastPlayer
o un'implementazione
personalizzata.
Concedere il controllo ad altri client
Le app client possono implementare un controller multimediale
per controllare la riproduzione della sessione multimediale. Per ricevere queste richieste, imposta un oggetto
callback durante la
creazione di MediaSession
.
Quando un controller sta per connettersi alla sessione multimediale, viene chiamato il metodo
onConnect()
. Puoi utilizzare il ControllerInfo
fornito
per decidere se accettare
o rifiutare
la richiesta. Vedi un esempio di questo nell'app demo Media3 Session.
Una volta connesso, un controller può inviare comandi di riproduzione alla sessione. La
sessione delega quindi questi comandi al giocatore. I comandi di riproduzione e delle playlist definiti nell'interfaccia Player
vengono gestiti automaticamente dalla sessione.
Altri metodi di callback ti consentono di gestire, ad esempio, richieste di
comandi di riproduzione personalizzati
e modifica della playlist. Questi callback includono in modo simile un oggetto ControllerInfo
in modo da poter determinare il controllo dell'accesso in base alle singole richieste.
Riproduzione di contenuti multimediali in background
Per continuare a riprodurre contenuti multimediali quando l'app non è in primo piano, ad esempio
per riprodurre musica, audiolibri o podcast anche quando l'utente non ha aperto l'app,
Player
e MediaSession
devono essere incapsulati in un
servizio in primo piano. Media3 fornisce
l'interfaccia MediaSessionService
a questo scopo.
Implementare un MediaSessionService
Crea una classe che estenda MediaSessionService
e crea un'istanza di MediaSession
nel metodo del ciclo di vita onCreate()
.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
Nel manifest, la classe Service
con un filtro
di intent MediaSessionService
e richiedi l'autorizzazione
FOREGROUND_SERVICE
per eseguire un servizio in primo piano:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Infine, nella classe che hai creato, esegui l'override del metodo onGetSession()
per controllare
l'accesso del client alla sessione multimediale. Restituisci MediaSession
per accettare la
richiesta di connessione oppure restituisci null
per rifiutarla.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Connessione alla UI in corso…
Ora che la sessione multimediale si trova in un Service
separato da Activity
o
Fragment
in cui si trova la UI del player, puoi utilizzare un MediaController
per collegarli. Nel metodo onStart()
di Activity
o Fragment
con la tua
UI, crea un SessionToken
per il tuo MediaSession
, poi utilizza SessionToken
per creare un MediaController
. La creazione di un MediaController
avviene
in modo asincrono.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController
implementa l'interfaccia Player
, quindi puoi utilizzare gli stessi
metodi come play()
e pause()
per controllare la riproduzione. Come per altri
componenti, ricordati di rilasciare MediaController
quando non è più
necessario, ad esempio il metodo del ciclo di vita onStop()
di un Activity
, chiamando
MediaController.releaseFuture()
.
Pubblicare una notifica
I servizi in primo piano devono pubblicare una notifica mentre sono attivi. Un
MediaSessionService
creerà automaticamente una
notifica MediaStyle
per
te sotto forma di MediaNotification
.
Per fornire una notifica personalizzata, crea un
MediaNotification.Provider
con DefaultMediaNotificationProvider.Builder
o creando un'implementazione personalizzata dell'interfaccia del fornitore. Aggiungi il tuo
provider a MediaSession
con
setMediaNotificationProvider
.
Pubblicizzare la tua raccolta di contenuti
Un MediaLibraryService
si basa su un MediaSessionService
consentendo alle app client di sfogliare i contenuti multimediali forniti dalla tua app. Le app client implementano un MediaBrowser
per interagire con il tuo MediaLibraryService
.
L'implementazione di un MediaLibraryService
è simile a quella di un
MediaSessionService
, tranne che in onGetSession()
devi restituire un
MediaLibrarySession
anziché un MediaSession
. Rispetto a un
MediaSession.Callback
, il MediaLibrarySession.Callback
include metodi
aggiuntivi che consentono a un client browser di navigare nei contenuti offerti dal tuo
servizio di biblioteca.
Analogamente a MediaSessionService
, dichiara MediaLibraryService
nel tuo
manifest e richiedi l'autorizzazione FOREGROUND_SERVICE
per eseguire un servizio in primo piano:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
L'esempio precedente include un filtro per intent sia per MediaLibraryService
sia, per la compatibilità con le versioni precedenti, per MediaBrowserService
. Il
filtro per intent aggiuntivo consente alle app client che utilizzano l'API MediaBrowserCompat
di riconoscere il tuo Service
.
Un MediaLibrarySession
ti consente di pubblicare la tua raccolta di contenuti in una struttura ad albero, con una singola MediaItem
radice. Ogni MediaItem
nell'albero può avere
un numero illimitato di nodi secondari MediaItem
. Puoi pubblicare una radice diversa o un albero diverso in base alla richiesta dell'app client. Ad esempio, l'albero che restituisci a un client che cerca un elenco di elementi multimediali consigliati potrebbe contenere solo il nodo radice MediaItem
e un singolo livello di nodi secondari MediaItem
, mentre l'albero che restituisci a un'altra app client potrebbe rappresentare una libreria di contenuti più completa.
Creazione di un MediaLibrarySession
in corso…
Un MediaLibrarySession
estende l'API MediaSession
per aggiungere API di navigazione dei contenuti. Rispetto al
callback MediaSession
,
il callback MediaLibrarySession
aggiunge metodi come:
onGetLibraryRoot()
per quando un cliente richiede la radiceMediaItem
di una struttura dei contenutionGetChildren()
per quando un client richiede i figli di unMediaItem
nell'albero dei contenutionGetSearchResult()
per quando un client richiede i risultati di ricerca dall'albero dei contenuti per una determinata query
I metodi di callback pertinenti includeranno un oggetto LibraryParams
con indicatori aggiuntivi sul tipo di albero dei contenuti a cui è interessata
un'app client.