Screenshot: L’applicazione YouTube per Android
ExoPlayer è un lettore multimediale a livello di applicazione costruito sopra le API di basso livello di Android. ExoPlayer ha una serie di vantaggi rispetto al MediaPlayer integrato in Android. Supporta molti degli stessi formati multimediali di MediaPlayer, più i formati adattivi, come DASH e SmoothStreaming. ExoPlayer è altamente personalizzabile ed estensibile, rendendolo capace di molti casi d’uso avanzati. È un progetto open source usato dalle applicazioni di Google, tra cui YouTube e Google Play Movies & TV.
- Prequisiti
- Cosa farai
- Di cosa avrai bisogno
- Prendi il codice
- Struttura della directory
- Importa il progetto iniziale
- app/build.gradle
- Aggiungi dipendenza ExoPlayer
- player-lib/build.gradle
- Aggiungi l’elemento PlayerView
- activity_player.xml
- PlayerActivity.java
- Creare un ExoPlayer
- PlayerActivity.java
- Crea un elemento multimediale
- PlayerActivity.java
- Giocare bene con il ciclo di vita dell’attività
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Preparazione finale
- PlayerActivity.java
- Play audio
- Testare il ciclo di vita dell’attività
- Play video
- PlayerActivity.java
- PlayerActivity.java
- Selezione adattiva delle tracce
- PlayerActivity.java
- Costruisci un MediaItem adattivo
- PlayerActivity.java
- Altri formati di streaming adattivo
- Ascolta
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Registra il tuo listener
- PlayerActivity.java
- PlayerActivity.java
- Vai più a fondo
- activity_player.xml
- activity_player.xml
- Personalizza il comportamento
- activity_player.xml
- Personalizza l’aspetto
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- Sovrascrivi lo stile predefinito
- activity_player.xml
- exo_player**_control_view.xml**
- Impara di più
Prequisiti
- Conoscenza moderata dello sviluppo Android e di Android Studio
Cosa farai
- Crea un’istanza
SimpleExoPlayer
, che prepara e riproduce media da una varietà di fonti. - Integrare ExoPlayer con il ciclo di vita delle attività dell’app per supportare il backgrounding, il foregrounding e la ripresa della riproduzione in un ambiente a finestra singola o multipla.
- Utilizzare
MediaItem
per creare una playlist. - Produrre flussi video adattivi, che adattano la qualità dei media alla larghezza di banda disponibile.
- Registrare ascoltatori di eventi per monitorare lo stato della riproduzione e mostrare come gli ascoltatori possono essere usati per misurare la qualità della riproduzione.
- Utilizza i componenti standard dell’UI di ExoPlayer, poi personalizzali secondo lo stile della tua app.
Di cosa avrai bisogno
- Android Studio versione 3.5 o superiore
- Un dispositivo Android con JellyBean (4.1) o superiore, idealmente con Nougat (7.1) o superiore in quanto supporta finestre multiple.
Prendi il codice
Per iniziare, scarica il progetto Android Studio:
Scarica lo zip
In alternativa, puoi clonare il repository GitHub:
git clone https://github.com/googlecodelabs/exoplayer-intro.git
Struttura della directory
La clonazione o la decompressione ti fornisce una cartella principale (exoplayer-intro
), che contiene una cartella per ogni passo di questo codelab, insieme a tutte le risorse necessarie:
/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-00/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-01/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-02/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-03/PATH/TO/YOUR/FOLDER/exoplayer-intro/exoplayer-codelab-04
Le cartelle exoplayer-codelab-N
(dove N
è 00
a 04
) contengono lo stato finale desiderato di ogni passo di questo codelab. Questi sono progetti Android Studio autonomi, ognuno dei quali può essere importato.
Importa il progetto iniziale
- Avvia Android Studio.
- Scegli File > Nuovo > Importa progetto*.*
- Importa il progetto iniziale da
exoplayer-codelab-00
.
Screenshot: Struttura del progetto durante l’importazione
Dopo la fine della compilazione, si vedono due moduli: il modulo app
(di tipo applicazione) e il modulo player-lib
(di tipo libreria). Il modulo app
è in realtà vuoto, avendo solo un manifest. Tutto dal modulo player-lib
viene unito quando l’applicazione viene costruita usando una dipendenza gradle in app/build.gradle
.
app/build.gradle
dependencies { implementation project(":player-lib")}
La tua attività di lettore multimediale è tenuta nel modulo player-lib
. La ragione per tenerlo in un modulo di libreria separato è che puoi condividerlo tra gli APK destinati a diverse piattaforme, come mobile e Android TV. Ti permette anche di approfittare di caratteristiche, come la consegna dinamica, che permettono alla tua funzione di riproduzione multimediale di essere installata solo quando l’utente ne ha bisogno.
- Deploy ed esegui l’app per controllare che tutto sia a posto. L’app dovrebbe riempire lo schermo con uno sfondo nero.
Screenshot: App vuota in esecuzione
Aggiungi dipendenza ExoPlayer
ExoPlayer è un progetto open source ospitato su GitHub. Ogni release è distribuita attraverso jCenter, che è uno dei repository di pacchetti predefiniti usati da Android Studio e Gradle. Ogni release è identificata in modo univoco da una stringa con il seguente formato:
com.google.android.exoplayer:exoplayer:rX.X.X
Puoi aggiungere ExoPlayer al tuo progetto semplicemente importando le sue classi e componenti UI. È piuttosto piccolo, avendo un ingombro ridotto di circa 70-300 kB a seconda delle caratteristiche incluse e dei formati supportati. La libreria ExoPlayer è divisa in moduli per permettere agli sviluppatori di importare solo le funzionalità di cui hanno bisogno. Per maggiori informazioni sulla struttura modulare di ExoPlayer, vedi Aggiungere i moduli di ExoPlayer.
- Aprire il file
build.gradle
del moduloplayer-lib
. - Aggiungere le seguenti righe alla sezione
dependencies
e sincronizzare il progetto.
player-lib/build.gradle
dependencies { implementation 'com.google.android.exoplayer:exoplayer-core:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-dash:2.12.0'implementation 'com.google.android.exoplayer:exoplayer-ui:2.12.0'}
Aggiungi l’elemento PlayerView
- Apri il file delle risorse di layout
activity_player.xml
dal moduloplayer-lib
. - Posiziona il cursore dentro l’elemento
FrameLayout
. - Inizia a digitare
<PlayerView
e lascia che Android Studio completi automaticamente l’elementoPlayerView
. - Usa
match_parent
per ilwidth
eheight
. - Dichiara l’id come
video_view
.
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
Andando avanti, ti riferisci a questo elemento UI come vista video.
- Nella
PlayerActivity
, ora devi trovare la vista video in modo da poterla impostare correttamente nel metodoonCreate
dell’attività.
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- Aggiungi il campo membro
playerView
alla tua classePlayerActivity
. Assicurati che il tipo di vista siaPlayerView
.
Nota: Usa la funzione Quick Fix in Android Studio per aggiungere automaticamente un campo membro. Ricordati di impostare il tipo a
PlayerView
invece del default
View
Screenshot: Quick fix menu for making a member field
Creare un ExoPlayer
Per riprodurre media in streaming, hai bisogno di un oggetto ExoPlayer
. Il modo più semplice per crearne uno è usare la classe SimpleExoPlayer.Builder
. Come suggerisce il nome, questa usa il modello del costruttore per costruire un’istanza SimpleExoPlayer
.
SimpleExoPlayer
è una comoda implementazione per tutti gli usi dell’interfaccia ExoPlayer
.
Aggiungi un metodo privato initializePlayer
per creare il tuo SimpleExoPlayer
.
PlayerActivity.java
private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}
Crea un SimpleExoPlayer.Builder
usando il tuo contesto, poi chiama build
per creare il tuo oggetto SimpleExoPlayer
. Questo viene poi assegnato a player
, che dovete dichiarare come campo membro. Usate quindi playerView.setPlayer
per legare il player
alla sua vista corrispondente.
Crea un elemento multimediale
Il vostro player
ora ha bisogno di un contenuto da riprodurre. Per questo, si crea un MediaItem
. Ci sono molti tipi diversi di MediaItem
, ma tu inizi a crearne uno per un file MP3 su internet.
Il modo più semplice per creare un MediaItem
è usare MediaItem.fromUri
, che accetta l’URI di un file multimediale. Aggiungi il MediaItem
al player
usando player.setMediaItem
.
- Aggiungi il seguente codice a
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}
Nota che R.string.media_url_mp3
è definito come https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 in strings.xml
.
Giocare bene con il ciclo di vita dell’attività
Il nostro player
può monopolizzare molte risorse tra cui memoria, CPU, connessioni di rete e codec hardware. Molte di queste risorse sono a corto di risorse, in particolare per i codec hardware dove ce ne può essere solo uno. È importante che tu rilasci queste risorse affinché le altre app le usino quando non le stai usando, come quando la tua app viene messa in background.
In altre parole, il ciclo di vita del tuo lettore dovrebbe essere legato al ciclo di vita della tua app. Per implementare questo, è necessario sovrascrivere i quattro metodi di PlayerActivity
: onStart
, onResume
, onPause
e onStop
.
- Con
PlayerActivity
aperto, clicca sul menu Codice > Sovrascrivi metodi…. - Seleziona
onStart
,onResume
,onPause
eonStop
. - Inizializza il player nel callback
onStart
oonResume
a seconda del livello API.
PlayerActivity.java
@Overridepublic void onStart() { super.onStart(); if (Util.SDK_INT >= 24) { initializePlayer(); }}@Overridepublic void onResume() { super.onResume(); hideSystemUi(); if ((Util.SDK_INT < 24 || player == null)) { initializePlayer(); }}
Il livello 24 e superiore delle API Android supporta finestre multiple. Poiché la vostra applicazione può essere visibile, ma non attiva in modalità finestra divisa, è necessario inizializzare il lettore in onStart
. Android API livello 24 e inferiore richiede di aspettare il più a lungo possibile fino a quando si afferrano le risorse, quindi aspettate fino a onResume
prima di inizializzare il lettore.
- Aggiungi il metodo
hideSystemUi
.
PlayerActivity.java
@SuppressLint("InlinedApi")private void hideSystemUi() { playerView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);}
hideSystemUi
è un metodo helper chiamato in onResume
, che vi permette di avere un’esperienza a schermo intero.
- Rilascia le risorse con
releasePlayer
(che crei a breve) inonPause
eonStop
.
PlayerActivity.java
@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}
Con API Level 24 e inferiori, non è garantito che onStop
venga chiamato, quindi devi rilasciare il giocatore il prima possibile in onPause
. Con il livello API 24 e superiore (che ha portato la modalità multi- e split-window), onStop
è garantito che venga chiamato. Nello stato di pausa, la vostra attività è ancora visibile, quindi aspettate a rilasciare il giocatore fino a onStop
.
Ora dovete creare un metodo releasePlayer
che liberi le risorse del giocatore e lo distrugga.
- Aggiungi il seguente codice all’attività:
PlayerActivity.java
private boolean playWhenReady = true;private int currentWindow = 0;private long playbackPosition = 0;private void releasePlayer() { if (player != null) { playWhenReady = player.getPlayWhenReady(); playbackPosition = player.getCurrentPosition(); currentWindow = player.getCurrentWindowIndex(); player.release(); player = null; }}
Prima di rilasciare e distruggere il lettore, memorizza le seguenti informazioni:
- Stato di riproduzione/pausa usando
getPlayWhenReady
. - Posizione di riproduzione corrente usando
getCurrentPosition
. - Indice della finestra corrente usando
getCurrentWindowIndex
. Per maggiori informazioni sulle finestre, vedi Timeline.
Questo ti permette di riprendere la riproduzione da dove l’utente ha lasciato. Tutto quello che devi fare è fornire queste informazioni di stato quando inizializzi il tuo lettore.
Preparazione finale
Tutto quello che devi fare ora è fornire le informazioni di stato che hai salvato in releasePlayer
al tuo lettore durante l’inizializzazione.
- Aggiungi il seguente a
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}
Ecco cosa succede:
-
setPlayWhenReady
dice al lettore se iniziare a giocare non appena tutte le risorse per la riproduzione sono state acquisite. PoichéplayWhenReady
è inizialmentetrue
, la riproduzione inizia automaticamente la prima volta che l’applicazione viene eseguita. -
seekTo
dice al lettore di cercare una certa posizione all’interno di una specifica finestra. SiacurrentWindow
cheplaybackPosition
sono inizializzati a zero in modo che la riproduzione parta dall’inizio la prima volta che l’applicazione viene eseguita. -
prepare
dice al lettore di acquisire tutte le risorse necessarie per la riproduzione.
Play audio
Finalmente, hai finito! Avvia l’applicazione per riprodurre il file MP3 e vedere l’artwork incorporato.
Screenshot: L’app che riproduce un singolo brano.
Testare il ciclo di vita dell’attività
Testare se l’app funziona in tutti i diversi stati del ciclo di vita dell’attività.
- Avvia un’altra app e metti di nuovo la tua app in primo piano. Riprende nella posizione corretta?
- Metti in pausa l’app e spostala sullo sfondo e poi di nuovo in primo piano. Rimane in uno stato di pausa quando è in background in stato di pausa?
- Ruota l’app. Come si comporta se cambi l’orientamento da verticale a orizzontale e viceversa?
Play video
Se vuoi riprodurre video, è facile come modificare l’URI dell’elemento multimediale in un file MP4.
- Cambia l’URI nel
initializePlayer
inR.string.media_url_mp4
. - Riavvia l’applicazione e prova il comportamento dopo essere stato messo in background anche con la riproduzione video.
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }
La PlayerView
fa tutto. Invece dell’opera d’arte, il video viene reso a schermo intero.
Screenshot: L’app che riproduce il video.
Sei forte! Hai appena creato un’app per lo streaming multimediale a tutto schermo su Android, completa di gestione del ciclo di vita, stato salvato e controlli UI!
La tua app attuale riproduce un singolo file multimediale, ma se vuoi riprodurre più di un file multimediale, uno dopo l’altro? Per questo, hai bisogno di una playlist.
Le playlist possono essere create aggiungendo più MediaItem
al tuo player
usando addMediaItem
. Questo permette una riproduzione senza soluzione di continuità e il buffering è gestito in background così l’utente non vede uno spinner di buffering quando cambia elementi multimediali.
- Aggiungi il seguente codice a
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }
Verifica come si comportano i controlli del player. Puoi usare e per navigare nella sequenza di elementi multimediali.
Screenshot: Controlli di riproduzione che mostrano un pulsante successivo e precedente
Questo è piuttosto comodo! Per maggiori informazioni, vedi la documentazione per gli sviluppatori su Media Items e Playlists, e questo articolo sull’API Playlist.
Lo streaming adattivo è una tecnica per lo streaming dei media che varia la qualità del flusso in base alla larghezza di banda della rete disponibile. Questo permette all’utente di sperimentare la migliore qualità dei media che la loro larghezza di banda permette.
Tipicamente, lo stesso contenuto multimediale è diviso in più tracce con qualità diverse (bit rate e risoluzioni). Il lettore sceglie una traccia in base alla larghezza di banda di rete disponibile.
Ogni traccia è divisa in pezzi di una certa durata, in genere tra 2 e 10 secondi. Questo permette al giocatore di passare rapidamente da una traccia all’altra quando cambia la larghezza di banda disponibile. Il lettore è responsabile della cucitura di questi pezzi insieme per una riproduzione senza soluzione di continuità.
Selezione adattiva delle tracce
Il cuore dello streaming adattivo è la selezione della traccia più appropriata per l’ambiente corrente. Aggiorna la tua app per riprodurre i media in streaming adattivo usando la selezione adattiva delle tracce.
- Aggiorna
initializePlayer
con il seguente codice:
PlayerActivity.java
private void initializePlayer() { if (player == null) { DefaultTrackSelector trackSelector = new DefaultTrackSelector(this); trackSelector.setParameters( trackSelector.buildUponParameters().setMaxVideoSizeSd()); player = new SimpleExoPlayer.Builder(this) .setTrackSelector(trackSelector) .build(); } // Remove or comment out. // player = new SimpleExoPlayer.Builder(this).build(); }
Prima, crea un DefaultTrackSelector
, che è responsabile della scelta delle tracce nell’elemento multimediale. Poi, dite al vostro trackSelector
di scegliere solo tracce di definizione standard o inferiore – un buon modo di risparmiare i dati del vostro utente a spese della qualità. Infine, passa il tuo trackSelector
al tuo costruttore in modo che sia usato quando costruisci l’istanza SimpleExoPlayer
.
Costruisci un MediaItem adattivo
DASH è un formato di streaming adattivo ampiamente usato. Per trasmettere contenuti DASH, è necessario creare un MediaItem
come prima. Tuttavia, questa volta, dobbiamo usare un MediaItem.Builder
piuttosto che fromUri
.
Questo perché fromUri
usa l’estensione del file per determinare il formato multimediale sottostante ma il nostro URI DASH non ha un’estensione di file quindi dobbiamo fornire un tipo MIME di APPLICATION_MPD
quando costruiamo il MediaItem
.
- Aggiornate
initializePlayer
come segue:
PlayerActivity.java
private void initializePlayer() { // Replace this line MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp4)); // With this MediaItem mediaItem = new MediaItem.Builder() .setUri(getString(R.string.media_url_dash)) .setMimeType(MimeTypes.APPLICATION_MPD) .build(); // Also remove the following lines MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem);}
- Riavvia l’applicazione e vedi lo streaming video adattivo con DASH in azione. È abbastanza facile con ExoPlayer!
Altri formati di streaming adattivo
HLS (MimeTypes.APPLICATION_M3U8
) e SmoothStreaming (MimeTypes.APPLICATION_SS
) sono altri formati di streaming adattivo comunemente usati, entrambi supportati da ExoPlayer. Per maggiori informazioni sulla costruzione di altre sorgenti multimediali adattive, vedi l’applicazione demo di ExoPlayer.
Nei passi precedenti, hai imparato come trasmettere flussi multimediali progressivi e adattivi. ExoPlayer sta facendo molto lavoro per te dietro le quinte, incluso quanto segue:
- Allocare la memoria
- Scaricare i file del contenitore
- Estrarre i metadati dal contenitore
- Decodificare i dati
- Rendering di video, audio e testo sullo schermo e sugli altoparlanti
A volte, è utile sapere cosa sta facendo ExoPlayer in fase di esecuzione per capire e migliorare l’esperienza di riproduzione dei tuoi utenti.
Per esempio, potresti voler riflettere i cambiamenti di stato della riproduzione nell’interfaccia utente facendo quanto segue:
- Visualizzando un indicatore di caricamento quando il lettore entra in uno stato di buffering
- Mostrando una sovrapposizione con le opzioni “guarda il prossimo” quando la traccia è finita
ExoPlayer offre diverse interfacce ascoltatrici che forniscono callback per eventi utili. Usate un ascoltatore per registrare in quale stato si trova il giocatore.
Ascolta
- Dichiarate un membro privato di tipo
PlaybackStateListener
nellaPlayerActivity
. - Create una costante
TAG
, che userete in seguito per il logging.
PlayerActivity.java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
- Instanziare il
playbackStateListener
all’inizio dionCreate
(non compilerà ancora, ma lo sistemerai a breve).
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
- Usa Quick Fix per creare automaticamente la classe interna
PlaybackStateListener
.
Screenshot: Menu Quick Fix per creare una classe mancante
- Implementa l’interfaccia
Player.EventListener
. Questa è usata per informare su importanti eventi del giocatore, inclusi gli errori e i cambiamenti di stato della riproduzione. - Overdi
onPlaybackStateChanged
aggiungendo il seguente codice:
PlayerActivity.java
private class PlaybackStateListener implements Player.EventListener { @Override public void onPlaybackStateChanged(int playbackState) { String stateString; switch (playbackState) { case ExoPlayer.STATE_IDLE: stateString = "ExoPlayer.STATE_IDLE -"; break; case ExoPlayer.STATE_BUFFERING: stateString = "ExoPlayer.STATE_BUFFERING -"; break; case ExoPlayer.STATE_READY: stateString = "ExoPlayer.STATE_READY -"; break; case ExoPlayer.STATE_ENDED: stateString = "ExoPlayer.STATE_ENDED -"; break; default: stateString = "UNKNOWN_STATE -"; break; } Log.d(TAG, "changed state to " + stateString); }}
onPlaybackStateChanged
viene chiamato quando lo stato della riproduzione cambia. Il nuovo stato è dato dal parametro playbackState
.
Il lettore può essere in uno dei seguenti quattro stati:
State |
Descrizione |
|
Il lettore è stato istanziato, ma non è stato ancora preparato. |
|
Il lettore non è in grado di giocare dalla posizione corrente perché non sono stati bufferizzati abbastanza dati. |
|
Il lettore è in grado di giocare immediatamente dalla posizione corrente. Questo significa che il lettore inizierà a riprodurre i media automaticamente se la proprietà playWhenReady del lettore è |
|
Il player ha finito di riprodurre il media. |
Registra il tuo listener
Per far chiamare i tuoi callback, devi registrare il tuo playbackStateListener
con il player. Fatelo in initializePlayer
.
- Registra l’ascoltatore prima che il gioco sia preparato.
PlayerActivity.java
private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}
Ancora una volta, dovete riordinare per evitare riferimenti penzolanti dal giocatore che potrebbero causare un memory leak.
- Rimuovi l’ascoltatore in
releasePlayer
:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- Apri logcat ed esegui l’applicazione.
- Usa i controlli UI per cercare, mettere in pausa e riprendere la riproduzione. Dovresti vedere lo stato di riproduzione cambiare nei log.
Vai più a fondo
ExoPlayer offre una serie di altri ascoltatori, che sono utili per capire l’esperienza di riproduzione dell’utente. Ci sono ascoltatori per audio e video, così come un AnalyticsListener
, che contiene le callback di tutti gli ascoltatori. Alcuni dei metodi più importanti sono i seguenti:
-
onRenderedFirstFrame
viene chiamato quando il primo fotogramma di un video viene reso. Con questo, si può calcolare quanto tempo l’utente ha dovuto aspettare per vedere un contenuto significativo sullo schermo. -
onDroppedVideoFrames
viene chiamato quando i fotogrammi del video sono stati abbandonati. I fotogrammi caduti indicano che la riproduzione è disturbata e l’esperienza dell’utente sarà probabilmente scarsa. -
onAudioUnderrun
viene chiamato quando c’è stato un underrun audio. Gli underrun causano glitch udibili nel suono e sono più evidenti dei fotogrammi video caduti.
AnalyticsListener
può essere aggiunto al player
con addAnalyticsListener
. Ci sono metodi corrispondenti anche per gli ascoltatori audio e video.
Pensa a quali eventi sono importanti per la tua app e per i tuoi utenti. Per maggiori informazioni, vedi Ascoltare gli eventi del lettore. Questo è tutto per gli ascoltatori di eventi!
Finora hai usato il PlayerControlView
di ExoPlayer per mostrare un controller di riproduzione all’utente.
Screenshot: Controller di riproduzione predefinito
E se vuoi cambiare la funzionalità o l’aspetto di questi controlli? Fortunatamente, questi controlli sono altamente personalizzabili.
La prima semplice personalizzazione è quella di non usare affatto il controller. Questo può essere fatto facilmente usando l’attributo use_controller
sull’elemento PlayerView
dentro activity_player.xml
.
- Imposta
use_controller
afalse
e il controllo non appare più:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
- Aggiungi il seguente spazio dei nomi al tuo
FrameLayout
:
activity_player.xml
<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">
Prova ora.
Personalizza il comportamento
PlayerControlView
ha diversi attributi che influenzano il suo comportamento. Usa show_timeout
, fastforward_increment
e rewind_increment
per personalizzare il comportamento del controller.
- Rimuovi
app:use_controller="false"
. - Cambia la vista del giocatore per usare
show_timeout
,fastforward_increment
erewind_increment
:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:show_timeout="10000" app:fastforward_increment="30000" app:rewind_increment="30000"/>
- Il valore
show_timeout
dice alPlayerView
il ritardo in millisecondi prima che il controllo sia nascosto dopo l’ultima interazione dell’utente. - I valori
fastforward_increment
erewind_increment
dicono al lettore il tempo in millisecondi per saltare avanti o indietro quando l’utente tocca i pulsanti fast-forward o rewind.
Gli attributi del PlayerControlView
possono anche essere impostati programmaticamente.
Personalizza l’aspetto
Bene, questo è un buon inizio. Ma cosa succede se vuoi che il PlayerControlView
look sia diverso o cambiare quali pulsanti sono visualizzati? L’implementazione di PlayerControlView
non presuppone che ci siano pulsanti, quindi è facile rimuoverli e aggiungerne di nuovi.
Guarda come puoi personalizzare il PlayerControlView
.
- Crea un nuovo file di layout
custom_player_control_view.xml
nella cartellaplayer-lib/res/layout/
. - Dal menu contestuale della cartella del layout, scegli Nuovo – File risorse di layout e nominalo
custom_player_control_view.xml
.
Screenshot: Il file di layout per la vista di controllo del giocatore è stato creato.
- Copia il file di layout originale da qui a
custom_player_control_view.xml
. - Rimuovi gli elementi
ImageButton
con gli id@id/exo_prev
e@id/exo_next
.
Per usare il tuo layout personalizzato, devi impostare l’attributo app:controller_layout_id
dell’elemento PlayerView
nel file activity_player.xml
.
- Usa l’ID del layout del tuo file personalizzato come nel seguente frammento di codice:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" app:controller_layout_id="@layout/custom_player_control_view"/>
- Riavvia l’applicazione. La vista di controllo del giocatore non ha più i pulsanti precedente e successivo.
Screenshot: Vista di controllo del giocatore personalizzata senza pulsanti precedente e successivo
Puoi applicare qualsiasi modifica tu voglia nel file di layout. Per impostazione predefinita, vengono scelti i colori del tema di Android. Puoi sovrascriverli per adattarli al design della tua applicazione.
- Aggiungi un attributo
android:tint
ad ogni elementoImageButton
:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- Cambia tutti gli attributi
android:textColor
che trovi nel tuo file personalizzato con lo stesso colore:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position" android:textColor="#FF00A6FF"/><TextView android:id="@id/exo_duration" android:textColor="#FF00A6FF"/>
- Lancia l’applicazione. Ora hai dei bellissimi componenti UI colorati!
Screenshot: Pulsanti colorati e visualizzazione del testo
Sovrascrivi lo stile predefinito
Hai appena creato un file di layout personalizzato e lo hai referenziato usando controller_layout_id
in activity_player.xml
.
Un altro approccio è quello di sovrascrivere il file di layout predefinito che PlayerControlView
usa. Il codice sorgente di PlayerControlView
ci dice che usa R.layout.exo_player_control_view
per il layout. Se creiamo il nostro file di layout con lo stesso nome, il PlayerControlView
usa il tuo file al suo posto.
- Rimuovi l’attributo
controller_layout_id
che hai appena aggiunto. - Elimina il file
custom_player_control_view.xml
.
Il PlayerView
in activity_player.xml
dovrebbe ora essere così:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- Crea un file chiamato
exo_player_control_view.xml
nella cartellares/layout
del tuo modulo di libreriaplayer-lib
. - Inserisci il seguente codice in
exo_player_control_view.xml
per aggiungere un pulsante play, un pulsante pausa e unImageView
con un logo:
exo_player**_control_view.xml**
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layoutDirection="ltr" android:background="#CC000000" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingTop="4dp" android:orientation="horizontal"> <ImageButton android:id="@id/exo_play" style="@style/ExoMediaButton.Play"/> <ImageButton android:id="@id/exo_pause" style="@style/ExoMediaButton.Pause"/> </LinearLayout> <ImageView android:contentDescription="@string/logo" android:src="@drawable/google_logo" android:layout_width="match_parent" android:layout_height="wrap_content"/></LinearLayout>
Questo dimostra come puoi aggiungere i tuoi elementi qui e mescolarli con elementi di controllo standard. ExoPlayerView
ora usa il tuo controllo personalizzato e tutta la logica per nascondere e mostrare quando si interagisce con il controllo è conservata.
Congratulazioni! Hai imparato molto sull’integrazione di ExoPlayer con la tua app.