Media streaming az ExoPlayerrel

4ec261ee5a0bd0cc.png

Képernyőkép: Az ExoPlayer egy alkalmazásszintű médialejátszó, amely az Android alacsony szintű média API-jaira épül. Az ExoPlayer számos előnnyel rendelkezik az Android beépített MediaPlayerével szemben. Számos olyan médiaformátumot támogat, mint a MediaPlayer, valamint adaptív formátumokat, például a DASH-t és a SmoothStreaminget. Az ExoPlayer nagymértékben testreszabható és bővíthető, így számos fejlett felhasználási esetre képes. Ez egy nyílt forráskódú projekt, amelyet a Google alkalmazásai, köztük a YouTube és a Google Play Movies & TV használnak.

Előfeltételek

  • Moderate knowledge of Android development and Android Studio

What you’ll do

  • Create a SimpleExoPlayer instance, which preparates and play media from a variety sources.
  • Integrálja az ExoPlayert az alkalmazás aktivitási életciklusába, hogy támogassa a háttérbe állítást, az előtérbe állítást és a lejátszás folytatását egy- vagy többablakos környezetben.
  • Használja a MediaItem-eket egy lejátszási lista létrehozásához.
  • Adaptív videofolyamok lejátszása, amelyek a médiaminőséget a rendelkezésre álló sávszélességhez igazítják.
  • Eseményhallgatók regisztrálása a lejátszás állapotának figyelésére, és annak bemutatása, hogy a hallgatók hogyan használhatók a lejátszás minőségének mérésére.
  • A standard ExoPlayer UI komponensek használata, majd testreszabása az alkalmazás stílusához.

Mire lesz szüksége

  • Android Studio 3.5 vagy újabb verzió
  • Egy Android készülék JellyBean (4.1) vagy újabb verzióval, ideális esetben Nougat (7.1) vagy újabb verzióval, mivel támogatja a több ablakot.

A kód beszerzése

A kezdéshez töltse le az Android Studio projektet:

Download zip

Alternatívaként klónozhatja a GitHub tárolót:

git clone https://github.com/googlecodelabs/exoplayer-intro.git

Könyvtárszerkezet

A klónozás vagy a kicsomagolás egy gyökérmappát (exoplayer-intro) biztosít, amely tartalmaz egy mappát a kódlabor minden egyes lépéséhez, valamint az összes szükséges erőforrást:

/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

A exoplayer-codelab-N mappák (ahol N 00-től 04-ig) tartalmazzák a kódlabor minden egyes lépésének kívánt végállapotát. Ezek önálló Android Studio projektek, amelyek mindegyike importálható.

Importálja a kezdeti projektet

  1. Indítsa el az Android Studio-t.
  2. Válassza a Fájl > Új > Projekt importálása*.*
  3. Importálja a kezdeti projektet a exoplayer-codelab-00-ből.

f2e5feb9ade6c7f7.png

Képernyőkép: A projekt szerkezete importáláskor

Az építés befejezése után két modul látható: a app modul (alkalmazás típusú) és a player-lib modul (könyvtár típusú). A app modul valójában üres, csak egy manifesztummal rendelkezik. Az player-lib modulból minden összeolvad, amikor az alkalmazás építése a app/build.gradle.

app/build.gradle

dependencies { implementation project(":player-lib")}

gradle függőség segítségével történik.

app/build.gradle

dependencies { implementation project(":player-lib")}

A médialejátszó aktivitása a player-lib modulban marad. Azért tartjuk külön könyvtármodulban, mert így megoszthatjuk a különböző platformokat célzó APK-k között, például a mobil és az Android TV között. Emellett lehetővé teszi, hogy kihasználja az olyan funkciók előnyeit, mint például a dinamikus kézbesítés, amelyek lehetővé teszik, hogy a médialejátszási funkciója csak akkor települjön, amikor a felhasználónak szüksége van rá.

  1. Telepítse és futtassa az alkalmazást, hogy ellenőrizze, minden rendben van-e. Az alkalmazásnak fekete háttérrel kell kitöltenie a képernyőt.

21c0dae6245fbd31.png

Képernyőkép: Üres alkalmazás fut

Az ExoPlayer függőség hozzáadása

Az ExoPlayer egy nyílt forráskódú projekt, amely a GitHubon található. Minden kiadás a jCenter-en keresztül kerül terjesztésre, amely az Android Studio és a Gradle által használt egyik alapértelmezett csomagtároló. Minden egyes kiadást a következő formátumú karakterlánc azonosít egyedileg:

com.google.android.exoplayer:exoplayer:rX.X.X

Az ExoPlayert egyszerűen hozzáadhatja a projektjéhez az osztályai és UI-komponensei importálásával. Elég kicsi, körülbelül 70-300 kB-ra zsugorodott alapterülettel rendelkezik, a beépített funkciók és a támogatott formátumok függvényében. Az ExoPlayer könyvtár modulokra van osztva, hogy a fejlesztők csak a szükséges funkciókat importálhassák. Az ExoPlayer moduláris felépítéséről további információt az ExoPlayer modulok hozzáadása című fejezetben talál.

  1. Nyissa meg a player-lib modul build.gradle fájlját.
  2. Adja hozzá a következő sorokat a dependencies szakaszhoz és szinkronizálja a 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'}

Add hozzá a PlayerView elemet

  1. Nyisd meg az player-lib modulból a activity_player.xml layout resource fájlt.
  2. Tegyük a kurzort a FrameLayout elembe.
  3. Kezdjük el a <PlayerView beírását, és hagyjuk, hogy az Android Studio automatikusan kitöltse a PlayerView elemet.
  4. A match_parent-et használja a width és a height elemhez.
  5. Az id-t deklarálja video_view-ként.

activity_player.xml

<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent"/>

A továbbiakban erre a felhasználói felület elemre videónézetként hivatkozik.

  1. A PlayerActivity-ben most meg kell találnod a videónézetet, hogy megfelelően beállíthasd az aktivitás onCreate metódusában.

PlayerActivity.java

@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
  1. Add hozzá a playerView tagmezőt a PlayerActivity osztályodhoz. Győződjön meg róla, hogy a nézet típusa PlayerView.

Megjegyzés: Használja az Android Studio gyorsjavítás funkcióját a tagmező automatikus hozzáadásához. Ne felejtse el beállítani a típust

PlayerView

nem pedig az alapértelmezett

View

b0f7f70115bb90e5.png

Screenshot:

ExoPlayer létrehozása

A streaming média lejátszásához egy ExoPlayer objektumra van szükség. Egy ilyen létrehozásának legegyszerűbb módja a SimpleExoPlayer.Builder osztály használata. Ahogy a neve is mutatja, ez a builder mintát használja egy SimpleExoPlayer példány létrehozására.

SimpleExoPlayer a ExoPlayer interfész egy kényelmes, minden célra használható implementációja.

Adjunk hozzá egy initializePlayer privát metódust a SimpleExoPlayer létrehozásához.

PlayerActivity.java

private SimpleExoPlayer player;private void initializePlayer() { player = new SimpleExoPlayer.Builder(this).build(); playerView.setPlayer(player);}

Hozzunk létre egy SimpleExoPlayer.Builder-et a környezetünkkel, majd hívjuk a build-t a SimpleExoPlayer objektum létrehozásához. Ezt azután hozzárendeljük a player-hez, amelyet tagmezőként kell deklarálnod. Ezután a playerView.setPlayer segítségével a player-t a megfelelő nézethez kötöd.

Médiaelem létrehozása

A player-ednek most valamilyen tartalomra van szüksége a lejátszáshoz. Ehhez hozzon létre egy MediaItem-t. Sokféle MediaItem létezik, de kezdjük azzal, hogy létrehozunk egyet egy interneten található MP3 fájlhoz.

A MediaItem létrehozásának legegyszerűbb módja a MediaItem.fromUri használata, amely elfogadja egy médiafájl URI-jét. Adjuk hozzá a MediaItem-et a player-hez a player.setMediaItem segítségével.

  1. Adjuk hozzá a következő kódot a initializePlayer-hoz:

PlayerActivity.java

private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.setMediaItem(mediaItem);}

Megjegyezzük, hogy a R.string.media_url_mp3 a strings.xml-ben https://storage.googleapis.com/exoplayer-test-media-0/play.mp3-ként van definiálva.

Az Activity életciklus szépen játszik

A playerünk sok erőforrást, többek között memóriát, CPU-t, hálózati kapcsolatokat és hardveres kodekeket foglalhat le. Ezen erőforrások közül sokan szűkösek, különösen a hardveres kodekek esetében, ahol esetleg csak egy van. Fontos, hogy ezeket az erőforrásokat felszabadítsuk más alkalmazások számára, amikor nem használjuk őket, például amikor az alkalmazásunk háttérbe kerül.

Másképpen fogalmazva, a lejátszó életciklusának az alkalmazásunk életciklusához kell kapcsolódnia. Ennek megvalósításához felül kell írnod a PlayerActivity négy metódusát: onStart, onResume, onPause és onStop.

  1. Az PlayerActivity megnyitásakor kattintson a Kód menü > Módszerek felülírása….
  2. Válassza ki a onStart, onResume, onPause és onStop módszereket.
  3. Inicializálja a lejátszót a onStart vagy onResume visszahívásban az API-szinttől függően.

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 24. és magasabb szintje támogatja a több ablakot. Mivel az alkalmazásod lehet látható, de nem aktív osztott ablakos módban, inicializálnod kell a lejátszót a onStart-ben. Az Android API 24. és alacsonyabb szintje megköveteli, hogy a lehető leghosszabb ideig várjon az erőforrások megragadásával, ezért a lejátszó inicializálásával várjon onResume-ig.

  1. Adja hozzá a hideSystemUi metódust.

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 egy onResume-ban hívott segédmetódus, amely lehetővé teszi a teljes képernyős megjelenítést.

  1. Az erőforrásokat a onPause-ben és a onStop-ban a releasePlayer segítségével (amelyet rövidesen létrehozol) szabadítsd fel.

PlayerActivity.java

@Overridepublic void onPause() { super.onPause(); if (Util.SDK_INT < 24) { releasePlayer(); }}@Overridepublic void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { releasePlayer(); }}

A 24-es vagy alacsonyabb API-szintnél nincs garancia arra, hogy a onStop meghívásra kerül, ezért a onPause-ben minél korábban fel kell szabadítani a játékost. A 24-es és magasabb API-szinttel (amely elhozta a több ablakos és osztott ablakos módot) a onStop meghívása garantált. A szüneteltetett állapotban az aktivitásod még látható, ezért várj a játékos felszabadításával a onStop-ig.

Ezután létre kell hoznod egy releasePlayer metódust, amely felszabadítja a játékos erőforrásait és megsemmisíti azt.

  1. Add hozzá a következő kódot az aktivitáshoz:

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; }}

A lejátszó felszabadítása és megsemmisítése előtt tárolja a következő információkat:

  • A lejátszás/szünet állapota a getPlayWhenReady.
  • A jelenlegi lejátszási pozíció a getCurrentPosition.
  • A jelenlegi ablakindex a getCurrentWindowIndex segítségével. Az ablakokkal kapcsolatos további információkért lásd: Idővonal.

Ez lehetővé teszi a lejátszás folytatását onnan, ahol a felhasználó abbahagyta. Mindössze annyit kell tennie, hogy a lejátszó inicializálásakor megadja ezt az állapotinformációt.

Végső előkészítés

Most már csak annyit kell tennie, hogy a releasePlayer-ben elmentett állapotinformációt megadja a lejátszónak az inicializálás során.

  1. Add hozzá a következőket a initializePlayer-hoz:

PlayerActivity.java

private void initializePlayer() { player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); player.prepare();}

Az alábbiak történnek:

  • setPlayWhenReady közli a lejátszóval, hogy elkezd-e játszani, amint a lejátszáshoz szükséges összes erőforrást megszerezte. Mivel a playWhenReady eredetileg true, a lejátszás automatikusan elindul az alkalmazás első futtatásakor.
  • seekTo megmondja a lejátszónak, hogy keressen egy bizonyos pozíciót egy adott ablakon belül. Mind a currentWindow, mind a playbackPosition nullára van inicializálva, így a lejátszás az alkalmazás első futtatásakor a legelejéről indul.
  • prepare utasítja a lejátszót, hogy szerezze meg a lejátszáshoz szükséges összes erőforrást.

Audio lejátszása

Végre kész! Indítsa el az alkalmazást az MP3 fájl lejátszásához és a beágyazott műalkotás megtekintéséhez.

1d049aead0483777.png

Képernyőkép: Az alkalmazás egyetlen zeneszámot játszik le.

A tevékenység életciklusának tesztelése

Tesztelje, hogy az alkalmazás a tevékenység életciklusának minden különböző állapotában működik-e.

  1. Elindít egy másik alkalmazást, és ismét előtérbe helyezi az alkalmazást. A megfelelő pozícióban folytatódik?
  2. Állítsa le az alkalmazást, majd helyezze azt a háttérbe, majd ismét az előtérbe. Ragaszkodik a szünetelt állapothoz, ha a háttérben szünetelt állapotban van?
  3. Pörgesd meg az alkalmazást. Hogyan viselkedik, ha a tájolást portréról landscape-re és vissza változtatja?

Videó lejátszása

Ha videót szeretne lejátszani, az olyan egyszerű, mint a médiaelem URI-jának módosítása MP4-fájlra.

  1. Változtassa meg az URI-t a initializePlayer-ban R.string.media_url_mp4-re.
  2. Indítsa el újra az alkalmazást, és tesztelje a viselkedést, miután háttérben van a videó lejátszásával is.

PlayerActivity.java

private void initializePlayer() { MediaItem mediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); }

A PlayerView mindent megtesz. Az artwork helyett a videó teljes képernyőn megjelenik.

4ebd0b0f98593691.png

Screenshot: Az alkalmazás lejátssza a videót.

Szuper! Most készítettél egy alkalmazást teljes képernyős médiastreamingre Androidon, életciklus-kezeléssel, mentett állapottal és UI-vezérlőkkel kiegészítve!

A jelenlegi alkalmazásod egyetlen médiafájlt játszik le, de mi van, ha több médiafájlt akarsz lejátszani, egymás után? Ehhez lejátszási listára van szüksége.

A lejátszási listákat úgy hozhatja létre, hogy több MediaItem-et ad hozzá a player-hez a addMediaItem segítségével. Ez lehetővé teszi a zökkenőmentes lejátszást, és a pufferelést a háttérben kezeli, így a felhasználó nem látja a médiaelemek váltásakor a pufferelő pörgettyűt.

  1. Add hozzá a következő kódot a initializePlayer-hoz:

PlayerActivity.java

private void initializePlayer() { player.setMediaItem(mediaItem); // Existing code MediaItem secondMediaItem = MediaItem.fromUri(getString(R.string.media_url_mp3)); player.addMediaItem(secondMediaItem); }

Nézd meg, hogyan viselkednek a lejátszó vezérlői. A 1f79fee4d082870f.pngés 39627002c03ce320.png segítségével navigálhat a médiaelemek sorrendjében.

7b5c034dafabe1bd.png

Képernyőkép: A lejátszásvezérlők a következő és az előző gombot mutatják

Ez nagyon praktikus! További információkért lásd a Médiaelemek és lejátszási listák fejlesztői dokumentációját, valamint ezt a cikket a lejátszási lista API-ról.

Az adaptív streaming a média streaming technikája, amely a stream minőségét a rendelkezésre álló hálózati sávszélesség alapján változtatja. Ez lehetővé teszi a felhasználó számára, hogy a sávszélessége által megengedett legjobb minőségű médiát élvezhesse.

Tipikusan ugyanazt a médiatartalmat több, különböző minőségű (bitsebességű és felbontású) zeneszámra osztják fel. A lejátszó a rendelkezésre álló hálózati sávszélesség alapján választ sávot.

Minden sáv adott időtartamú, általában 2 és 10 másodperc közötti darabokra van felosztva. Ez lehetővé teszi a lejátszó számára, hogy a rendelkezésre álló sávszélesség változásával gyorsan váltson a zeneszámok között. A lejátszó felelős e darabok összeillesztéséért a zökkenőmentes lejátszás érdekében.

Adaptív sávválasztás

Az adaptív streaming középpontjában az aktuális környezetnek leginkább megfelelő sáv kiválasztása áll. Frissítse az alkalmazást az adaptív streaming média lejátszásához az adaptív sávválasztás használatával.

  1. Frissítse a initializePlayer kódot a következő kóddal:

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(); }

Először hozzon létre egy DefaultTrackSelector-at, amely a médiaelemben a sávok kiválasztásáért felelős. Ezután mondd meg a trackSelector-nek, hogy csak szabványos vagy annál alacsonyabb felbontású zeneszámokat válasszon – ez egy jó módja annak, hogy a felhasználó adatait a minőség rovására kíméld. Végül adja át a trackSelector-jét az építőjének, hogy azt használja fel a SimpleExoPlayer példány építésénél.

Adaptív MediaItem építése

A DASH egy széles körben használt adaptív streaming formátum. A DASH tartalom streameléséhez a korábbiakhoz hasonlóan egy MediaItem létrehozására van szükség. Ezúttal azonban nem fromUri, hanem MediaItem.Builder-t kell használnunk.

Ez azért van, mert a fromUri a fájlkiterjesztést használja a mögöttes médiaformátum meghatározásához, a mi DASH URI-nk azonban nem rendelkezik fájlkiterjesztéssel, ezért a MediaItem létrehozásakor APPLICATION_MPD MIME-típust kell megadnunk.

  1. Az initializePlayer frissítése a következőképpen:

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. Indítsa újra az alkalmazást, és nézze meg az adaptív videostreaminget a DASH segítségével működés közben. Az ExoPlayerrel nagyon egyszerű!

Más adaptív streaming-formátumok

AHLS (MimeTypes.APPLICATION_M3U8) és a SmoothStreaming (MimeTypes.APPLICATION_SS) más gyakran használt adaptív streaming-formátumok, amelyeket az ExoPlayer is támogat. További információkat más adaptív médiaforrások felépítéséről az ExoPlayer demóalkalmazásban talál.

A korábbi lépésekben megtanulta, hogyan kell progresszív és adaptív médiafolyamokat streamelni. Az ExoPlayer rengeteg munkát végez a színfalak mögött, többek között a következőket:

  • Memória kiosztása
  • Konténerfájlok letöltése
  • Metaadatok kinyerése a konténerből
  • Adatok dekódolása
  • Videó, hang és szöveg megjelenítése a képernyőn és a hangszórókon

Néha hasznos tudni, mit csinál az ExoPlayer futásidőben, hogy megértsük és javítsuk a lejátszási élményt a felhasználók számára.

Elképzelhető például, hogy a lejátszási állapotváltozásokat a felhasználói felületen a következőkkel szeretné tükrözni:

  • Egy betöltési pörgettyű megjelenítése, amikor a lejátszó pufferelési állapotba kerül
  • Egy “watch next” opciókat tartalmazó overlay megjelenítése, amikor a zeneszám véget ért

Az ExoPlayer számos hallgatói felületet kínál, amelyek a hasznos események visszahívását biztosítják. A hallgatót arra használod, hogy naplózd, milyen állapotban van a lejátszó.

Hallgatás

  1. Kinyilváníts egy PlaybackStateListener típusú privát tagot a PlayerActivity-ben.
  2. Készíts egy TAG konstanst, amit később naplózásra használsz.

PlayerActivity.java

private PlaybackStateListener playbackStateListener;private static final String TAG = PlayerActivity.class.getName();
  1. Elhelyezze a playbackStateListener-t a onCreate elején (még nem fog lefordítani, de ezt hamarosan kijavítja).

PlayerActivity.java

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); playbackStateListener = new PlaybackStateListener();
  1. A Quick Fix segítségével automatikusan létrehozza a PlaybackStateListener belső osztályt.

b59ce69a22595ba7.png

Screenshot: Quick Fix menü a hiányzó osztály létrehozásához

  1. Implementálja a Player.EventListener interfészt. Ez arra szolgál, hogy tájékoztasson a lejátszó fontos eseményeiről, beleértve a hibákat és a lejátszási állapot változásait.
  2. A onPlaybackStateChanged felülírása a következő kód hozzáadásával:

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 a lejátszási állapot változásakor hívódik meg. Az új állapotot a playbackState paraméter adja meg.

A lejátszó a következő négy állapot valamelyikében lehet:

State

Description

ExoPlayer.STATE_IDLE

A lejátszó példányosításra került, de még nincs előkészítve.

ExoPlayer.STATE_BUFFERING

A játékos nem tud az aktuális pozícióból játszani, mert nem lett elegendő adat pufferelve.

ExoPlayer.STATE_READY

A játékos képes azonnal játszani az aktuális pozícióból. Ez azt jelenti, hogy a lejátszó automatikusan elkezdi lejátszani a médiát, ha a lejátszó playWhenReady tulajdonsága true. Ha ez false, akkor a lejátszó szünetel.

ExoPlayer.STATE_ENDED

A lejátszó befejezte a média lejátszását.

Regisztrálja a hallgatóját

Hogy a visszahívásai meghívódjanak, regisztrálnia kell a playbackStateListener-t a lejátszónál. Ezt a initializePlayer-ban tedd meg.

  1. Regisztráld a hallgatót a lejátszás előkészítése előtt.

PlayerActivity.java

private void initializePlayer() { if (player == null) { player.addListener(playbackStateListener); player.prepare();}

Még egyszer rendet kell tenned, hogy elkerüld a lejátszóból származó lógó hivatkozásokat, amelyek memóriaszivárgást okozhatnak.

  1. Távolítsa el a hallgatót a releasePlayer:

PlayerActivity.java

private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
  1. Nyissa meg a logcat-et és futtassa az alkalmazást.
  2. A felhasználói felület vezérlőelemeit használja a lejátszás keresésére, szüneteltetésére és folytatására. Látnia kell a lejátszás állapotának változását a naplókban.

Mélyebbre kell mennie

AzExoPlayer számos egyéb hallgatót kínál, amelyek hasznosak a felhasználó lejátszási élményének megértéséhez. Vannak audió és videó figyelők, valamint egy AnalyticsListener, amely az összes figyelő visszahívásait tartalmazza. A legfontosabb módszerek közül néhány a következő:

  • onRenderedFirstFrame a videó első képkockájának megjelenítésekor hívódik. Ezzel kiszámítható, hogy a felhasználónak mennyi időt kellett várnia, hogy értelmes tartalmat lásson a képernyőn.
  • onDroppedVideoFrames akkor hívódik, amikor a videó képkockái kiesnek. A kiesett képkockák azt jelzik, hogy a lejátszás akadozik, és a felhasználói élmény valószínűleg rossz lesz.
  • onAudioUnderrun akkor hívódik, ha a hang alá futott. Az alulmúlás hallható zavarokat okoz a hangban, és sokkal feltűnőbb, mint a kiesett videóképkockák.

AnalyticsListener a player-hez a addAnalyticsListener segítségével adható hozzá. A hang- és videohallgatókhoz is vannak megfelelő metódusok.

Gondolja át, hogy milyen események fontosak az alkalmazása és a felhasználók számára. További információért lásd: A lejátszó eseményeinek figyelése. Ennyit az eseményhallgatókról!

Eleddig az ExoPlayer PlayerControlView-t használtad a lejátszásvezérlő megjelenítésére a felhasználó számára.

bcfe17eebcad9e13.png

Képernyőkép: Alapértelmezett lejátszásvezérlő

Mi van akkor, ha meg szeretné változtatni ezeknek a vezérlőknek a funkcionalitását vagy megjelenését? Szerencsére ezek a vezérlők nagymértékben testreszabhatók.

Az első egyszerű testreszabás az, hogy egyáltalán nem használja a vezérlőt. Ezt könnyen megtehetjük a activity_player.xml elemen belüli PlayerView elem use_controller attribútumának használatával.

  1. A use_controller false értékre állítva a vezérlő nem jelenik meg többé:

activity_player.xml

<com.google.android.exoplayer2.ui.PlayerView app:use_controller="false"/>
  1. Adja hozzá a következő névteret a FrameLayout-hez:

activity_player.xml

<FrameLayout xmlns:app="http://schemas.android.com/apk/res-auto">

Kipróbálja most.

A viselkedés testreszabása

PlayerControlView több attribútummal rendelkezik, amelyek befolyásolják a viselkedését. A show_timeout, fastforward_increment és rewind_increment segítségével testre szabhatod a vezérlő viselkedését.

  1. Távolítsd el a app:use_controller="false".
  2. Változtasd meg a játékos nézetet, hogy használja a show_timeout, fastforward_increment és 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"/>
  • A show_timeout érték megadja a PlayerView a késleltetést milliszekundumokban, mielőtt a vezérlő elrejtőzik a felhasználó utolsó interakciója után.
  • A fastforward_increment és rewind_increment értékek azt az időt mondják meg milliszekundumban, hogy a lejátszó előre vagy hátra ugorjon, amikor a felhasználó megérinti a gyors előre- vagy visszatekerés gombokat.

A PlayerControlView attribútumai programozottan is beállíthatók.

A megjelenés testreszabása

Hát, ez egy jó kezdet. De mi van akkor, ha azt szeretné, hogy a PlayerControlView másképp nézzen ki, vagy azt szeretné megváltoztatni, hogy mely gombok jelenjenek meg? A PlayerControlView megvalósítása nem feltételezi, hogy léteznek gombok, így könnyű eltávolítani őket, és újakat hozzáadni.

Nézd meg, hogyan tudod testreszabni a PlayerControlView-t.

  1. Hozzon létre egy új custom_player_control_view.xml elrendezési fájlt a player-lib/res/layout/ mappában.
  2. Az elrendezési mappa kontextusmenüjéből válassza az Új – Elrendezési erőforrásfájl parancsot, és nevezze el custom_player_control_view.xml.

ae1e3795726d4e4e.png

Screenshot: Létrejött a játékosvezérlő nézet elrendezési fájlja.

  1. Az eredeti elrendezési fájlt innen másolja át a custom_player_control_view.xml.
  2. Távolítsa el a ImageButton azonosítójú @id/exo_prev és @id/exo_next elemeket.

Az egyéni elrendezés használatához a activity_player.xml fájlban a PlayerView elem app:controller_layout_id attribútumát kell beállítania.

  1. Az egyéni fájl elrendezési azonosítóját használja, mint a következő kódrészletben:

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. Újra indítsa el az alkalmazást. A játékosvezérlő nézet már nem rendelkezik az előző és a következő gombokkal.

89e6535a22c8e321.png

Képernyőkép: Egyéni lejátszóvezérlő nézet előző és következő gombok nélkül

Az elrendezési fájlban bármilyen változtatást alkalmazhat. Alapértelmezés szerint az Android téma színei vannak kiválasztva. Ezt felülbírálhatja, hogy megfeleljen az alkalmazás dizájnjának.

  1. Adjunk hozzá egy android:tint attribútumot minden ImageButton elemhez:

custom_player_control_view.xml

<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
  1. Változtassa meg az összes android:textColor attribútumot, amelyet az egyéni fájlban talál: #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. Futtassa az alkalmazást. Most már gyönyörű, színes UI-komponensekkel rendelkezel!

e9835d65d6dd0634.png

Képernyőkép: Színezett gombok és szöveges nézet

Override the default style

Elkészítettél egy egyéni elrendezési fájlt, és a activity_player.xml-ben controller_layout_id segítségével hivatkoztál rá.

Egy másik megközelítés az alapértelmezett elrendezési fájl felülírása, amelyet PlayerControlView használ. A PlayerControlView forráskódjából kiderül, hogy a R.layout.exo_player_control_view állományt használja az elrendezéshez. Ha létrehozzuk a saját layout fájlunkat ugyanezzel a fájlnévvel, a PlayerControlView a mi fájlunkat használja helyette.

  1. Távolítsuk el az imént hozzáadott controller_layout_id attribútumot.
  2. Töröljük a custom_player_control_view.xml fájlt.

A PlayerView a activity_player.xml-ben most így kell kinéznie:

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. Készítsen egy exo_player_control_view.xml nevű fájlt a player-lib könyvtármodul res/layout mappájában.
  2. A exo_player_control_view.xml-be illessze be a következő kódot egy lejátszás gomb, egy szünet gomb és egy ImageView logóval:

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>

Ez azt mutatja, hogyan adhatunk ide saját elemeket, és hogyan keverhetjük őket a szabványos vezérlőelemekkel. A ExoPlayerView most már az egyéni vezérlőelemet használja, és a vezérlőelemmel való interakció során a megjelenítés és elrejtés minden logikája megmarad.

Gratulálunk! Sokat tanultál az ExoPlayer integrálásáról az alkalmazásodba.

Tudj meg többet

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.