Jetpack Media3 definisce un'interfaccia Player
che illustra 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 di riproduzione ed è personalizzabile per gestire eventuali casi d'uso aggiuntivi. ExoPlayer inoltre consente di astrarre la frammentazione del dispositivo e del sistema operativo, in modo che il codice funzioni in modo coerente nell'intero ecosistema Android. ExoPlayer include:
- Supporto per le playlist
- Supporto di diversi formati di streaming progressivo e adattativo
- Supporto dell'inserimento di annunci sia lato client sia lato server
- Supporto della riproduzione con protezione DRM
Questa pagina illustra alcuni dei passaggi chiave per creare un'app di riproduzione. Per maggiori dettagli, consulta le nostre guide complete su Media3 ExoPlayer.
Per iniziare
Per iniziare, aggiungi una dipendenza dai moduli ExoPlayer, UI e Common di Media3 di Jetpack:
implementation "androidx.media3:media3-exoplayer:1.4.1" implementation "androidx.media3:media3-ui:1.4.1" implementation "androidx.media3:media3-common:1.4.1"
A seconda del caso d'uso, potresti anche aver bisogno di moduli aggiuntivi di Media3, come exoplayer-dash
per riprodurre gli stream in formato DASH.
Assicurati di sostituire 1.4.1
con la versione che preferisci della biblioteca. Puoi consultare le note di rilascio per visualizzare la versione più recente.
Creazione di un media player
Con Media3, puoi utilizzare l'implementazione inclusa dell'Player
interfaccia 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 media player nel metodo di ciclo di vita onCreate()
del Activity
, del Fragment
o del 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 output audio è 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 incapsula un PlayerControlView
per i controlli di riproduzione, un SubtitleView
per la visualizzazione dei sottotitoli e un Surface
per il rendering del video.
Preparazione del player
Aggiungere elementi multimediali a una playlist per la riproduzione con metodi come setMediaItem()
e addMediaItem()
.
Quindi, 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 è in un Activity
o Fragment
, significa che deve prepararlo nel
metodo del ciclo di vita onStart()
a partire dal livello API 24 e nel metodo di ciclo di vita onResume()
a partire dal livello API 23. Per un giocatore che si trova in Service
,
puoi prepararlo in onCreate()
.
Controllare il player
Dopo aver preparato il player, puoi controllarne la riproduzione chiamando metodi sul player, ad esempio:
play()
epause()
per avviare e mettere in pausa la riproduzioneseekTo()
per andare a una posizione all'interno dell'elemento multimediale correnteseekToNextMediaItem()
eseekToPreviousMediaItem()
per spostarti nella playlist.
I componenti dell'interfaccia utente, come PlayerView
o PlayerControlView
, si aggiorneranno di conseguenza quando sono associati a un player.
Rilascia il player
La riproduzione può richiedere risorse limitate, come i decodificatori video, pertanto è importante chiamare release()
sul player per liberare risorse quando non è più necessario.
Se il player si trova in un Activity
o Fragment
, rilascialo nel
metodo del ciclo di vita onStop()
a partire dal livello API 24 o con il metodo onPause()
con il livello API 23 e versioni precedenti. Per un giocatore che si trova in un Service
, puoi liberarlo in onDestroy()
.
Gestire la riproduzione con una sessione multimediale
Su Android, le sessioni multimediali forniscono un modo standardizzato per interagire con un media player oltre i confini dei processi. La connessione di una sessione multimediale al player consente di pubblicizzare la riproduzione di contenuti multimediali all'esterno 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 al modulo Media3 Session:
implementation "androidx.media3:media3-session:1.4.1"
Crea una sessione multimediale
Puoi creare un MediaSession
dopo aver inizializzato un player come segue:
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 del Player
con lo stato del
MediaSession
. Funziona con qualsiasi implementazione di Player
, tra cui ExoPlayer
, CastPlayer
o un'implementazione personalizzata.
Concedere il controllo ad altri client
Le app client possono implementare un controllore multimediale per controllare la riproduzione della sessione multimediale. Per ricevere queste richieste, imposta un oggetto callback quando crei il tuo 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 nell'app demo Media3 Session.
Una volta connesso, un controller può inviare comandi di riproduzione alla sessione. La sessione poi delega questi comandi al player. I comandi di riproduzione e playlist definiti nell'interfaccia Player
vengono gestiti automaticamente dalla sessione.
Altri metodi di callback ti consentono di gestire, ad esempio, le richieste di
comandi di riproduzione personalizzati
e di modificare la playlist. In modo analogo, questi callback includono un oggetto ControllerInfo
, che ti consente
di determinare il controllo dell'accesso in base alle singole richieste.
Riproduzione di contenuti multimediali in background
Per continuare a riprodurre contenuti multimediali quando la tua app non è in primo piano, ad esempio per riprodurre musica, audiolibri o podcast anche quando l'utente non ha aperto la tua app, Player
e MediaSession
devono essere incapsulati in un
servizio in primo piano. Media3 fornisce l'interfaccia MediaSessionService
a questo scopo.
Implementazione di un MediaSessionService
Crea una classe che estenda MediaSessionService
e crea un'istanza di MediaSession
nel metodo di 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 file manifest, la classe Service
con un filtro intentMediaSessionService
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, nel corso che hai creato, sostituisci il metodo onGetSession()
per controllare
l'accesso del client alla tua sessione multimediale. Restituisci un MediaSession
per accettare la richiesta di connessione oppure restituisce null
per rifiutare la richiesta.
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 all'interfaccia utente in corso...
Ora che la sessione multimediale si trova in un Service
separato da Activity
o
Fragment
in cui si trova l'UI del tuo player, puoi utilizzare MediaController
per
collegarli. Nel metodo onStart()
di Activity
o Fragment
con la UI, crea un SessionToken
per il MediaSession
, quindi utilizza il 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 gli altri componenti, ricordati di rilasciare MediaController
quando non è più necessario, ad esempio il metodo di ciclo di vita onStop()
di un Activity
, chiamando MediaController.releaseFuture()
.
Pubblicazione di una notifica
I servizi in primo piano sono tenuti a pubblicare una notifica quando sono attivi. Un
MediaSessionService
creerà automaticamente una
MediaStyle
notifica 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 provider. Aggiungi il tuo
provider a MediaSession
con
setMediaNotificationProvider
.
Pubblicità della raccolta di contenuti
Un MediaLibraryService
si basa su MediaSessionService
consentendo alle app client di sfogliare i contenuti multimediali forniti dalla tua app. Le app client implementano MediaBrowser
per interagire con MediaLibraryService
.
L'implementazione di un MediaLibraryService
è simile a quella di un
MediaSessionService
, tranne per il fatto che in onGetSession()
devi restituire un
MediaLibrarySession
anziché un MediaSession
. Rispetto a un MediaSession.Callback
, MediaLibrarySession.Callback
include metodi aggiuntivi che consentono a un client del browser di navigare nei contenuti offerti dal tuo servizio di biblioteca.
Come per 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 riportato sopra include un filtro intent sia per MediaLibraryService
che, per la compatibilità con le versioni precedenti, per MediaBrowserService
precedente. Il
filtro di 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 un singolo MediaItem
principale. Ogni MediaItem
nell'albero può avere un numero illimitato di nodi MediaItem
secondari. Puoi pubblicare una radice o un albero diverso in base alla richiesta dell'app client. Ad esempio, la struttura ad albero restituita a un client che cerca un elenco di elementi multimediali consigliati potrebbe contenere solo il nodo principale MediaItem
e un singolo livello di nodi MediaItem
secondari, mentre la struttura ad albero che torni a un'altra app client potrebbe rappresentare una libreria di contenuti più completa.
Creazione di un MediaLibrarySession
Una MediaLibrarySession
estende l'API MediaSession
per aggiungere API di navigazione dei contenuti. Rispetto al
callback MediaSession
,
il
callback MediaLibrarySession
aggiunge metodi come:
onGetLibraryRoot()
quando un client richiede la radiceMediaItem
di una struttura di contenutionGetChildren()
per quando un client richiede gli elementi secondari di unaMediaItem
nell'albero dei contenutionGetSearchResult()
quando un client richiede i risultati di ricerca dalla struttura ad 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.