Воспроизведение аудио и видео
Простое воспроизведение мультимедиа в Android
«Воспроизведение аудио и видео» — бесплатный урок Android Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.
За пределами изображений: воспроизведение медиа
Coil прекрасно отображает изображения, но приложения также воспроизводят звук и видео: сигнал уведомления, подкаст, фоновый ролик или ленту видео. В Android для работы с медиа предусмотрены специализированные API.
Современная рекомендуемая библиотека — Media3 (ExoPlayer). Она значительно лучше старого MediaPlayer справляется с потоковой передачей, форматами, буферизацией и управлением воспроизведением. В этом уроке вы научитесь воспроизводить простое аудио и видео в приложении Compose.
Добавление зависимостей Media3
Media3 разделена на модули. Для большинства приложений нужны media3-exoplayer (механизм воспроизведения) и media3-ui (готовые представления проигрывателя). Для видео в Compose также можно использовать PlayerView через AndroidView.
// build.gradle.kts (module level)
dependencies {
implementation("androidx.media3:media3-exoplayer:1.5.0")
implementation("androidx.media3:media3-ui:1.5.0")
}Создание ExoPlayer
ExoPlayer создаётся на основе Context. Ему передаётся MediaItem (URL или локальный файл), затем вызывается prepare() и запускается воспроизведение. Проигрыватель работает в собственных потоках, поэтому интерфейс не блокируется.
Важно: проигрыватель использует системные ресурсы, поэтому его нужно освободить. Подробнее об этом — далее.
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
}Воспроизведение аудио
Для воспроизведения только аудио настройка такая же: достаточно указать в MediaItem URL аудиофайла (mp3, aac и т. д.). Представление для отображения не требуется, поэтому управление выполняется через объект проигрывателя: play(), pause(), seekTo().
Этого достаточно, чтобы создать проигрыватель подкастов или музыки.
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()
}Сохранение проигрывателя в Compose
В Compose следует создать проигрыватель один раз и сохранять его между рекомпозициями. Используйте remember, чтобы новый проигрыватель не создавался при каждой рекомпозиции.
Сочетайте это с правильной очисткой ресурсов (в следующем эпизоде), чтобы не допустить утечек.
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()
}
}
}Освобождение проигрывателя
Проигрыватель удерживает кодеки, буферы и аудиофокус. Если забыть освободить его, произойдёт утечка памяти, а воспроизведение может продолжиться после закрытия экрана. В Compose DisposableEffect выполняет очистку, когда компонуемый элемент покидает композицию.
Всегда вызывайте там 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
}Отображение видео с помощью PlayerView
Media3 предоставляет готовый PlayerView с элементами управления. В Compose нет встроенного компонуемого элемента для видео, поэтому представление встраивается с помощью AndroidView, после чего к нему подключается проигрыватель.
Так вы сразу получаете кнопки воспроизведения и паузы, шкалу перемотки и полноэкранный режим.
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
)
}Полный экран видео
Объединим всё вместе: создадим проигрыватель, сохраним его, подключим к PlayerView и освободим при уничтожении. Это автономный экран видео, который можно повторно использовать.
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)
)
}Отслеживание состояния воспроизведения
Чтобы обновлять интерфейс (значок воспроизведения или паузы, индикатор выполнения), отслеживайте проигрыватель с помощью Player.Listener. Он сообщает об изменениях состояния, например о буферизации, готовности и завершении, а также о том, активно ли воспроизведение.
Добавляйте слушатель при появлении экрана и удаляйте его при очистке.
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
}Пауза при переходе приложения в фон
Для встроенного видео (не в музыкальном приложении) обычно нужно приостанавливать воспроизведение, когда пользователь покидает экран, и возобновлять его при возвращении. Можно связать воспроизведение с жизненным циклом Compose: наблюдать за Lifecycle и ставить воспроизведение на паузу при ON_PAUSE.
Это предотвращает воспроизведение видео, которое пользователь не видит, и экономит заряд батареи.
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) }
}
}Фоновое аудио с MediaSession
Если аудио должно продолжать воспроизводиться в фоне (музыка, подкасты), оберните воспроизведение в MediaSessionService. Это обеспечивает интеграцию с системными элементами управления, экраном блокировки и кнопками Bluetooth.
Решение сложнее, но основная идея заключается в предоставлении доступа к проигрывателю через 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()
}
}Быстрая проверка
На экране Compose, где хранится ExoPlayer, какой API Compose следует использовать, чтобы освободить проигрыватель, когда экран покидает композицию?
Итоги
Вы добавили воспроизведение аудио и видео:
- Используйте Media3 ExoPlayer — современную замену MediaPlayer.
- Создайте проигрыватель, задайте
MediaItem, вызовитеprepare(), а затемplay(). - В Compose сохраняйте проигрыватель с помощью
rememberи освобождайте его вonDisposeвнутриDisposableEffect. - Отображайте видео, встраивая
PlayerViewс помощьюAndroidView. - Отслеживайте состояние через
Player.Listener, а для фонового аудио используйтеMediaSessionService.
На этом завершается курс «Загрузка изображений и медиа с Coil». Теперь вы умеете плавно загружать изображения и воспроизводить медиа современным способом Android.
Часто задаваемые вопросы
Урок «Воспроизведение аудио и видео» бесплатный?
Да — полный текст урока «Воспроизведение аудио и видео» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.
Чему я научусь в уроке «Воспроизведение аудио и видео»?
Простое воспроизведение мультимедиа в Android Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Android Academy?
Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Воспроизведение аудио и видео»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Android Academy?
Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Загрузка изображений с Coil
- Заполнители и состояния ошибок
- Кэширование и производительность
- Воспроизведение аудио и видео