Schermopname: De Android-app YouTube
ExoPlayer is een mediaspeler op app-niveau die is gebouwd bovenop de low-level media-API’s in Android. ExoPlayer heeft een aantal voordelen ten opzichte van de ingebouwde MediaPlayer in Android. Het ondersteunt veel van dezelfde media formaten als MediaPlayer, plus adaptieve formaten, zoals DASH en SmoothStreaming. ExoPlayer is in hoge mate aanpasbaar en uitbreidbaar, waardoor het geschikt is voor vele geavanceerde gebruiksscenario’s. Het is een open-sourceproject dat wordt gebruikt door Google-apps, waaronder YouTube en Google Play Movies & TV.
- Voorvereisten
- Wat u zult doen
- Wat hebt u nodig
- Krijg de code
- Directory structuur
- Importeer het initiële project
- app/build.gradle
- ExoPlayer afhankelijkheid toevoegen
- player-lib/build.gradle
- Voeg het PlayerView element toe
- activity_player.xml
- PlayerActivity.java
- Maak een ExoPlayer
- PlayerActivity.java
- Maak een media-item
- PlayerActivity.java
- Vriendelijk omgaan met de levenscyclus van activiteiten
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Eindvoorbereiding
- PlayerActivity.java
- Play audio
- Test de activiteitenlevenscyclus
- Play video
- PlayerActivity.java
- PlayerActivity.java
- Adaptieve trackselectie
- PlayerActivity.java
- Bouw een adaptief MediaItem
- PlayerActivity.java
- Andere adaptieve streamingformaten
- Luister
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Registreer uw luisteraar
- PlayerActivity.java
- PlayerActivity.java
- Ga dieper
- activity_player.xml
- activity_player.xml
- Aanpassen van het gedrag
- activity_player.xml
- Aanpassen van het uiterlijk
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- De standaardstijl overschrijven
- activity_player.xml
- exo_player**_control_view.xml**
- Lees meer
Voorvereisten
- Meerdere kennis van Android-ontwikkeling en Android Studio
Wat u zult doen
- Een
SimpleExoPlayer
instance maken, die media uit verschillende bronnen voorbereidt en afspeelt. - Integreer ExoPlayer met de activiteitencyclus van de app om ondersteuning te bieden voor backgrounding, foregrounding en het hervatten van het afspelen in een omgeving met één of meerdere vensters.
- Gebruik
MediaItem
s om een afspeellijst te maken. - Play adaptieve video streams, die de media kwaliteit aan te passen aan de beschikbare bandbreedte.
- Registreer gebeurtenis luisteraars om het afspelen staat te controleren en laten zien hoe luisteraars kunnen worden gebruikt om de kwaliteit van het afspelen te meten.
- Gebruik standaard ExoPlayer UI-componenten, pas ze vervolgens aan de stijl van uw app aan.
Wat hebt u nodig
- Android Studio versie 3.5 of hoger
- Een Android-toestel met JellyBean (4.1) of hoger, idealiter met Nougat (7.1) of hoger omdat het meerdere vensters ondersteunt.
Krijg de code
Om te beginnen, downloadt u het Android Studio-project:
Download zip
Als alternatief kunt u de GitHub-repository klonen:
git clone https://github.com/googlecodelabs/exoplayer-intro.git
Directory structuur
Het klonen of unzippen levert u een hoofdmap op (exoplayer-intro
), die een map bevat voor elke stap van dit codelab, samen met alle bronnen die u nodig hebt:
/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
De exoplayer-codelab-N
mappen (waarbij N
00
tot 04
is) bevatten de gewenste eindtoestand van elke stap van dit codelab. Dit zijn standalone Android Studio projecten, die elk kunnen worden geïmporteerd.
Importeer het initiële project
- Start Android Studio.
- Kies Bestand > Nieuw > Import Project*.*
- Importeer het initiële project van
exoplayer-codelab-00
.
Schermopname: Project structuur bij importeren
Nadat het bouwen is voltooid, ziet u twee modules: de app
module (van het type applicatie) en de player-lib
module (van het type bibliotheek). De app
module is eigenlijk leeg, en heeft alleen een manifest. Alles uit de player-lib
module wordt samengevoegd wanneer de app wordt gebouwd met behulp van een gradle afhankelijkheid in app/build.gradle
.
app/build.gradle
dependencies { implementation project(":player-lib")}
Uw media speler Activiteit wordt bewaard in de player-lib
module. De reden om het in een aparte bibliotheek module te houden is zodat u het kunt delen tussen APKs gericht op verschillende platforms, zoals mobiel en Android TV. Hiermee kunt u ook profiteren van functies zoals Dynamic Delivery, waarmee uw media-afspeelfunctie alleen wordt geïnstalleerd wanneer de gebruiker deze nodig heeft.
- Deploy en voer de app uit om te controleren of alles in orde is. De app moet het scherm vullen met een zwarte achtergrond.
Schermopname: Blanco app draait
ExoPlayer afhankelijkheid toevoegen
ExoPlayer is een open source project dat gehost wordt op GitHub. Elke release wordt gedistribueerd via jCenter, wat een van de standaard package repositories is die wordt gebruikt door Android Studio en Gradle. Elke release wordt uniek geïdentificeerd door een string met het volgende formaat:
com.google.android.exoplayer:exoplayer:rX.X.X
Je kunt ExoPlayer aan je project toevoegen door simpelweg de classes en UI componenten te importeren. Het is vrij klein, met een verkleinde voetafdruk van ongeveer 70 tot 300 kB, afhankelijk van de inbegrepen functies en ondersteunde formaten. De ExoPlayer bibliotheek is opgedeeld in modules om ontwikkelaars toe te laten enkel de functionaliteit te importeren die ze nodig hebben. Voor meer informatie over de modulaire structuur van ExoPlayer, zie ExoPlayer modules toevoegen.
- Open het
build.gradle
bestand van deplayer-lib
module. - Voeg de volgende regels toe aan de
dependencies
sectie en synchroniseer het project.
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'}
Voeg het PlayerView element toe
- Open het layout resource bestand
activity_player.xml
van deplayer-lib
module. - Plaats de cursor binnen het
FrameLayout
element. - Start met het typen van
<PlayerView
en laat Android Studio hetPlayerView
element autocomplete. - Gebruik
match_parent
voor dewidth
enheight
. - Leg het id vast als
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"/>
In het vervolg verwijst u naar dit UI-element als de videoweergave.
- In de
PlayerActivity
moet u nu de videoweergave vinden, zodat u deze correct kunt instellen in deonCreate
-methode van de activity.
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- Voeg het
playerView
-lidveld toe aan uwPlayerActivity
-klasse. Zorg ervoor dat het weergavetypePlayerView
.
Note: gebruik de Quick Fix-functie in Android Studio om een lidveld automatisch toe te voegen. Vergeet niet om het type in te stellen op
PlayerView
in plaats van de standaard
View
Schermopname: Snelmenu voor het maken van een lidveld
Maak een ExoPlayer
Om streaming media af te spelen, heb je een ExoPlayer
object nodig. De eenvoudigste manier om er een te maken is door de SimpleExoPlayer.Builder
klasse te gebruiken. Zoals de naam al doet vermoeden, maakt deze gebruik van het builder patroon om een SimpleExoPlayer
instantie te bouwen.
SimpleExoPlayer
is een handige, all-purpose implementatie van de ExoPlayer
interface.
Voeg een private methode initializePlayer
toe om uw SimpleExoPlayer
te maken.
PlayerActivity.java
private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}
Maak een SimpleExoPlayer.Builder
met behulp van uw context, roep dan build
aan om uw SimpleExoPlayer
object te maken. Dit wordt dan toegewezen aan player
, die u moet verklaren als een lidveld. U gebruikt dan playerView.setPlayer
om de player
te binden aan de bijbehorende view.
Maak een media-item
Uw player
heeft nu wat inhoud nodig om af te spelen. Hiervoor maakt u een MediaItem
. Er zijn veel verschillende soorten MediaItem
, maar u begint met het maken van een MediaItem
voor een MP3 bestand op het internet.
De eenvoudigste manier om een MediaItem
te maken is om MediaItem.fromUri
te gebruiken, die de URI van een mediabestand accepteert. Voeg de MediaItem
toe aan de player
met behulp van player.setMediaItem
.
- Voeg de volgende code toe aan
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}
Merk op dat R.string.media_url_mp3
is gedefinieerd als https://storage.googleapis.com/exoplayer-test-media-0/play.mp3 in strings.xml
.
Vriendelijk omgaan met de levenscyclus van activiteiten
Onze player
kan veel bronnen in beslag nemen, waaronder geheugen, CPU, netwerkverbindingen en hardware codecs. Veel van deze bronnen zijn schaars, vooral voor hardware codecs waar er misschien maar één is. Het is belangrijk dat u deze bronnen vrijgeeft voor andere apps om te gebruiken wanneer u ze niet gebruikt, zoals wanneer uw app op de achtergrond wordt gezet.
Anders gezegd, de levenscyclus van uw speler moet worden gekoppeld aan de levenscyclus van uw app. Om dit te implementeren, moet u de vier methoden van PlayerActivity
overriden: onStart
, onResume
, onPause
, en onStop
.
- Met
PlayerActivity
open, klik op Code menu > Override methods…. - Selecteer
onStart
,onResume
,onPause
, enonStop
. - Initialiseer de speler in de
onStart
ofonResume
callback, afhankelijk van het API-niveau.
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-niveau 24 en hoger ondersteunt meerdere vensters. Omdat uw app zichtbaar kan zijn, maar niet actief in split window mode, moet u de speler initialiseren in onStart
. Android API-niveau 24 en lager vereist dat u zo lang mogelijk wacht tot u resources pakt, dus u wacht tot onResume
voordat u de speler initialiseert.
- Voeg de methode
hideSystemUi
toe.
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
is een helpermethode die wordt aangeroepen in onResume
, waarmee u een schermvullende ervaring kunt hebben.
- Release resources met
releasePlayer
(die u binnenkort maakt) inonPause
enonStop
.
PlayerActivity.java
@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}
Met API-niveau 24 en lager is er geen garantie dat onStop
wordt aangeroepen, dus moet u de speler zo vroeg mogelijk in onPause
vrijgeven. Met API Level 24 en hoger (welke multi- en split-window mode bracht), is onStop
gegarandeerd aangeroepen te worden. In de gepauzeerde toestand is uw activiteit nog steeds zichtbaar, dus wacht u met het vrijgeven van de speler tot onStop
.
U moet nu een releasePlayer
-methode maken, die de bronnen van de speler vrijmaakt en deze vernietigt.
- Voeg de volgende code toe aan de activiteit:
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; }}
Voordat u de speler vrijgeeft en vernietigt, slaat u de volgende informatie op:
- Situatie afspelen/pauzeren met behulp van
getPlayWhenReady
. - Huidige afspeelpositie met behulp van
getCurrentPosition
. - Huidige vensterindex met behulp van
getCurrentWindowIndex
. Voor meer informatie over vensters, zie Timeline.
Hiermee kunt u het afspelen hervatten vanaf het punt waar de gebruiker was gebleven. Het enige wat u hoeft te doen is deze toestandsinformatie te verstrekken wanneer u uw speler initialiseert.
Eindvoorbereiding
Het enige wat u nu nog hoeft te doen is de toestandsinformatie die u in releasePlayer
hebt opgeslagen, aan uw speler te verstrekken tijdens de initialisatie.
- Voeg het volgende toe aan
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}
Dit is wat er gebeurt:
-
setPlayWhenReady
vertelt de speler of hij moet beginnen met spelen zodra alle bronnen voor het afspelen zijn verkregen. OmdatplayWhenReady
in eerste instantietrue
is, begint het afspelen automatisch de eerste keer dat de app wordt uitgevoerd. -
seekTo
vertelt de speler te zoeken naar een bepaalde positie binnen een specifiek venster. ZowelcurrentWindow
alsplaybackPosition
worden op nul gezet, zodat het afspelen vanaf het begin begint als de app voor de eerste keer wordt gestart. -
prepare
vertelt de speler om alle bronnen te verwerven die nodig zijn voor het afspelen.
Play audio
Eindlijk bent u klaar! Start de app om het MP3-bestand af te spelen en de ingesloten illustraties te bekijken.
Schermopname: De app speelt een enkel nummer af.
Test de activiteitenlevenscyclus
Test of de app werkt in alle verschillende toestanden van de activiteitenlevenscyclus.
- Start een andere app en zet uw app opnieuw op de voorgrond. Wordt de app op de juiste positie hervat?
- Pauzeer de app, verplaats deze naar de achtergrond en vervolgens weer naar de voorgrond. Blijft het op een gepauzeerde toestand wanneer het op de achtergrond is?
- Roteer de app. Hoe gedraagt het zich als u de oriëntatie verandert van portret naar landschap en terug?
Play video
Als u video wilt afspelen, is het zo eenvoudig als het wijzigen van het media-item URI naar een MP4-bestand.
- Verander de URI in de
initializePlayer
naarR.string.media_url_mp4
. - Start de app opnieuw en test het gedrag na op de achtergrond te zijn gezet met het afspelen van video ook.
PlayerActivity.java
private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }
De PlayerView
doet het allemaal. In plaats van het artwork wordt de video schermvullend weergegeven.
Schermopname: De app die video afspeelt.
You rock! Je hebt zojuist een app gemaakt voor het streamen van media op volledig scherm op Android, compleet met lifecycle management, opgeslagen status en UI-besturingselementen!
Je huidige app speelt een enkel mediabestand af, maar wat als je meer dan een mediabestand wilt afspelen, achter elkaar? Daarvoor hebt u een afspeellijst nodig.
Playlists kunnen worden gemaakt door meer MediaItem
s aan uw player
toe te voegen met addMediaItem
. Dit maakt naadloos afspelen mogelijk en het bufferen wordt op de achtergrond afgehandeld, zodat de gebruiker geen bufferende spinner ziet bij het wisselen van media-items.
- Voeg de volgende code toe aan
initializePlayer
:
PlayerActivity.java
private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }
Controleer hoe de bediening van de speler zich gedraagt. U kunt en gebruiken om door de opeenvolging van media-items te navigeren.
Schermopname: Afspeelknoppen met een volgende en vorige knop
Dat is best handig! Zie voor meer informatie de documentatie voor ontwikkelaars over media-items en afspeellijsten, en dit artikel over de afspeellijst-API.
Adaptief streamen is een techniek voor het streamen van media waarbij de kwaliteit van de stream wordt gevarieerd op basis van de beschikbare netwerkbandbreedte. Hierdoor kan de gebruiker de media van de beste kwaliteit ervaren die zijn bandbreedte toelaat.
Typisch wordt dezelfde media-inhoud opgesplitst in meerdere tracks met verschillende kwaliteiten (bitsnelheden en resoluties). De speler kiest een track op basis van de beschikbare netwerkbandbreedte.
Elke track wordt opgesplitst in brokjes van een bepaalde duur, meestal tussen 2 en 10 seconden. Dit stelt de speler in staat om snel tussen tracks te wisselen als de beschikbare bandbreedte verandert. De speler is verantwoordelijk voor het aan elkaar hechten van deze brokken voor naadloze weergave.
Adaptieve trackselectie
De kern van adaptieve streaming is het selecteren van de meest geschikte track voor de huidige omgeving. Werk uw app bij om adaptieve streamingmedia af te spelen door adaptieve trackselectie te gebruiken.
- Update
initializePlayer
met de volgende code:
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(); }
Maak eerst een DefaultTrackSelector
, die verantwoordelijk is voor het kiezen van tracks in het media-item. Vertel je trackSelector
dan alleen tracks te kiezen met een standaard definitie of lager – een goede manier om de gegevens van je gebruiker te sparen ten koste van de kwaliteit. Geef tenslotte uw trackSelector
door aan uw bouwer, zodat deze wordt gebruikt bij het bouwen van de SimpleExoPlayer
instantie.
Bouw een adaptief MediaItem
DASH is een veel gebruikt adaptief streaming formaat. Om DASH inhoud te streamen, moet u een MediaItem
maken zoals voorheen. Deze keer moeten we echter een MediaItem.Builder
gebruiken in plaats van fromUri
.
Dit komt omdat fromUri
de bestandsextensie gebruikt om het onderliggende mediaformaat te bepalen, maar onze DASH URI heeft geen bestandsextensie, dus moeten we een MIME-type van APPLICATION_MPD
opgeven bij het construeren van de MediaItem
.
- Update
initializePlayer
als volgt:
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);}
- Herstart de app en zie adaptieve videostreaming met DASH in actie. Het is heel eenvoudig met ExoPlayer!
Andere adaptieve streamingformaten
HLS (MimeTypes.APPLICATION_M3U8
) en SmoothStreaming (MimeTypes.APPLICATION_SS
) zijn andere veelgebruikte adaptieve streamingformaten, die beide worden ondersteund door ExoPlayer. Voor meer informatie over het bouwen van andere adaptieve media bronnen, zie de ExoPlayer demo app.
In de vorige stappen heb je geleerd hoe je progressieve en adaptieve media streams kunt streamen. ExoPlayer doet veel werk voor u achter de schermen, waaronder het volgende:
- Het toewijzen van geheugen
- Het downloaden van container bestanden
- Het extraheren van metadata uit de container
- Het decoderen van data
- Het weergeven van video, audio en tekst naar het scherm en de luidsprekers
Soms is het nuttig om te weten wat ExoPlayer tijdens runtime doet om de afspeelervaring voor uw gebruikers te begrijpen en te verbeteren.
U zou bijvoorbeeld veranderingen in de afspeelstatus in de gebruikersinterface kunnen weergeven door het volgende te doen:
- Het tonen van een laadspinner als de speler in een bufferstatus komt
- Het tonen van een overlay met “bekijk volgende” opties als de track is afgelopen
ExoPlayer biedt verschillende listener interfaces die callbacks bieden voor nuttige gebeurtenissen. U gebruikt een luisteraar om te loggen in welke toestand de speler zich bevindt.
Luister
- Declare een private member van het type
PlaybackStateListener
in dePlayerActivity
. - Creëer een
TAG
constante, die u later gebruikt voor logging.
PlayerActivity.java
private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
- Instantieer de
playbackStateListener
aan het begin vanonCreate
(het zal nog niet compileren, maar je repareert dit binnenkort).
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
- Gebruik Quick Fix om de binnenste klasse
PlaybackStateListener
automatisch te maken.
Schermopname: Quick Fix-menu voor het maken van een ontbrekende klasse
- Implementeer de interface
Player.EventListener
. Deze wordt gebruikt om u te informeren over belangrijke speler gebeurtenissen, inclusief fouten en afspeel toestand veranderingen. - Override
onPlaybackStateChanged
door het toevoegen van de volgende code:
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
wordt aangeroepen wanneer de afspeel toestand verandert. De nieuwe toestand wordt gegeven door de parameter playbackState
.
De speler kan zich in een van de volgende vier toestanden bevinden:
State |
Description |
|
De speler is geïnstantieerd, maar is nog niet voorbereid. |
|
De speler is niet in staat om vanaf de huidige positie af te spelen omdat er niet genoeg gegevens zijn gebufferd. |
|
De speler is in staat om onmiddellijk vanaf de huidige positie af te spelen. Dit betekent dat de speler automatisch begint met het afspelen van media als de eigenschap playWhenReady van de speler |
|
De speler is klaar met het afspelen van de media. |
Registreer uw luisteraar
Om uw callbacks te laten aanroepen, moet u uw playbackStateListener
bij de speler registreren. Doe dat in initializePlayer
.
- Registreer de luisteraar voordat het afspelen wordt voorbereid.
PlayerActivity.java
private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}
Ook hier moet je opruimen om bungelende verwijzingen van de speler die een geheugenlek zouden kunnen veroorzaken te voorkomen.
- Verwijder de luisteraar in
releasePlayer
:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- Open logcat en voer de app uit.
- Gebruik de UI-besturingselementen om het afspelen te zoeken, te pauzeren en te hervatten. U zou de afspeelstatus moeten zien veranderen in de logs.
Ga dieper
ExoPlayer biedt een aantal andere luisteraars, die nuttig zijn bij het begrijpen van de afspeelervaring van de gebruiker. Er zijn luisteraars voor audio en video, en ook een AnalyticsListener
, die de callbacks van alle luisteraars bevat. Enkele van de belangrijkste methoden zijn de volgende:
-
onRenderedFirstFrame
wordt aangeroepen wanneer het eerste frame van een video wordt gerenderd. Hiermee kunt u berekenen hoe lang de gebruiker heeft moeten wachten om zinvolle inhoud op het scherm te zien. -
onDroppedVideoFrames
wordt aangeroepen wanneer video frames zijn gedropped. Afgevallen frames geven aan dat het afspelen hapert en de gebruikerservaring is waarschijnlijk slecht. -
onAudioUnderrun
wordt aangeroepen wanneer er een audio underrun is geweest. Underruns veroorzaken hoorbare haperingen in het geluid en zijn opvallender dan dropped video frames.
AnalyticsListener
kan worden toegevoegd aan de player
met addAnalyticsListener
. Er zijn ook overeenkomstige methoden voor de audio- en videoluisteraars.
Bedenk welke gebeurtenissen belangrijk zijn voor uw app en uw gebruikers. Voor meer informatie, zie Luisteren naar speler gebeurtenissen. Dat is het voor gebeurtenis-luisteraars!
Tot nu toe hebt u ExoPlayer PlayerControlView
gebruikt om een afspeelcontroller aan de gebruiker te tonen.
Schermopname: Standaard afspeelbesturing
Wat als u de functionaliteit of het uiterlijk van deze besturingselementen wilt wijzigen? Gelukkig zijn deze regelaars in hoge mate aanpasbaar.
De eerste eenvoudige aanpassing is om de regelaar helemaal niet te gebruiken. Dit kan eenvoudig worden gedaan door het use_controller
-attribuut te gebruiken op het PlayerView
-element binnen activity_player.xml
.
- Stel
use_controller
in opfalse
en de besturing wordt niet meer weergegeven:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
- Voeg de volgende namespace toe aan uw
FrameLayout
:
activity_player.xml
<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">
Probeer het nu.
Aanpassen van het gedrag
PlayerControlView
heeft verschillende attributen die het gedrag beïnvloeden. Gebruik show_timeout
, fastforward_increment
, en rewind_increment
om het gedrag van de controller aan te passen.
- Verwijder
app:use_controller="false"
. - Verander de spelerweergave om
show_timeout
,fastforward_increment
enrewind_increment
te gebruiken:
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"/>
- De
show_timeout
waarde vertelt dePlayerView
de vertraging in milliseconden voordat het besturingselement wordt verborgen nadat de gebruiker er voor het laatst mee heeft ge¨ınteracteerd. - De
fastforward_increment
enrewind_increment
waarden vertellen de speler de tijd in milliseconden om vooruit of achteruit te springen wanneer de gebruiker op de vooruitspoel of terugspoel knoppen tikt.
De attributen van de PlayerControlView
kunnen ook programmatisch worden ingesteld.
Aanpassen van het uiterlijk
Wel, dat is een goed begin. Maar wat als u de PlayerControlView
er anders uit wilt laten zien of wilt veranderen welke knoppen worden weergegeven? De implementatie van PlayerControlView
gaat er niet van uit dat er knoppen bestaan, dus het is eenvoudig om ze te verwijderen en nieuwe toe te voegen.
Kijk eens hoe u de PlayerControlView
kunt aanpassen.
- Maak een nieuw opmaak bestand
custom_player_control_view.xml
in de mapplayer-lib/res/layout/
. - Vanuit het context menu van de opmaak map, kies Nieuw – Opmaak bron bestand en noem het
custom_player_control_view.xml
.
Schermopname: Het opmaakbestand voor de spelerbesturingsweergave is gemaakt.
- Kopieer het oorspronkelijke opmaakbestand van hier naar
custom_player_control_view.xml
. - Verwijder de
ImageButton
elementen met de id@id/exo_prev
en@id/exo_next
.
Om uw aangepaste lay-out te gebruiken, moet u het kenmerk app:controller_layout_id
van het PlayerView
element in het activity_player.xml
bestand instellen.
- Gebruik de lay-out ID van uw aangepaste bestand zoals in het volgende codefragment:
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"/>
- Start de app opnieuw. De spelerbesturingsweergave heeft niet langer de knoppen Vorige en Volgende.
Schermopname: Aangepaste spelerbesturingsweergave zonder knoppen Vorige en Volgende
U kunt de gewenste wijzigingen aanbrengen in het lay-outbestand. Standaard worden de kleuren van het Android thema gekozen. U kunt dit opheffen zodat het overeenkomt met het ontwerp van uw app.
- Voeg een
android:tint
-attribuut toe aan elkImageButton
-element:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- Verander alle
android:textColor
-attributen in uw aangepaste bestand in dezelfde kleur:#FF00A6FF
.
custom_player_control_view.xml
<TextView android:id="@id/exo_position" android:textColor="#FF00A6FF"/><TextView android:id="@id/exo_duration" android:textColor="#FF00A6FF"/>
- Run de app. Nu hebt u prachtige, gekleurde UI-componenten!
Schermopname: Gekleurde knoppen en tekst
De standaardstijl overschrijven
U hebt zojuist een aangepast opmaakbestand gemaakt en daarnaar verwezen met controller_layout_id
in activity_player.xml
.
Een andere benadering is om het standaardopmaakbestand dat PlayerControlView
gebruikt, te overschrijven. De broncode van PlayerControlView
vertelt ons dat het R.layout.exo_player_control_view
gebruikt voor opmaak. Als u ons eigen opmaakbestand maakt met dezelfde bestandsnaam, gebruikt PlayerControlView
uw bestand in plaats daarvan.
- Verwijder het
controller_layout_id
attribuut dat u zojuist hebt toegevoegd. - Verwijder het bestand
custom_player_control_view.xml
.
De PlayerView
in activity_player.xml
zou er nu als volgt uit moeten zien:
activity_player.xml
<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>
- Maak een bestand met de naam
exo_player_control_view.xml
in deres/layout
map van uw bibliotheekmoduleplayer-lib
. - Invoeg de volgende code in
exo_player_control_view.xml
om een afspeelknop, een pauzeknop, en eenImageView
met een logo toe te voegen:
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>
Dit demonstreert hoe u hier uw eigen elementen kunt toevoegen en ze kunt mengen met standaard besturingselementen. ExoPlayerView
gebruikt nu uw aangepaste besturingselement en alle logica voor het verbergen en tonen bij interactie met het besturingselement is behouden.
Gefeliciteerd! U heeft veel geleerd over het integreren van ExoPlayer in uw app.