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
- What you’ll do
- Mire lesz szüksége
- A kód beszerzése
- Könyvtárszerkezet
- Importálja a kezdeti projektet
- app/build.gradle
- app/build.gradle
- Az ExoPlayer függőség hozzáadása
- player-lib/build.gradle
- Add hozzá a PlayerView elemet
- activity_player.xml
- PlayerActivity.java
- ExoPlayer létrehozása
- PlayerActivity.java
- Médiaelem létrehozása
- PlayerActivity.java
- Az Activity életciklus szépen játszik
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Végső előkészítés
- PlayerActivity.java
- Audio lejátszása
- A tevékenység életciklusának tesztelése
- Videó lejátszása
- PlayerActivity.java
- PlayerActivity.java
- Adaptív sávválasztás
- PlayerActivity.java
- Adaptív MediaItem építése
- PlayerActivity.java
- Más adaptív streaming-formátumok
- Hallgatás
- PlayerActivity.java
- PlayerActivity.java
- PlayerActivity.java
- Regisztrálja a hallgatóját
- PlayerActivity.java
- PlayerActivity.java
- Mélyebbre kell mennie
- activity_player.xml
- activity_player.xml
- A viselkedés testreszabása
- activity_player.xml
- A megjelenés testreszabása
- activity_player.xml
- custom_player_control_view.xml
- custom_player_control_view.xml
- Override the default style
- activity_player.xml
- exo_player**_control_view.xml**
- Tudj meg többet
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
- Indítsa el az Android Studio-t.
- Válassza a Fájl > Új > Projekt importálása*.*
- Importálja a kezdeti projektet a
exoplayer-codelab-00
-ből.
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á.
- 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.
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.
- Nyissa meg a
player-lib
modulbuild.gradle
fájlját. - 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
- Nyisd meg az
player-lib
modulból aactivity_player.xml
layout resource fájlt. - Tegyük a kurzort a
FrameLayout
elembe. - Kezdjük el a
<PlayerView
beírását, és hagyjuk, hogy az Android Studio automatikusan kitöltse aPlayerView
elemet. - A
match_parent
-et használja awidth
és aheight
elemhez. - 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.
- A
PlayerActivity
-ben most meg kell találnod a videónézetet, hogy megfelelően beállíthasd az aktivitásonCreate
metódusában.
PlayerActivity.java
@Overrideprotected void onCreate(Bundle savedInstanceState) { playerView = findViewById(R.id.video_view);}
- Add hozzá a
playerView
tagmezőt aPlayerActivity
osztályodhoz. Győződjön meg róla, hogy a nézet típusaPlayerView
.
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
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.
- 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
.
- Az
PlayerActivity
megnyitásakor kattintson a Kód menü > Módszerek felülírása…. - Válassza ki a
onStart
,onResume
,onPause
ésonStop
módszereket. - Inicializálja a lejátszót a
onStart
vagyonResume
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.
- 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.
- Az erőforrásokat a
onPause
-ben és aonStop
-ban areleasePlayer
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.
- 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.
- 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 aplayWhenReady
eredetilegtrue
, 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 acurrentWindow
, mind aplaybackPosition
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.
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.
- Elindít egy másik alkalmazást, és ismét előtérbe helyezi az alkalmazást. A megfelelő pozícióban folytatódik?
- Á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?
- 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.
- Változtassa meg az URI-t a
initializePlayer
-banR.string.media_url_mp4
-re. - 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.
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.
- 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 és segítségével navigálhat a médiaelemek sorrendjében.
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.
- 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.
- 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);}
- 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
- Kinyilváníts egy
PlaybackStateListener
típusú privát tagot aPlayerActivity
-ben. - 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();
- Elhelyezze a
playbackStateListener
-t aonCreate
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();
- A Quick Fix segítségével automatikusan létrehozza a
PlaybackStateListener
belső osztályt.
Screenshot: Quick Fix menü a hiányzó osztály létrehozásához
- 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. - 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 |
|
A lejátszó példányosításra került, de még nincs előkészítve. |
|
A játékos nem tud az aktuális pozícióból játszani, mert nem lett elegendő adat pufferelve. |
|
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 |
|
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.
- 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.
- Távolítsa el a hallgatót a
releasePlayer
:
PlayerActivity.java
private void releasePlayer() { if (player != null) { player.removeListener(playbackStateListener); player.release(); player = null; }}
- Nyissa meg a logcat-et és futtassa az alkalmazást.
- 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.
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.
- 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"/>
- 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.
- Távolítsd el a
app:use_controller="false"
. - Változtasd meg a játékos nézetet, hogy használja a
show_timeout
,fastforward_increment
ésrewind_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 aPlayerView
a késleltetést milliszekundumokban, mielőtt a vezérlő elrejtőzik a felhasználó utolsó interakciója után. - A
fastforward_increment
ésrewind_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.
- Hozzon létre egy új
custom_player_control_view.xml
elrendezési fájlt aplayer-lib/res/layout/
mappában. - 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
.
Screenshot: Létrejött a játékosvezérlő nézet elrendezési fájlja.
- Az eredeti elrendezési fájlt innen másolja át a
custom_player_control_view.xml
. - 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.
- 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"/>
- Ú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.
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.
- Adjunk hozzá egy
android:tint
attribútumot mindenImageButton
elemhez:
custom_player_control_view.xml
<ImageButton android:id="@id/exo_rew" android:tint="#FF00A6FF" style="@style/ExoMediaButton.Rewind"/>
- 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"/>
- Futtassa az alkalmazást. Most már gyönyörű, színes UI-komponensekkel rendelkezel!
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.
- Távolítsuk el az imént hozzáadott
controller_layout_id
attribútumot. - 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"/>
- Készítsen egy
exo_player_control_view.xml
nevű fájlt aplayer-lib
könyvtármodulres/layout
mappájában. - A
exo_player_control_view.xml
-be illessze be a következő kódot egy lejátszás gomb, egy szünet gomb és egyImageView
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.