
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
MediaItems 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.xmlfrånplayer-lib-modulen. - Placera markören inne i
FrameLayout-elementet. - Börja skriva
<PlayerViewoch låt Android Studio automatiskt kompletteraPlayerView-elementet. - Använd
match_parentförwidthochheight. - 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
PlayerActivitymå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
playerViewtill 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,onPauseochonStop. - Initialisera spelaren i
onStartelleronResumecallback 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) ionPauseochonStop.
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:
-
setPlayWhenReadytalar om för spelaren om den ska börja spela upp så snart alla resurser för uppspelning har förvärvats. EftersomplayWhenReadyinitialt ärtruestartar uppspelningen automatiskt första gången appen körs. -
seekTotalar om för spelaren att söka sig till en viss position i ett visst fönster. BådecurrentWindowochplaybackPositioninitialiseras till noll så att uppspelningen startar från början första gången appen körs. -
preparetalar 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
initializePlayertillR.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 MediaItems 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
initializePlayermed 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
initializePlayerpå 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
PlaybackStateListeneriPlayerActivity. - Skapa en
TAGkonstant, som du använder för loggning senare.
PlayerActivity.java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
- Instantera
playbackStateListeneri 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
PlaybackStateListenerautomatiskt.

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
onPlaybackStateChangedgenom 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:
-
onRenderedFirstFrameanropas 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. -
onDroppedVideoFramesanropas när videoramar har tappats. Nedfallna ramar indikerar att uppspelningen är janky och att användarupplevelsen sannolikt är dålig. -
onAudioUnderrunanropas 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_controllertillfalseoch 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_incrementochrewind_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_timeouttalar om förPlayerViewfördröjningen i millisekunder innan kontrollen döljs efter att användaren senast interagerade med den. - Värdena
fastforward_incrementochrewind_incrementtalar 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.xmli 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_prevoch@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_idsom 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.xmli mappenres/layouti din biblioteksmodulplayer-lib. - Insätt följande kod i
exo_player_control_view.xmlför att lägga till en play-knapp, en pausknapp och enImageViewmed 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
.