Odtwarzanie dźwięku i obrazu
Podstawy odtwarzania multimediów w Androidzie
Odtwarzanie dźwięku i obrazu to bezpłatna lekcja Android Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Android Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Android Academy zawiera 4 lekcji w sumie.
Poza obrazami: odtwarzanie multimediów
Coil świetnie wyświetla obrazy, ale aplikacje odtwarzają również dźwięk i wideo: dźwięk powiadomienia, podcast, klip w tle czy kanał wideo. Android udostępnia do obsługi multimediów wyspecjalizowane interfejsy API.
Obecnie zalecaną biblioteką jest Media3 (ExoPlayer). Obsługuje transmisję strumieniową, formaty, buforowanie i elementy sterujące odtwarzaniem znacznie lepiej niż starszy MediaPlayer. W tej lekcji odtworzą Państwo prosty dźwięk i wideo w aplikacji Compose.
Dodawanie zależności Media3
Media3 jest podzielone na moduły. W większości aplikacji potrzebne są media3-exoplayer (silnik odtwarzacza) oraz media3-ui (gotowe widoki odtwarzacza). W przypadku wideo w Compose można także użyć PlayerView za pośrednictwem AndroidView.
// build.gradle.kts (module level)
dependencies {
implementation("androidx.media3:media3-exoplayer:1.5.0")
implementation("androidx.media3:media3-ui:1.5.0")
}Tworzenie ExoPlayer
Obiekt ExoPlayer tworzy się na podstawie Context. Należy przekazać mu MediaItem (adres URL lub plik lokalny), wywołać prepare(), a następnie rozpocząć odtwarzanie. Odtwarzacz działa we własnych wątkach, więc nie blokuje interfejsu użytkownika.
Co ważne, odtwarzacz zajmuje zasoby systemowe i trzeba go zwolnić — więcej informacji już wkrótce.
import android.content.Context
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
fun createPlayer(context: Context, url: String): ExoPlayer {
val player = ExoPlayer.Builder(context).build()
player.setMediaItem(MediaItem.fromUri(url))
player.prepare()
player.playWhenReady = true
return player
}Odtwarzanie dźwięku
W przypadku odtwarzania wyłącznie dźwięku konfiguracja jest identyczna — wystarczy wskazać w MediaItem adres URL pliku audio (mp3, aac itd.). Nie ma widoku do wyświetlenia, więc odtwarzaniem steruje się za pomocą obiektu odtwarzacza: play(), pause(), seekTo().
To wystarczy, aby zbudować odtwarzacz podcastów lub muzyki.
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
fun playPodcast(player: ExoPlayer, audioUrl: String) {
player.setMediaItem(MediaItem.fromUri(audioUrl))
player.prepare()
player.play()
}
fun togglePause(player: ExoPlayer) {
if (player.isPlaying) player.pause() else player.play()
}Zapamiętywanie odtwarzacza w Compose
W Compose należy utworzyć odtwarzacz tylko raz i zachować go między rekompozycjami. Należy użyć remember, aby nowy odtwarzacz nie był tworzony przy każdej rekompozycji.
Należy połączyć to z prawidłowym czyszczeniem zasobów (w następnej scenie), aby uniknąć wycieków.
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
@Composable
fun rememberPlayer(url: String): ExoPlayer {
val context = LocalContext.current
return remember {
ExoPlayer.Builder(context).build().apply {
setMediaItem(MediaItem.fromUri(url))
prepare()
}
}
}Zwalnianie odtwarzacza
Odtwarzacz utrzymuje aktywne kodeki, bufory i fokus audio. Jeśli zapomną Państwo go zwolnić, dojdzie do wycieku pamięci, a odtwarzanie może trwać po zamknięciu ekranu. W Compose DisposableEffect wykonuje operacje porządkowe, gdy composable opuszcza kompozycję.
W tym miejscu zawsze należy wywołać player.release().
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.media3.exoplayer.ExoPlayer
@Composable
fun ManagedPlayer(player: ExoPlayer) {
DisposableEffect(player) {
onDispose {
player.release()
}
}
// ... use player here
}Wyświetlanie wideo za pomocą PlayerView
Media3 udostępnia gotowy PlayerView z elementami sterującymi. Compose nie ma natywnego composable do wideo, dlatego widok należy osadzić za pomocą AndroidView i podłączyć do niego odtwarzacz.
Zapewnia to bez dodatkowej pracy przyciski odtwarzania i pauzy, pasek przewijania oraz tryb pełnoekranowy.
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
@Composable
fun VideoPlayer(player: ExoPlayer, modifier: Modifier = Modifier) {
AndroidView(
factory = { context ->
PlayerView(context).apply {
this.player = player
}
},
modifier = modifier
)
}Kompletny ekran wideo
Połączmy teraz wszystkie elementy: utwórzmy odtwarzacz, zapamiętajmy go, podłączmy do PlayerView i zwolnijmy podczas usuwania. Otrzymamy samodzielny ekran wideo, który można ponownie wykorzystać.
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
@Composable
fun VideoScreen(videoUrl: String) {
val context = LocalContext.current
val player = remember {
ExoPlayer.Builder(context).build().apply {
setMediaItem(MediaItem.fromUri(videoUrl))
prepare()
playWhenReady = true
}
}
DisposableEffect(Unit) { onDispose { player.release() } }
AndroidView(
factory = { PlayerView(it).apply { this.player = player } },
modifier = Modifier.fillMaxWidth().height(220.dp)
)
}Śledzenie stanu odtwarzania
Aby aktualizować interfejs użytkownika (ikonę odtwarzania/pauzy lub pasek postępu), należy nasłuchiwać odtwarzacza za pomocą Player.Listener. Zgłasza on zmiany stanu, takie jak buforowanie, gotowość i zakończenie, a także informuje, czy odtwarzanie jest aktywne.
Listener należy dodać, gdy ekran się pojawia, i usunąć podczas jego usuwania.
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
fun observe(player: ExoPlayer, onPlaying: (Boolean) -> Unit): Player.Listener {
val listener = object : Player.Listener {
override fun onIsPlayingChanged(isPlaying: Boolean) {
onPlaying(isPlaying)
}
override fun onPlaybackStateChanged(state: Int) {
when (state) {
Player.STATE_BUFFERING -> { /* show spinner */ }
Player.STATE_READY -> { /* ready */ }
Player.STATE_ENDED -> { /* finished */ }
}
}
}
player.addListener(listener)
return listener
}Wstrzymywanie po przejściu aplikacji do tła
W przypadku wideo osadzonego w interfejsie (a nie aplikacji muzycznej) zwykle należy wstrzymać odtwarzanie, gdy użytkownik opuszcza ekran, i wznowić je po powrocie. Można powiązać odtwarzanie z cyklem życia Compose, obserwując Lifecycle i wstrzymując odtwarzanie przy ON_PAUSE.
Zapobiega to odtwarzaniu wideo, którego użytkownik nie może oglądać, i oszczędza baterię.
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.media3.exoplayer.ExoPlayer
@Composable
fun PauseWithLifecycle(player: ExoPlayer) {
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_PAUSE -> player.pause()
Lifecycle.Event.ON_RESUME -> player.play()
else -> {}
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }
}
}Dźwięk w tle z MediaSession
W przypadku dźwięku, który powinien być odtwarzany po przejściu aplikacji do tła (muzyka, podcasty), należy umieścić odtwarzanie w MediaSessionService. Integruje to odtwarzanie z elementami sterującymi systemu, ekranem blokady i przyciskami Bluetooth.
Wymaga to nieco więcej pracy, ale główna idea polega na udostępnieniu odtwarzacza za pośrednictwem MediaSession.
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
class PlaybackService : MediaSessionService() {
private var session: MediaSession? = null
override fun onCreate() {
super.onCreate()
val player = ExoPlayer.Builder(this).build()
session = MediaSession.Builder(this, player).build()
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = session
override fun onDestroy() {
session?.run { player.release(); release() }
session = null
super.onDestroy()
}
}Szybkie sprawdzenie
Na ekranie Compose, który przechowuje obiekt ExoPlayer, którego API Compose należy użyć, aby zwolnić odtwarzacz, gdy ekran opuszcza kompozycję?
Podsumowanie
Dodali Państwo odtwarzanie dźwięku i wideo:
- Należy używać Media3 ExoPlayer, nowoczesnego następcy MediaPlayer.
- Należy utworzyć odtwarzacz, ustawić
MediaItem, wywołaćprepare(), a następnieplay(). - W Compose odtwarzacz należy zapamiętać za pomocą
rememberi zwolnić wonDisposeelementuDisposableEffect. - Wideo należy wyświetlać, osadzając
PlayerViewza pomocąAndroidView. - Stan należy śledzić za pomocą
Player.Listener, a do odtwarzania dźwięku w tle używaćMediaSessionService.
To kończy kurs Images & Media Loading with Coil. Potrafią już Państwo płynnie ładować obrazy i odtwarzać multimedia w nowoczesny sposób na Androidzie.
Ucz się Kotlin dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 36
- Lekcje
- 152
Często zadawane pytania
Czy lekcja „Odtwarzanie dźwięku i obrazu” jest bezpłatna?
Tak — pełny tekst „Odtwarzanie dźwięku i obrazu” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Android Academy, przejdź na CoddyKit PRO. Kurs Android Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Odtwarzanie dźwięku i obrazu”?
Podstawy odtwarzania multimediów w Androidzie Ćwiczysz Android Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Android Academy?
Nie wymagamy żadnego doświadczenia. Android Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Odtwarzanie dźwięku i obrazu”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Android Academy?
Tak. Każda lekcja Android Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Wczytywanie obrazów za pomocą Coil
- Elementy zastępcze i stany błędów
- Buforowanie i wydajność
- Odtwarzanie dźwięku i obrazu