Jetpack Media3 definisce un'interfaccia Player
che descrive le funzionalità di base
per la riproduzione di file video e audio. ExoPlayer
è l'implementazione predefinita
di questa interfaccia in Media3. Consigliamo di utilizzare ExoPlayer, poiché fornisce un insieme completo di funzionalità che coprono la maggior parte dei casi d'uso di riproduzione ed è personalizzabile per gestire eventuali altri casi d'uso. ExoPlayer elimina anche 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 una varietà di formati di streaming progressivo e adattivo
- Supporto per l'inserimento di annunci lato client e lato server
- Supporto per la riproduzione protetta da DRM
In questa pagina vengono illustrati alcuni dei passaggi principali per la creazione di un'app di riproduzione; per ulteriori dettagli, puoi consultare le nostre guide complete su Media3 ExoPlayer.
Per iniziare
Per iniziare, aggiungi una dipendenza ai moduli ExoPlayer, UI e Common di Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.3.1" implementation "androidx.media3:media3-ui:1.3.1" implementation "androidx.media3:media3-common:1.3.1"
A seconda del caso d'uso, potrebbero essere necessari anche moduli aggiuntivi di Media3,
ad esempio exoplayer-dash
per riprodurre gli stream nel formato DASH.
Assicurati di sostituire 1.3.1
con la tua versione preferita della libreria. Puoi consultare le note di rilascio
per conoscere la versione più recente.
Creazione di un media player
Con Media3, puoi utilizzare l'implementazione inclusa dell'interfaccia Player
, ExoPlayer
, oppure 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, tra cui:
setAudioAttributes()
per configurare la gestione dell'elemento attivo 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 PlayerControlView
per i controlli di riproduzione, SubtitleView
per la visualizzazione dei sottotitoli e Surface
per il rendering del video.
Preparazione del player
Aggiungi elementi multimediali a una playlist per la riproduzione con metodi quali 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 si trova in un Activity
o Fragment
, significa che lo prepara nel
metodo del ciclo di vita onStart()
a livello dell'API 24 e livelli successivi o al metodo del ciclo di vita onResume()
con il livello API 23 e livelli precedenti. Per un giocatore in un Service
,
puoi prepararlo in onCreate()
.
Controllare il player
Dopo che il player è stato preparato, puoi controllare la riproduzione richiamando metodi sul player quali:
play()
epause()
per avviare e mettere in pausa la riproduzioneseekTo()
per cercare una posizione all'interno dell'elemento multimediale correnteseekToNextMediaItem()
eseekToPreviousMediaItem()
per navigare nella playlist
I componenti dell'interfaccia utente come PlayerView
o PlayerControlView
verranno aggiornati
di conseguenza quando sono associati a un player.
Rilascia il player
La riproduzione può richiedere risorse limitate, ad esempio i decodificatori video, quindi è importante chiamare release()
sul player per liberare risorse quando il player non è più necessario.
Se il player si trova in un Activity
o Fragment
, rilascialo secondo il
onStop()
metodo del ciclo di vita all'API 24 e livelli successivi o onPause()
al livello API 23 e sotto. Per un player in un dispositivo Service
, puoi
rilasciarlo 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. Se colleghi una sessione multimediale al player, puoi pubblicizzare la riproduzione di contenuti multimediali esternamente e ricevere comandi di riproduzione da fonti esterne, ad esempio per integrare i controlli multimediali di sistema su dispositivi mobili e schermi di grandi dimensioni.
Per utilizzare le sessioni multimediali, aggiungi una dipendenza nel modulo Sessione Media3:
implementation "androidx.media3:media3-session:1.3.1"
Creare una sessione multimediale
Dopo aver inizializzato un player, puoi creare un MediaSession
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 quello di MediaSession
. Questo vale con qualsiasi implementazione di Player
, tra cui
ExoPlayer
, CastPlayer
o
un'implementazione personalizzata.
Concedi il controllo ad altri clienti
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 del tuo MediaSession
.
Quando un controller sta per connettersi alla tua sessione multimediale, viene chiamato il metodo onConnect()
. Puoi utilizzare l'elemento ControllerInfo
fornito per decidere se accettare o rifiutare la richiesta. Guarda un esempio nell'app demo Media3 Session.
Una volta connesso, un controller può inviare comandi di riproduzione alla sessione. La sessione delega questi comandi al player. I comandi per la riproduzione e la 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 simile, questi callback includono un oggetto ControllerInfo
in modo da poter determinare il controllo dell'accesso in base alle 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 di MediaSessionService
a questo scopo.
Implementare un MediaSessionService
Crea una classe che estende MediaSessionService
e crei un'istanza del tuo
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 file manifest, la tua classe Service
con un filtro per 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 un valore MediaSession
per accettare la richiesta di connessione oppure 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 tua sessione multimediale si trova in un Service
separato da quello in Activity
o Fragment
in cui si trova l'interfaccia utente del tuo player, puoi utilizzare un MediaController
per collegarli tra loro. Nel metodo onStart()
di Activity
o Fragment
con la tua
UI, crea un SessionToken
per MediaSession
, quindi usa 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()
.
Pubblicazione di una notifica
Per poter pubblicare una notifica quando sono attivi, i servizi in primo piano sono necessari. Un
MediaSessionService
creerà automaticamente una
notifica MediaStyle
sotto forma di MediaNotification
.
Per fornire una notifica personalizzata, crea un elemento MediaNotification.Provider
con DefaultMediaNotificationProvider.Builder
o un'implementazione personalizzata dell'interfaccia del provider. Aggiungi il tuo provider a MediaSession
con setMediaNotificationProvider
.
Pubblicizzare la raccolta di contenuti
Un elemento MediaLibraryService
si basa su MediaSessionService
consentendo alle app client di sfogliare i contenuti multimediali forniti dalla tua app. Le app client implementano un elemento MediaBrowser
per interagire con MediaLibraryService
.
L'implementazione di MediaLibraryService
è simile all'implementazione di un MediaSessionService
, ad eccezione del fatto che in onGetSession()
dovresti restituire un MediaLibrarySession
anziché un MediaSession
. Rispetto a MediaSession.Callback
, MediaLibrarySession.Callback
include metodi aggiuntivi che consentono a un client browser di esplorare i contenuti offerti dal tuo servizio di raccolta.
Analogamente a MediaSessionService
, dichiara MediaLibraryService
nel file 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 per intent sia per MediaLibraryService
sia, per la compatibilità con le versioni precedenti, per la versione precedente di MediaBrowserService
. Il
filtro per intent aggiuntivo consente alle app client che utilizzano l'API MediaBrowserCompat
di riconoscere Service
.
Un MediaLibrarySession
ti consente di pubblicare la tua raccolta di contenuti in una struttura
ad albero, con un'unica radice MediaItem
. Ogni MediaItem
nell'albero può avere
un numero illimitato di nodi MediaItem
secondari. Puoi pubblicare una radice diversa o un albero diverso, in base alla richiesta dell'app client. Ad esempio, la struttura ad albero restituita a un client in cerca di un elenco di elementi multimediali consigliati potrebbe contenere solo l'elemento principale MediaItem
e un singolo livello di nodi MediaItem
secondari, mentre la struttura restituita a un'app client diversa potrebbe rappresentare una libreria di contenuti più completa.
Creazione di un MediaLibrarySession
in corso...
Un elemento MediaLibrarySession
estende l'API MediaSession
per aggiungere API per la navigazione di contenuti. Rispetto al callback MediaSession
, il callback MediaLibrarySession
aggiunge metodi quali:
onGetLibraryRoot()
per quando un client richiede il valoreMediaItem
principale di una struttura ad albero dei contenutionGetChildren()
per quando un cliente richiede i figli diMediaItem
nella struttura ad albero dei contenutionGetSearchResult()
per quando un client richiede 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.