Media streamen met ExoPlayer

4ec261ee5a0bd0cc.png

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

  • 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 MediaItems 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

  1. Start Android Studio.
  2. Kies Bestand > Nieuw > Import Project*.*
  3. Importeer het initiële project van exoplayer-codelab-00.

f2e5feb9ade6c7f7.png

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.

  1. Deploy en voer de app uit om te controleren of alles in orde is. De app moet het scherm vullen met een zwarte achtergrond.

21c0dae6245fbd31.png

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.

  1. Open het build.gradle bestand van de player-lib module.
  2. 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

  1. Open het layout resource bestand activity_player.xml van de player-lib module.
  2. Plaats de cursor binnen het FrameLayout element.
  3. Start met het typen van <PlayerView en laat Android Studio het PlayerView element autocomplete.
  4. Gebruik match_parent voor de width en height.
  5. 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.

  1. In de PlayerActivity moet u nu de videoweergave vinden, zodat u deze correct kunt instellen in de onCreate-methode van de activity.

PlayerActivity.java

@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
  1. Voeg het playerView-lidveld toe aan uw PlayerActivity-klasse. Zorg ervoor dat het weergavetype PlayerView.

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

b0f7f70115bb90e5.png

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.

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

  1. Met PlayerActivity open, klik op Code menu > Override methods….
  2. Selecteer onStart, onResume, onPause, en onStop.
  3. Initialiseer de speler in de onStart of onResume 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.

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

  1. Release resources met releasePlayer (die u binnenkort maakt) in onPause en 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(); }}

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.

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

  1. 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. Omdat playWhenReady in eerste instantie true 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. Zowel currentWindow als playbackPosition 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.

1d049aead0483777.png

Schermopname: De app speelt een enkel nummer af.

Test de activiteitenlevenscyclus

Test of de app werkt in alle verschillende toestanden van de activiteitenlevenscyclus.

  1. Start een andere app en zet uw app opnieuw op de voorgrond. Wordt de app op de juiste positie hervat?
  2. 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?
  3. 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.

  1. Verander de URI in de initializePlayer naar R.string.media_url_mp4.
  2. 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.

4ebd0b0f98593691.png

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

  1. 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 1f79fee4d082870f.pngen 39627002c03ce320.png gebruiken om door de opeenvolging van media-items te navigeren.

7b5c034dafabe1bd.png

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.

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

  1. 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);}
  1. 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

  1. Declare een private member van het type PlaybackStateListener in de PlayerActivity.
  2. Creëer een TAG constante, die u later gebruikt voor logging.

PlayerActivity.java

private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
  1. Instantieer de playbackStateListener aan het begin van onCreate (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();
  1. Gebruik Quick Fix om de binnenste klasse PlaybackStateListener automatisch te maken.

b59ce69a22595ba7.png

Schermopname: Quick Fix-menu voor het maken van een ontbrekende klasse

  1. Implementeer de interface Player.EventListener. Deze wordt gebruikt om u te informeren over belangrijke speler gebeurtenissen, inclusief fouten en afspeel toestand veranderingen.
  2. 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

ExoPlayer.STATE_IDLE

De speler is geïnstantieerd, maar is nog niet voorbereid.

ExoPlayer.STATE_BUFFERING

De speler is niet in staat om vanaf de huidige positie af te spelen omdat er niet genoeg gegevens zijn gebufferd.

ExoPlayer.STATE_READY

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 true is. Als deze false is, wordt de speler gepauzeerd.

ExoPlayer.STATE_ENDED

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.

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

  1. Verwijder de luisteraar in releasePlayer:

PlayerActivity.java

private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
  1. Open logcat en voer de app uit.
  2. 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.

bcfe17eebcad9e13.png

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.

  1. Stel use_controller in op false en de besturing wordt niet meer weergegeven:

activity_player.xml

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

  1. Verwijder app:use_controller="false".
  2. Verander de spelerweergave om show_timeout, fastforward_increment en rewind_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 de PlayerView de vertraging in milliseconden voordat het besturingselement wordt verborgen nadat de gebruiker er voor het laatst mee heeft ge¨ınteracteerd.
  • De fastforward_increment en rewind_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.

  1. Maak een nieuw opmaak bestand custom_player_control_view.xml in de map player-lib/res/layout/.
  2. Vanuit het context menu van de opmaak map, kies Nieuw – Opmaak bron bestand en noem het custom_player_control_view.xml.

ae1e3795726d4e4e.png

Schermopname: Het opmaakbestand voor de spelerbesturingsweergave is gemaakt.

  1. Kopieer het oorspronkelijke opmaakbestand van hier naar custom_player_control_view.xml.
  2. 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.

  1. 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"/>
  1. Start de app opnieuw. De spelerbesturingsweergave heeft niet langer de knoppen Vorige en Volgende.

89e6535a22c8e321.png

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.

  1. Voeg een android:tint-attribuut toe aan elk ImageButton-element:

custom_player_control_view.xml

<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
  1. 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"/>
  1. Run de app. Nu hebt u prachtige, gekleurde UI-componenten!

e9835d65d6dd0634.png

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.

  1. Verwijder het controller_layout_id attribuut dat u zojuist hebt toegevoegd.
  2. 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"/>
  1. Maak een bestand met de naam exo_player_control_view.xml in de res/layout map van uw bibliotheekmodule player-lib.
  2. Invoeg de volgende code in exo_player_control_view.xml om een afspeelknop, een pauzeknop, en een ImageView 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.

Lees meer

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.