Medieströmning med ExoPlayer

4ec261ee5a0bd0cc.png

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

  • 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

  1. Starta Android Studio.
  2. Välj fil > Ny > Importera projekt*.*
  3. Importera det ursprungliga projektet från exoplayer-codelab-00.

f2e5feb9ade6c7f7.png

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.

  1. Leverera och kör appen för att kontrollera att allt är som det ska. Appen ska fylla skärmen med en svart bakgrund.

21c0dae6245fbd31.png

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.

  1. Öppna build.gradle-filen för player-lib-modulen.
  2. 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

  1. Öppna layoutresursfilen activity_player.xml från player-lib-modulen.
  2. Placera markören inne i FrameLayout-elementet.
  3. Börja skriva <PlayerView och låt Android Studio automatiskt komplettera PlayerView-elementet.
  4. Använd match_parent för width och height.
  5. 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.

  1. I PlayerActivity måste du nu hitta videovyn så att du kan ställa in den korrekt i onCreate-metoden i aktiviteten.

PlayerActivity.java

@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
  1. Lägg till medlemsfältet playerView till din PlayerActivity-klass. Se till att vyns typ är PlayerView.

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

b0f7f70115bb90e5.png

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.

  1. 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.

  1. Med PlayerActivity öppen klickar du på Kodmeny > Överstyr metoder….
  2. Välj onStart, onResume, onPause och onStop.
  3. Initialisera spelaren i onStart eller onResume 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.

  1. 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.

  1. Släpp resurser med releasePlayer (som du skapar inom kort) i onPause och onStop.

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.

  1. 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.

  1. 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. Eftersom playWhenReady initialt är true 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åde currentWindow och playbackPosition 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.

1d049aead0483777.png

Screenshot:

Testa aktivitetslivscykeln

Testa om appen fungerar i alla olika tillstånd i aktivitetslivscykeln.

  1. Starta en annan app och sätt din app i förgrunden igen. Återgår den till rätt position?
  2. 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?
  3. 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.

  1. Ändra URI i initializePlayer till R.string.media_url_mp4.
  2. 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.

4ebd0b0f98593691.png

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.

  1. 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 1f79fee4d082870f.pngoch 39627002c03ce320.png för att navigera i sekvensen av medieobjekt.

7b5c034dafabe1bd.png

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.

  1. 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.

  1. Uppdatera initializePlayer på följande sätt:

PlayerActivity.java

  1. 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

  1. Deklarera en privat medlem av typen PlaybackStateListener i PlayerActivity.
  2. Skapa en TAGkonstant, som du använder för loggning senare.

PlayerActivity.java

private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
  1. Instantera playbackStateListener i början av onCreate (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();
  1. Använd Quick Fix för att skapa den inre klassen PlaybackStateListener automatiskt.

b59ce69a22595ba7.png

Screenshot: Quick Fix-menyn för att skapa en saknad klass

  1. Implementera gränssnittet Player.EventListener. Detta används för att informera dig om viktiga spelarhändelser, inklusive fel och ändringar av uppspelningstillstånd.
  2. 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

ExoPlayer.STATE_IDLE

Spelaren har instansierats, men har inte förberetts ännu.

ExoPlayer.STATE_BUFFERING

Spelaren kan inte spela från den aktuella positionen eftersom inte tillräckligt med data har buffrats.

ExoPlayer.STATE_READY

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 true. Om den är false är spelaren pausad.

ExoPlayer.STATE_ENDED

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.

  1. 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.

  1. För bort lyssnaren i releasePlayer:

PlayerActivity.java

private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
  1. Öppna logcat och kör appen.
  2. 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.

bcfe17eebcad9e13.png

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.

  1. Sätt use_controller till false och kontrollen visas inte längre:

activity_player.xml

<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
  1. 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.

  1. Ta bort app:use_controller="false".
  2. Ändra spelarvyn så att den använder show_timeout, fastforward_increment och rewind_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ör PlayerView fördröjningen i millisekunder innan kontrollen döljs efter att användaren senast interagerade med den.
  • Värdena fastforward_increment och rewind_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.

  1. Skapa en ny layoutfil custom_player_control_view.xml i mappen player-lib/res/layout/.
  2. I layoutmappens kontextmeny väljer du Ny – Layoutresursfil och namnger den custom_player_control_view.xml.

ae1e3795726d4e4e.png

Screenshot: Layoutfilen för spelarkontrollvyn har skapats.

  1. Kopiera den ursprungliga layoutfilen härifrån till custom_player_control_view.xml.
  2. 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.

  1. 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"/>
  1. Starta appen igen. Spelarkontrollvyn har inte längre knapparna föregående och nästa.

89e6535a22c8e321.png

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.

  1. Lägg till ett android:tint-attribut till varje ImageButton-element:

custom_player_control_view.xml

<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
  1. 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"/>
  1. Kör programmet. Nu har du vackra, färgade gränssnittskomponenter!

e9835d65d6dd0634.png

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.

  1. Ta bort attributet controller_layout_id som du just lagt till.
  2. 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"/>
  1. Skapa en fil som heter exo_player_control_view.xml i mappen res/layout i din biblioteksmodul player-lib.
  2. Insätt följande kod i exo_player_control_view.xml för att lägga till en play-knapp, en pausknapp och en ImageView 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

.

Lämna ett svar

Din e-postadress kommer inte publiceras.