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 set completo di funzionalità che coprono la maggior parte dei casi d'uso di 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 in tutto l'ecosistema Android. ExoPlayer include:
- Supporto per le playlist
- Supporto per una varietà di formati di streaming progressivo e adattivo formats
- Supporto per l'inserimento di annunci lato client e lato server ad insertion
- Supporto per la riproduzione di contenuti protetti da DRM
Questa pagina illustra alcuni dei passaggi chiave per la creazione di 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 Jetpack Media3:
Kotlin
implementation("androidx.media3:media3-exoplayer:1.11.0")
implementation("androidx.media3:media3-ui:1.11.0")
implementation("androidx.media3:media3-common:1.11.0")
Alla moda
implementation "androidx.media3:media3-exoplayer:1.11.0"
implementation "androidx.media3:media3-ui:1.11.0"
implementation "androidx.media3:media3-common:1.11.0"
A seconda del caso d'uso, potresti aver bisogno anche di moduli aggiuntivi di Media3, come exoplayer-dash per riprodurre stream in formato DASH.
Assicurati di sostituire 1.11.0 con la versione della libreria che preferisci. Puoi consultare le note sulla versione per visualizzare l'ultima
versione.
Creazione di un media player
Con Media3, puoi utilizzare l'implementazione inclusa dell'Player
interfaccia, ExoPlayer, oppure puoi 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 del ciclo di vita onCreate() di Activity, Fragment o Service in cui si trova.
The 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 viene disconnessosetTrackSelector()per configurare la selezione delle tracce
Media3 fornisce un componente UI PlayerView che puoi includere nel file di layout dell'app. Questo componente incapsula un PlayerControlView per i controlli di riproduzione, SubtitleView per la visualizzazione dei sottotitoli e Surface per il rendering dei video.
Preparazione del player
Aggiungi elementi multimediali a una playlist per la riproduzione con metodi come
setMediaItem() e addMediaItem(). Poi, chiama prepare() per avviare
il caricamento dei contenuti multimediali e acquisire le risorse necessarie.
Non devi eseguire questi passaggi prima che l'app sia in primo piano. Se il player si trova in un Activity o Fragment, significa che devi 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 player in un Service, puoi prepararlo in onCreate(). Per un
esempio di come implementare i metodi del ciclo di vita, consulta il codelab di Exoplayer.
Controllo del player
Dopo aver preparato il player, puoi controllare la riproduzione chiamando metodi come:
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 UI come PlayerView o PlayerControlView si aggiorneranno di conseguenza quando sono associati a un player.
Rilascio del player
La riproduzione può richiedere risorse in quantità limitata, come i video
decoder, quindi è importante chiamare release() sul player per liberare
le risorse quando non è più necessario.
Se il player si trova in un Activity o Fragment, rilascialo 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 player in un Service, puoi rilasciarlo in onDestroy(). Per un esempio di come
implementare i metodi del ciclo di vita, consulta il codelab di Exoplayer.
Gestione della riproduzione con una sessione multimediale
Su Android, le sessioni multimediali forniscono un modo standardizzato per interagire con un media player tra i limiti dei processi. Il collegamento di una sessione multimediale al player ti consente di pubblicizzare la riproduzione di 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 Media3 Session:
Kotlin
implementation("androidx.media3:media3-session:1.11.0")
Alla moda
implementation "androidx.media3:media3-session:1.11.0"
Creazione di 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 di Player con lo stato di MediaSession. Questa funzionalità è compatibile con qualsiasi Player implementazione, inclusi
ExoPlayer, CastPlayer o un'implementazione personalizzata.
Concessione del 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 callback object quando crei il tuo
MediaSession.
Quando un controller sta per connettersi alla sessione multimediale, viene chiamato il onConnect()
metodo. Puoi utilizzare ControllerInfo fornito per decidere se
accettare o rifiutare la richiesta. Per un esempio, consulta l'app demo di Media3
Session.
Una volta connesso, un controller può inviare comandi di riproduzione alla sessione. La sessione delega quindi 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 la modifica della playlist. Questi callback includono anche un oggetto ControllerInfo, in modo da poter determinare il controllo dell'accesso in base alla richiesta.
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.
Implementazione di un MediaSessionService
Crea una classe che estenda MediaSessionService e crea un'istanza di your
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, dichiara la 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 client alla sessione multimediale. Restituisci un MediaSession per accettare la richiesta di connessione o 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 all'UI
Ora che la sessione multimediale si trova in un Service separato da Activity o Fragment in cui si trova l'UI del player, puoi utilizzare un MediaController per collegarli. Nel metodo onStart() di Activity o Fragment con l'UI, crea un SessionToken per MediaSession, quindi 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 gli altri
componenti, ricorda di rilasciare MediaController quando non è più
necessario nel metodo del 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 mentre sono attivi. Un
MediaSessionService creerà automaticamente una notifica MediaStyle
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 provider a tuo
MediaSession con setMediaNotificationProvider.
Pubblicizzazione della 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 MediaLibraryService.
L'implementazione di un MediaLibraryService è simile all'implementazione di un
MediaSessionService, tranne 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 browser di navigare tra i contenuti offerti dal 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 precedente include un filtro per intent sia per MediaLibraryService sia, per la retrocompatibilità, per il MediaBrowserService legacy. 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 un singolo MediaItem radice. Ogni MediaItem nell'albero può avere un numero qualsiasi di nodi MediaItem secondari. 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 la radice MediaItem e un singolo livello di nodi MediaItem secondari, mentre l'albero che restituisci a un'altra app client potrebbe rappresentare una raccolta di contenuti più completa.
Creazione di un MediaLibrarySession
Un MediaLibrarySession estende l'API MediaSession per aggiungere API di navigazione dei contenuti. Rispetto al MediaSession callback, il MediaLibrarySession
callback aggiunge metodi come:
onGetLibraryRoot()quando un client richiede la radiceMediaItemdi un albero di contenutionGetChildren()quando un client richiede i figli di unMediaItemnell'albero dei contenutionGetSearchResult()quando un client richiede i risultati di ricerca dall'albero dei contenuti per una determinata query
I metodi di callback pertinenti includeranno un LibraryParams oggetto con
segnali aggiuntivi sul tipo di albero di contenuti a cui è
interessata un'app client.