Skärmdump: YouTube Android-appen
ExoPlayer är en mediespelare på appnivå som är byggd ovanpå media-API:er på låg nivå i Android. ExoPlayer har ett antal fördelar jämfört med den inbyggda MediaPlayer i Android. Den stöder många av samma medieformat som MediaPlayer, plus adaptiva format som DASH och SmoothStreaming. ExoPlayer är mycket anpassningsbar och utbyggbar, vilket gör att den kan användas för många avancerade användningsområden. Det är ett projekt med öppen källkod som används av Google-appar, inklusive YouTube och Google Play Movies & TV.
- Förutsättningar
- Vad du ska göra
- Vad du behöver
- Hämta koden
- Adressstruktur
- Importera det ursprungliga projektet
- app/build.gradle
- Add ExoPlayer dependency
- player-lib/build.gradle
- Lägg till PlayerView-elementet
- activity_player.xml
- PlayerActivity.java
- Skapa en ExoPlayer
- PlayerActivity.java
- Skapa ett medieobjekt
- PlayerActivity.java
- Spela snällt med aktivitetslivscykeln
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Slutförberedelser
- PlayerActivity.java
- Spela upp ljud
- Testa aktivitetslivscykeln
- Spela upp video
- PlayerActivity.java
- PlayerActivity.java
- Adaptivt spårval
- PlayerActivity.java
- Bygg ett adaptivt MediaItem
- PlayerActivity.java
- Andra adaptiva streamingformat
- Lyssna upp
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Registera din lyssnare
- PlayerActivity.java
- PlayerActivity.java
- Gå djupare
- activity_player.xml
- activity_player.xml
- Anpassa beteendet
- activity_player.xml
- Anpassa utseendet
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- activity_player.xml
- exo_player**_control_view.xml**
- Lär dig mer
Förutsättningar
- Moderata kunskaper om Android-utveckling och Android Studio
Vad du ska göra
- Skapa en
SimpleExoPlayer
-instans som förbereder och spelar upp media från en mängd olika källor. - Integrera ExoPlayer med appens aktivitetslivscykel för att stödja bakgrunds-, förgrunds- och återupptagningsuppspelning i en miljö med ett eller flera fönster.
- Använd
MediaItem
s för att skapa en spellista. - Spela upp adaptiva videoströmmar, som anpassar mediekvaliteten till den tillgängliga bandbredden.
- Registrera händelselysslare för att övervaka uppspelningstillståndet och visa hur lyssnare kan användas för att mäta kvaliteten på uppspelningen.
- Använd standard ExoPlayer UI-komponenter och anpassa dem sedan till appens stil.
Vad du behöver
- Android Studio version 3.5 eller högre
- En Android-enhet med JellyBean (4.1) eller högre, helst med Nougat (7.1) eller högre eftersom den stöder flera fönster.
Hämta koden
För att komma igång laddar du ner Android Studio-projektet:
Ladda ner zip
Alternativt kan du klona GitHub-förrådet:
git clone https://github.com/googlecodelabs/exoplayer-intro.git
Adressstruktur
Kloning eller zippning ger dig en rotmapp (exoplayer-intro
), som innehåller en mapp för varje steg i det här codelabbet, tillsammans med alla resurser du behöver:
/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
Mapperna exoplayer-codelab-N
(där N
är 00
till 04
) innehåller det önskade slutläget för varje steg i det här codelabbet. Dessa är fristående Android Studio-projekt som var och en kan importeras.
Importera det ursprungliga projektet
- Starta Android Studio.
- Välj fil > Ny > Importera projekt*.*
- Importera det ursprungliga projektet från
exoplayer-codelab-00
.
Screenshot: Projektstruktur vid import
När byggningen är klar ser du två moduler: app
-modulen (av typen program) och player-lib
-modulen (av typen bibliotek). Modulen app
är egentligen tom och har bara ett manifest. Allt från player-lib
-modulen slås samman när appen byggs med hjälp av ett gradle-beroende i app/build.gradle
.
app/build.gradle
dependencies { implementation project(":player-lib")}
Din mediaspelaraktivitet finns kvar i player-lib
-modulen. Anledningen till att den förvaras i en separat biblioteksmodul är att du kan dela den mellan APK:er som riktar sig till olika plattformar, t.ex. mobil och Android TV. Det gör också att du kan dra nytta av funktioner, till exempel Dynamic Delivery, som gör att din funktion för uppspelning av media endast installeras när användaren behöver den.
- Leverera och kör appen för att kontrollera att allt är som det ska. Appen ska fylla skärmen med en svart bakgrund.
Screenshot: Blank app running
Add ExoPlayer dependency
ExoPlayer är ett öppen källkodsprojekt som finns på GitHub. Varje utgåva distribueras via jCenter, som är ett av de standardpaketförråd som används av Android Studio och Gradle. Varje utgåva identifieras unikt av en sträng med följande format:
com.google.android.exoplayer:exoplayer:rX.X.X
Du kan lägga till ExoPlayer i ditt projekt helt enkelt genom att importera dess klasser och UI-komponenter. Den är ganska liten och har ett krympt fotavtryck på cirka 70-300 kB beroende på de inkluderade funktionerna och de format som stöds. ExoPlayer-biblioteket är uppdelat i moduler så att utvecklare endast kan importera den funktionalitet de behöver. Mer information om ExoPlayers modulära struktur finns i Lägg till ExoPlayer-moduler.
- Öppna
build.gradle
-filen förplayer-lib
-modulen. - Lägg till följande rader i
dependencies
-sektionen och synkronisera projektet.
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'}
Lägg till PlayerView-elementet
- Öppna layoutresursfilen
activity_player.xml
frånplayer-lib
-modulen. - Placera markören inne i
FrameLayout
-elementet. - Börja skriva
<PlayerView
och låt Android Studio automatiskt kompletteraPlayerView
-elementet. - Använd
match_parent
förwidth
ochheight
. - Deklarera id som
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"/>
I fortsättningen hänvisar du till det här gränssnittselementet som videovisning.
- I
PlayerActivity
måste du nu hitta videovyn så att du kan ställa in den korrekt ionCreate
-metoden i aktiviteten.
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- Lägg till medlemsfältet
playerView
till dinPlayerActivity
-klass. Se till att vyns typ ärPlayerView
.
Anmärkning: Använd funktionen Snabbrättning i Android Studio för att lägga till ett medlemsfält automatiskt. Kom ihåg att ställa in typen till
PlayerView
i stället för standardvärdet
View
Screenshot: Snabbhjälpsmeny för att skapa ett medlemsfält
Skapa en ExoPlayer
För att spela upp strömmande media behöver du ett ExoPlayer
-objekt. Det enklaste sättet att skapa ett är att använda SimpleExoPlayer.Builder
-klassen. Som namnet antyder använder den byggmönstret för att skapa en SimpleExoPlayer
-instans.
SimpleExoPlayer
är en praktisk implementering för alla ändamål av ExoPlayer
-gränssnittet.
Lägg till en privat metod initializePlayer
för att skapa din SimpleExoPlayer
.
PlayerActivity.java
private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}
Skapa en SimpleExoPlayer.Builder
med hjälp av din kontext och anropa sedan build
för att skapa ditt SimpleExoPlayer
-objekt. Detta tilldelas sedan player
, som du måste deklarera som ett medlemsfält. Du använder sedan playerView.setPlayer
för att binda player
till motsvarande vy.
Skapa ett medieobjekt
Din player
behöver nu något innehåll att spela upp. För detta skapar du en MediaItem
. Det finns många olika typer av MediaItem
, men du börjar med att skapa en för en MP3-fil på Internet.
Det enklaste sättet att skapa en MediaItem
är att använda MediaItem.fromUri
, som accepterar URI för en mediefil. Lägg till MediaItem
i player
med hjälp av player.setMediaItem
.
- Lägg till följande kod i
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}
Notera att R.string.media_url_mp3
är definierat som https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 i strings.xml
.
Spela snällt med aktivitetslivscykeln
Vår player
kan ta mycket resurser i anspråk, inklusive minne, CPU, nätverksanslutningar och hårdvarucodecs. Många av dessa resurser är bristfälliga, särskilt när det gäller hårdvarucodecs där det kanske bara finns en. Det är viktigt att du frigör dessa resurser så att andra appar kan använda dem när du inte använder dem, t.ex. när din app hamnar i bakgrunden.
Med andra ord bör din spelares livscykel vara knuten till din apps livscykel. För att genomföra detta måste du åsidosätta de fyra metoderna i PlayerActivity
: onStart
, onResume
, onPause
och onStop
.
- Med
PlayerActivity
öppen klickar du på Kodmeny > Överstyr metoder…. - Välj
onStart
,onResume
,onPause
ochonStop
. - Initialisera spelaren i
onStart
elleronResume
callback beroende på API-nivå.
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(); }}
Android API-nivå 24 och högre stöder flera fönster. Eftersom din app kan vara synlig, men inte aktiv i delat fönsterläge, måste du initialisera spelaren i onStart
. Android API-nivå 24 och lägre kräver att du väntar så länge som möjligt tills du tar resurser, så du väntar till onResume
innan du initialiserar spelaren.
- Lägg till
hideSystemUi
-metoden.
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
är en hjälpmetod som anropas i onResume
, vilket gör det möjligt för dig att få en helskärmsupplevelse.
- Släpp resurser med
releasePlayer
(som du skapar inom kort) ionPause
ochonStop
.
PlayerActivity.java
@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}
Med API-nivå 24 och lägre finns det ingen garanti för att onStop
anropas, så du måste släppa spelaren så tidigt som möjligt i onPause
. Med API-nivå 24 och högre (vilket medförde multi- och split-window-läge) är det garanterat att onStop
anropas. I det pausade tillståndet är din aktivitet fortfarande synlig, så du väntar med att släppa spelaren tills onStop
.
Du måste nu skapa en releasePlayer
-metod som frigör spelarens resurser och förstör den.
- Lägg till följande kod till aktiviteten:
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; }}
För att frigöra och förstöra spelaren ska du lagra följande information:
- Play/pause-status med hjälp av
getPlayWhenReady
. - Aktuell uppspelningsposition med hjälp av
getCurrentPosition
. - Aktuellt fönsterindex med hjälp av
getCurrentWindowIndex
. Mer information om fönster finns i Tidslinje.
Detta gör det möjligt att återuppta uppspelningen där användaren slutade. Allt du behöver göra är att tillhandahålla den här tillståndsinformationen när du initialiserar spelaren.
Slutförberedelser
Allt du behöver göra nu är att tillhandahålla den tillståndsinformation som du sparade i releasePlayer
till din spelare under initialiseringen.
- Lägg till följande i
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}
Här är vad som händer:
-
setPlayWhenReady
talar om för spelaren om den ska börja spela upp så snart alla resurser för uppspelning har förvärvats. EftersomplayWhenReady
initialt ärtrue
startar uppspelningen automatiskt första gången appen körs. -
seekTo
talar om för spelaren att söka sig till en viss position i ett visst fönster. BådecurrentWindow
ochplaybackPosition
initialiseras till noll så att uppspelningen startar från början första gången appen körs. -
prepare
talar om för spelaren att skaffa alla resurser som krävs för uppspelningen.
Spela upp ljud
Äntligen är du klar! Starta appen för att spela upp MP3-filen och se det inbäddade konstverket.
Screenshot:
Testa aktivitetslivscykeln
Testa om appen fungerar i alla olika tillstånd i aktivitetslivscykeln.
- Starta en annan app och sätt din app i förgrunden igen. Återgår den till rätt position?
- Pausera appen och flytta den till bakgrunden och sedan till förgrunden igen. Håller den fast vid det pausade läget när den är i bakgrunden i det pausade läget?
- Rota appen. Hur beter den sig om du ändrar orienteringen från porträtt till landskap och tillbaka?
Spela upp video
Om du vill spela upp video är det lika enkelt som att ändra medieobjektets URI till en MP4-fil.
- Ändra URI i
initializePlayer
tillR.string.media_url_mp4
. - Starta appen igen och testa beteendet efter att ha varit i bakgrunden med videouppspelning också.
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }
Den PlayerView
gör allt. Istället för konstverket återges videon i helskärm.
Screenshot:
Du rockar! Du har precis skapat en app för medieströmning i fullskärmsläge på Android, komplett med livscykelhantering, sparat tillstånd och gränssnittskontroller!
Din nuvarande app spelar upp en enda mediefil, men vad händer om du vill spela upp mer än en mediefil, en efter en? För det behöver du en spellista.
Playlistor kan skapas genom att lägga till fler MediaItem
s till din player
med hjälp av addMediaItem
. Detta möjliggör sömlös uppspelning och buffringen hanteras i bakgrunden så att användaren inte ser en buffertspinnare vid byte av medieobjekt.
- Lägg till följande kod till
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }
Kontrollera hur spelarkontrollerna beter sig. Du kan använda och för att navigera i sekvensen av medieobjekt.
Screenshot: Uppspelningskontroller som visar en nästa och föregående knapp
Det är ganska praktiskt! Mer information finns i utvecklardokumentationen om medieobjekt och spellistor och i den här artikeln om API:et för spellistor.
Adaptiv strömning är en teknik för att strömma media genom att variera kvaliteten på strömmen baserat på den tillgängliga nätverksbandbredden. Detta gör det möjligt för användaren att uppleva den bästa mediekvalitet som bandbredden tillåter.
Typiskt sett delas samma medieinnehåll upp i flera spår med olika kvaliteter (bithastigheter och upplösningar). Spelaren väljer ett spår baserat på den tillgängliga nätverksbandbredden.
Varje spår är uppdelat i bitar av en viss längd, vanligtvis mellan 2 och 10 sekunder. Detta gör det möjligt för spelaren att snabbt växla mellan spåren när den tillgängliga bandbredden ändras. Spelaren ansvarar för att sammanfoga dessa delar för sömlös uppspelning.
Adaptivt spårval
Kärnan i adaptiv streaming är att välja det mest lämpliga spåret för den aktuella miljön. Uppdatera din app för att spela upp adaptiv strömmande media med hjälp av adaptivt spårval.
- Uppdatera
initializePlayer
med följande kod:
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(); }
Skapa först en DefaultTrackSelector
, som är ansvarig för att välja spår i mediaobjektet. Säg sedan till din trackSelector
att endast välja spår med standarddefinition eller lägre – ett bra sätt att spara användardata på bekostnad av kvaliteten. Slutligen skickar du din trackSelector
till din byggare så att den används när du bygger SimpleExoPlayer
-instansen.
Bygg ett adaptivt MediaItem
DASH är ett allmänt använt adaptivt streamingformat. För att strömma DASH-innehåll måste du skapa en MediaItem
som tidigare. Den här gången måste vi dock använda en MediaItem.Builder
i stället för fromUri
.
Detta beror på att fromUri
använder filtillägget för att bestämma det underliggande medieformatet, men vår DASH URI har inget filtillägg så vi måste ange en MIME-typ APPLICATION_MPD
när vi konstruerar MediaItem
.
- Uppdatera
initializePlayer
på följande sätt:
PlayerActivity.java
- Starta om appen och se adaptiv videoströmning med DASH i aktion. Det är ganska enkelt med ExoPlayer!
Andra adaptiva streamingformat
HLS (MimeTypes.APPLICATION_M3U8
) och SmoothStreaming (MimeTypes.APPLICATION_SS
) är andra vanliga adaptiva streamingformat som båda stöds av ExoPlayer. Mer information om hur du konstruerar andra adaptiva mediekällor finns i ExoPlayers demoapp.
I de föregående stegen lärde du dig att strömma progressiva och adaptiva medieströmmar. ExoPlayer gör mycket arbete åt dig bakom kulisserna, bland annat följande:
- Allokering av minne
- Hämtning av behållarfiler
- Extrahering av metadata från behållaren
- Avkodning av data
- Rendering av video, ljud och text till skärmen och högtalarna
I vissa fall är det användbart att veta vad ExoPlayer gör vid körning för att förstå och förbättra uppspelningsupplevelsen för dina användare.
Du kanske till exempel vill återspegla ändringar i uppspelningstillståndet i användargränssnittet genom att göra följande:
- Visa en laddningsspinnare när spelaren går in i ett bufferttillstånd
- Visa en överlagring med ”titta på nästa”-alternativ när spåret är avslutat
ExoPlayer erbjuder flera lyssnargränssnitt som ger callbacks för användbara händelser. Du använder en lyssnare för att logga vilket tillstånd spelaren befinner sig i.
Lyssna upp
- Deklarera en privat medlem av typen
PlaybackStateListener
iPlayerActivity
. - Skapa en
TAG
konstant, som du använder för loggning senare.
PlayerActivity.java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
- Instantera
playbackStateListener
i början avonCreate
(det kommer inte att kompileras ännu, men du fixar detta inom kort).
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
- Använd Quick Fix för att skapa den inre klassen
PlaybackStateListener
automatiskt.
Screenshot: Quick Fix-menyn för att skapa en saknad klass
- Implementera gränssnittet
Player.EventListener
. Detta används för att informera dig om viktiga spelarhändelser, inklusive fel och ändringar av uppspelningstillstånd. - Override
onPlaybackStateChanged
genom att lägga till följande kod:
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
anropas när uppspelningstillståndet ändras. Det nya tillståndet ges av parametern playbackState
.
Spelaren kan befinna sig i något av följande fyra tillstånd:
State |
Description |
|
Spelaren har instansierats, men har inte förberetts ännu. |
|
Spelaren kan inte spela från den aktuella positionen eftersom inte tillräckligt med data har buffrats. |
|
Spelaren kan omedelbart spela från den aktuella positionen. Detta innebär att spelaren börjar spela upp media automatiskt om spelarens egenskap playWhenReady är |
|
Spelaren har spelat upp mediet färdigt. |
Registera din lyssnare
För att dina callbacks ska kunna anropas måste du registrera din playbackStateListener
hos spelaren. Gör det i initializePlayer
.
- Registera lyssnaren innan uppspelningen förbereds.
PlayerActivity.java
private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}
Även här måste du städa upp för att undvika hängande referenser från spelaren, vilket skulle kunna orsaka en minnesläcka.
- För bort lyssnaren i
releasePlayer
:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- Öppna logcat och kör appen.
- Använd gränssnittskontrollerna för att söka, pausa och återuppta uppspelningen. Du bör se hur uppspelningstillståndet ändras i loggarna.
Gå djupare
ExoPlayer erbjuder ett antal andra lyssnare, som är användbara för att förstå användarens uppspelningsupplevelse. Det finns lyssnare för ljud och video samt en AnalyticsListener
, som innehåller callbacks från alla lyssnare. Några av de viktigaste metoderna är följande:
-
onRenderedFirstFrame
anropas när den första bilden av en video återges. Med detta kan du beräkna hur länge användaren var tvungen att vänta för att se meningsfullt innehåll på skärmen. -
onDroppedVideoFrames
anropas när videoramar har tappats. Nedfallna ramar indikerar att uppspelningen är janky och att användarupplevelsen sannolikt är dålig. -
onAudioUnderrun
anropas när det har förekommit en audiounderkörning. Underkörningar orsakar hörbara glapp i ljudet och är mer märkbara än tappade videoramar.
AnalyticsListener
kan läggas till player
med addAnalyticsListener
. Det finns motsvarande metoder även för ljud- och videoblyssnarna.
Tänk efter vilka händelser som är viktiga för din app och dina användare. Mer information finns i Lyssna på spelarhändelser. Det var allt för händelselysslare!
So långt har du använt ExoPlayers PlayerControlView
för att visa en uppspelningskontroll för användaren.
Screenshot:
Vad händer om du vill ändra funktionaliteten eller utseendet på dessa kontroller? Lyckligtvis är dessa kontroller mycket anpassningsbara.
Den första enkla anpassningen är att inte använda kontrollern alls. Detta kan enkelt göras genom att använda attributet use_controller
på elementet PlayerView
inuti activity_player.xml
.
- Sätt
use_controller
tillfalse
och kontrollen visas inte längre:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
- Lägg till följande namnområde till din
FrameLayout
:
activity_player.xml
<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">
Prova nu.
Anpassa beteendet
PlayerControlView
har flera attribut som påverkar dess beteende. Använd show_timeout
, fastforward_increment
och rewind_increment
för att anpassa kontrollörens beteende.
- Ta bort
app:use_controller="false"
. - Ändra spelarvyn så att den använder
show_timeout
,fastforward_increment
ochrewind_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"/>
- Värdet
show_timeout
talar om förPlayerView
fördröjningen i millisekunder innan kontrollen döljs efter att användaren senast interagerade med den. - Värdena
fastforward_increment
ochrewind_increment
talar om för spelaren hur lång tid i millisekunder det tar att hoppa framåt eller bakåt när användaren trycker på knapparna för snabbspolning eller återspolning.
Attributen för PlayerControlView
kan också ställas in programmatiskt.
Anpassa utseendet
Ja, det är en bra början. Men vad händer om du vill att PlayerControlView
ska se annorlunda ut eller ändra vilka knappar som visas? Implementationen av PlayerControlView
förutsätter inte att det finns några knappar, så det är lätt att ta bort dem och lägga till nya.
Se hur du kan anpassa PlayerControlView
.
- Skapa en ny layoutfil
custom_player_control_view.xml
i mappenplayer-lib/res/layout/
. - I layoutmappens kontextmeny väljer du Ny – Layoutresursfil och namnger den
custom_player_control_view.xml
.
Screenshot: Layoutfilen för spelarkontrollvyn har skapats.
- Kopiera den ursprungliga layoutfilen härifrån till
custom_player_control_view.xml
. - Ta bort
ImageButton
-elementen med id@id/exo_prev
och@id/exo_next
.
För att använda din anpassade layout måste du ställa in attributet app:controller_layout_id
för PlayerView
-elementet i activity_player.xml
-filen.
- Använd layout-id:t för din anpassade fil som i följande kodutdrag:
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"/>
- Starta appen igen. Spelarkontrollvyn har inte längre knapparna föregående och nästa.
Screenshot: Anpassad spelarkontrollvy utan föregående eller nästa knappar
Du kan göra vilka ändringar som helst i layoutfilen. Som standard väljs färgerna i Android-temat. Du kan åsidosätta detta för att matcha designen i din app.
- Lägg till ett
android:tint
-attribut till varjeImageButton
-element:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- Förändra alla
android:textColor
-attribut som du hittar i din anpassade fil till samma färg:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position" android:textColor="#FF00A6FF"/><TextView android:id="@id/exo_duration" android:textColor="#FF00A6FF"/>
- Kör programmet. Nu har du vackra, färgade gränssnittskomponenter!
Screenshot: Du har just skapat en anpassad layoutfil och hänvisat till den med controller_layout_id
i activity_player.xml
.
En annan metod är att åsidosätta standardlayoutfilen som PlayerControlView
använder. Källkoden för PlayerControlView
berättar att den använder R.layout.exo_player_control_view
för layout. Om du skapar en egen layoutfil med samma filnamn använder PlayerControlView
din fil i stället.
- Ta bort attributet
controller_layout_id
som du just lagt till. - Ta bort filen
custom_player_control_view.xml
.
Den PlayerView
i activity_player.xml
ska nu se ut så här:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- Skapa en fil som heter
exo_player_control_view.xml
i mappenres/layout
i din biblioteksmodulplayer-lib
. - Insätt följande kod i
exo_player_control_view.xml
för att lägga till en play-knapp, en pausknapp och enImageView
med en logotyp:
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>
Detta visar hur du kan lägga till egna element här och blanda dem med standardkontrollelement. ExoPlayerView
använder nu din egen kontroll och all logik för att dölja och visa när du interagerar med kontrollen bevaras.
Grattis! Du har lärt dig mycket om att integrera ExoPlayer i din app.
Lär dig mer
.