ExoPlayer är ett bibliotek med öppen källkod för mediaspelare på Android, utvecklat av Google som ett alternativ till den inbyggda MediaPlayer. ExoPlayer erbjuder uppspelning av ljud och video i olika format, inklusive DASH, HLS, SmoothStreaming och vanliga mediafiler, via ett enhetligt API med stöd för adaptiv streaming. Enligt Google I/O (2024) används ExoPlayer i över 60 000 Android-appar, inklusive YouTube, Google TV och Netflix.
Huvudpunkter
ExoPlayer är ett bibliotek för multimediauppspelning på Android med öppen källkod (Apache 2.0), vars första version släpptes av Google 2014. Till skillnad från den inbyggda MediaPlayer, som är ett tunt lager ovanför systemets mediacodec (MediaCodec), är ExoPlayer helt implementerad på Java/Kotlin-nivå, vilket ger utvecklare full kontroll över varje steg i uppspelningen.
Arkitekturmässigt är ExoPlayer byggd på modulär princip: varje aspekt av uppspelningen implementeras av en separat komponent. Huvudmodulen (exoplayer-core) innehåller spelaren, renderare, spårväljare och buffert hantering. Ytterligare moduler (exoplayer-dash, exoplayer-hls, exoplayer-rtsp, exoplayer-smoothstreaming) lägger till stöd för respektive streamingprotokoll. Denna arkitektur gör att appar endast kan ansluta nödvändiga komponenter, vilket minimerar APK-storleken.
ExoPlayer 2 (nuvarande huvudversion) släpptes 2018 och medförde en genomgripande omarbetning av API:et: introduktion av Player Interface, stöd för Compose via AndroidX Media3, förbättrad felhantering och adaptiva algoritmer för spårval. Från och med version 2.19 (2024) blev ExoPlayer en del av AndroidX Media-biblioteket, vilket förenklade integration och uppdatering via den standardiserade Android-beroendehanteraren.
I hjärtat av ExoPlayer finns komponenten ExoPlayerImpl, som hanterar uppspelningens livscykel. Den innehåller MediaSource (mediakälla), TrackSelector (spårval), LoadControl (buffert hantering) och en lista med Renderer (renderare för video, ljud, undertexter och metadata). Varje komponent kan ersättas med en egen implementering via Builder eller fabriksmetoder.
För videorendering använder ExoPlayer SurfaceView, TextureView eller SphericalSurfaceView (för 360-gradersvideo). Det rekommenderade alternativet är SurfaceView eftersom det ger hårdvaruacceleration och minimal energiförbrukning. För Jetpack Compose tillhandahåller AndroidX Media3-biblioteket komponenten `AndroidView`, som omsluter SurfaceView, och experimentella `Media3Compose` med inbyggd Compose-integration.
ExoPlayer erbjuder en bred uppsättning funktioner som går utöver en vanlig mediaspelare. Huvudfunktionerna inkluderar stöd för alla populära streamingprotokoll, ett flexibelt DRM-system, adaptiv bitrate-växling (ABR) och analysverktyg för uppspelning.
| Funktion | Beskrivning | Modul |
|---|---|---|
| DASH | Adaptiv streaming enligt MPEG-standard | exoplayer-dash |
| HLS | HTTP Live Streaming från Apple | exoplayer-hls |
| SmoothStreaming | Adaptiv streaming från Microsoft | exoplayer-smoothstreaming |
| RTSP | Real-Time Streaming Protocol för live | exoplayer-rtsp |
| Widevine | DRM-skydd av innehåll | exoplayer-drm |
| Concatenation | Sammanslagning av flera mediafiler | exoplayer-core |
| Ads | IMA SDK-integration för annonser | exoplayer-ima |
ABR (Adaptive Bitrate) i ExoPlayer är implementerad via gränssnittet AdaptiveTrackSelection. Som standard används AdaptiveTrackSelectionFactory, som skapar DefaultAdaptiveTrackSelection — en balanserad algoritm som tar hänsyn till nätverksbandbredd och buffertstorlek. För specifika scenarier kan alternativa implementeringar anslutas: BOLA (minimering av växlingar), RandomAdaptiveTrackSelection (testning) eller en egen implementering via gränssnittet TrackSelection.
BandwidthMeter är en annan nyckelkomponent som ansvarar för att mäta nätverksbandbredd. Som standard används DefaultBandwidthMeter, som samlar in statistik från alla HTTP-förfrågningar från spelaren. Utvecklaren kan utöka den för att ta hänsyn till ytterligare faktorer: nätverkstyp (Wi-Fi, 4G, 5G), signal från mobiltorn eller trafikkostnad för användaren.
ExoPlayer stöder Widevine (L1, L3), PlayReady och ClearKey DRM. Licensanskaffning konfigureras via DrmSessionManager, som interagerar med licensservern. För premiumvideo (4K HDR) krävs hårdvarustöd för Widevine L1, vilket ger skydd på chipt nivå och förhindrar skärminsamling. Valet av DRM-system beror på målplattformen: Widevine används på Android och Chromecast, PlayReady på Xbox och Windows, FairPlay på iOS och Apple TV. ExoPlayer bestämmer automatiskt tillgängligt DRM-system baserat på MPD-filen och kräver ingen manuell konfiguration för grundläggande scenarier.
Anslutning av ExoPlayer till ett Android-projekt görs via Gradle-beroenden. Från och med version 2.19 är ExoPlayer en del av AndroidX Media (androidx.media3), vilket säkerställer kompatibilitet med Jetpack Compose och andra AndroidX-komponenter. Låt oss titta på steg-för-steg-integration i Kotlin.
Lägg till ExoPlayer-moduler i filen build.gradle (Module). Minimisatsen inkluderar core, ui och modulen för det erforderliga streamingprotokollet. För uppspelning av DASH-innehåll krävs exoplayer-dash, för HLS — exoplayer-hls.
dependencies {
implementation "androidx.media3:media3-exoplayer:1.5.0"
implementation "androidx.media3:media3-ui:1.5.0"
implementation "androidx.media3:media3-exoplayer-dash:1.5.0"
implementation "androidx.media3:media3-exoplayer-hls:1.5.0"
}
Skapa och konfigurera spelaren i Activity eller Fragment. ExoPlayer använder PlayerView (eller StyledPlayerView för anpassning) för att visa video och inbyggda kontroller. Minimikonfigurationen inkluderar att skapa spelaren via ExoPlayer.Builder och skicka en MediaItem med källans URI.
class PlayerActivity : AppCompatActivity() {
private var player: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
player = ExoPlayer.Builder(this).build()
val playerView = findViewById<StyledPlayerView>(R.id.playerView)
playerView.player = player
val mediaItem = MediaItem
.Builder()
.setUri("https://example.com/video.mp4")
.build()
player?.setMediaItem(mediaItem)
player?.prepare()
}
override fun onDestroy() {
player?.release()
super.onDestroy()
}
}
För produktionsappar är hantering av möjliga uppspelningsfel nödvändig: nätverksfel, ej stödda format, DRM-licensfel. ExoPlayer tillhandahåller gränssnittet Player.Listener med metoderna onPlayerError, onPlaybackStateChanged och onPlayWhenReadyChanged. Det rekommenderas att visa informativa felmeddelanden med möjlighet att försöka igen.
Valet mellan ExoPlayer och den inbyggda MediaPlayer är en vanlig fråga vid utveckling av Android-appar. MediaPlayer har varit en del av Android SDK sedan version 1.0, medan ExoPlayer är ett bibliotek som kräver anslutning via Gradle. Låt oss titta på deras skillnader baserat på viktiga kriterier.
| Kriterium | ExoPlayer | MediaPlayer |
|---|---|---|
| Arkitektur | Modulär, helt i Java/Kotlin | Lager ovanför systemets C++-komponenter |
| Streaming | DASH, HLS, SmoothStreaming, RTSP | Endast lokala filer och HLS (Android 9+) |
| Anpassning | Fullständig (varje komponent utbytbar) | Minimal (endast parametrar) |
| Uppdateringar | Via Google Play eller APK (oberoende av OS) | Endast via Android-uppdatering (OTA) |
| APK-storlek | +1-3 MB (beroende på moduler) | 0 (del av systemet) |
| Min SDK | API 16+ (Android 4.1) | API 1+ |
| DRM | Widevine, PlayReady, ClearKey | Widevine (begränsat) |
ExoPlayer vinner i scenarier som kräver streaming (DASH, HLS), UI-anpassning, DRM-stöd och oberoende av Android-version. MediaPlayer är lämplig för enkla appar som spelar upp lokala mediafiler, där APK-storleken är kritisk och det inte finns några krav på adaptiv streaming. För moderna appar med innehåll från nätet är ExoPlayer det självklara valet.
Undantag — appar med minimal SDK lägre än API 16 (Android 4.1), som praktiskt taget inte längre finns på marknaden. För alla appar med targetSdk 33+ och minimal SDK 21+ är ExoPlayer inte bara att föredra, utan nödvändig för stöd av moderna format som AV1 och Dolby Vision via lämpliga tillägg.
För produktionsappar kräver grundintegrationen av ExoPlayer ofta ytterligare konfiguration: cachehantering, optimering av buffring för mobila nätverk, integration med analysverktyg och anpassning av ljudspårsval. Låt oss titta på avancerade användningsscenarier.
CacheDataSourceFactory gör det möjligt att cachelagra nedladdade segment i lokal lagring, vilket sparar trafik vid upprepad visning och möjliggör offlineuppspelning. ExoPlayer använder SimpleCache från biblioteket exoplayer-cas — filcachelagring med stöd för LRU-utrymning och storleksbegränsningar.
val cache = SimpleCache(
cacheDir,
LeastRecentlyUsedCacheEvictor(50 * 1024 * 1024),
AppDatabaseProvider(this)
)
val cacheDataSourceFactory = CacheDataSource
.Factory()
.setCache(cache)
val player = ExoPlayer.Builder(this)
.setMediaSourceFactory(
DefaultMediaSourceFactory(cacheDataSourceFactory)
)
.build()
I mobila appar är hantering av växling mellan Wi-Fi och mobilnät avgörande. ExoPlayer tillhandahåller ConnectivityManager för att övervaka nätverksstatus. Vid förlust av anslutning rekommenderas att inte stoppa spelaren, utan att övergå till PAUSED-tillstånd med bibehållen position. Efter återställning av anslutningen, återuppta uppspelningen med omladdning av segment.
Med lanseringen av AndroidX Media3 fick biblioteket experimentellt stöd för Jetpack Compose. Komponenten `AndroidView` omsluter SurfaceView eller PlayerView och säkerställer kompatibilitet med Compose-hierarkin. För djupare integration används biblioteket `androidx.media3:media3-ui-compose`, som tillhandahåller Compose-kompatibla spelarkontroller.
@Composable
fun VideoPlayer(uri: String) {
val context = LocalContext.current
val player = remember {
ExoPlayer.Builder(context).build()
.also { it.setMediaItem(MediaItem.fromUri(uri)) }
}
DisposableEffect(key = null) {
player.prepare()
onDispose { player.release() }
}
AndroidView(
factory = { StyledPlayerView(context).also { it.player = player } }
)
}
Vanliga frågor
ExoPlayer stöder Android API 16+ (Android 4.1 Jelly Bean). För DASH och HLS med fMP4-segment rekommenderas dock API 21+ (Android 5.0 Lollipop). DRM-moduler (Widevine) kräver API 19+, och hårdvaruavkodning av HEVC är tillgänglig från och med API 21.
Ja, ExoPlayer är utmärkt för ljud. För uppspelning av endast ljud krävs ingen SurfaceView eller PlayerView. ExoPlayer väljer automatiskt en ljudrenderare och fungerar i bakgrunden. För bakgrundsuppspelning rekommenderas att använda MediaSessionService för integration med systemkontroller.
TrackSelector i ExoPlayer hanterar val av ljudspår. För att växla, använd player.getCurrentTracks().groups och player.setTrackSelectionParameters() med angivelse av önskat ljudspråk. För DASH- och HLS-strömmar med flera ljudspår sker växling utan avbrott i uppspelningen.
Ja, ExoPlayer stöder inbyggda (i MP4-, WebM-container) och externa undertexter i formaten TTML, SRT, VTT och CEA-608. För externa undertexter används SingleSampleMediaSource eller MergingMediaSource för att kombinera med videoströmmen. Visning av stiliserade undertexter konfigureras via CaptionStyleCompat.
För låglatens streaming, konfigurera LoadControl med mindre målvärden för buffert: använd DefaultLoadControl.Builder().setTargetBufferBytes(1024 * 512).setBufferDurationsMs(500, 2000, 500, 1000) för HLS LL och DASH LL. Ställ även in minPlaybackSpeed = 1.02 för accelererad buffertfyllning vid eftersläpning från livesändningen.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också