Reproduzindo áudio e vídeo
Reprodução simples de mídia no Android.
Reproduzindo áudio e vídeo é uma aula grátis de Android Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Android Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Android Academy inclui 4 aulas no total.
Além das imagens: reprodução de mídia
O Coil exibe imagens muito bem, mas os aplicativos também reproduzem som e vídeo: um toque de notificação, um podcast, um clipe em segundo plano ou um feed de vídeos. O Android tem APIs específicas para mídia.
A biblioteca moderna recomendada é o Media3 (ExoPlayer). Ela lida com transmissão, formatos, armazenamento temporário e controles de reprodução muito melhor do que o antigo MediaPlayer. Nesta lição, você reproduzirá áudio e vídeo simples em um aplicativo Compose.
Adicionando dependências do Media3
O Media3 é dividido em módulos. Para a maioria dos aplicativos, você precisará de media3-exoplayer (o mecanismo do player) e media3-ui (controles de player prontos). Para vídeos em Compose, você também pode usar PlayerView por meio de AndroidView.
// build.gradle.kts (module level)
dependencies {
implementation("androidx.media3:media3-exoplayer:1.5.0")
implementation("androidx.media3:media3-ui:1.5.0")
}Criando um ExoPlayer
Um ExoPlayer é criado a partir de um Context. Você fornece um MediaItem (uma URL ou um arquivo local), chama prepare() e inicia a reprodução. Ele executa suas próprias threads, portanto não bloqueia a interface.
É importante lembrar que um player mantém recursos do sistema e precisa ser liberado; falaremos mais sobre isso em breve.
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
}Reproduzindo áudio
Para uma reprodução somente de áudio, a configuração é idêntica; basta apontar o MediaItem para uma URL de áudio (mp3, aac etc.). Não há uma visualização para exibir, então você controla tudo pelo objeto do player: play(), pause(), seekTo().
Isso é suficiente para criar um player de podcasts ou músicas.
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()
}Mantendo o player na memória no Compose
No Compose, você deve criar o player uma vez e mantê-lo entre as recomposições. Use remember para que um novo player não seja criado a cada recomposição.
Combine isso com uma limpeza adequada (na próxima cena) para não deixar recursos vazando.
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()
}
}
}Liberando o player
Um player mantém codecs, buffers e o foco de áudio ativos. Se você se esquecer de liberá-lo, haverá vazamento de memória e ele poderá continuar reproduzindo depois que a tela desaparecer. No Compose, DisposableEffect executa a limpeza quando o composable deixa a composição.
Sempre chame player.release() nesse ponto.
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
}Exibindo vídeo com PlayerView
O Media3 fornece um PlayerView pronto com controles. O Compose não tem um composable nativo para vídeo, então você incorpora a View usando AndroidView e associa o player.
Isso oferece reprodução, pausa, uma barra de busca e tela cheia sem nenhum trabalho adicional.
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
)
}Uma tela de vídeo completa
Vamos reunir tudo: crie o player, mantenha-o na memória, associe-o a um PlayerView e libere-o ao descartá-lo. Esta é uma tela de vídeo independente que você pode reutilizar.
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)
)
}Acompanhando o estado da reprodução
Para atualizar sua interface (um ícone de reprodução/pausa ou uma barra de progresso), escute o player com um Player.Listener. Ele informa mudanças de estado, como armazenamento temporário, pronto e encerrado, além de indicar se a reprodução está ativa.
Adicione o listener quando a tela aparecer e remova-o ao descartá-la.
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
}Pausando quando o aplicativo vai para segundo plano
Para vídeos incorporados (não um aplicativo de música), normalmente você deseja pausar quando o usuário sair da tela e retomar quando ele voltar. É possível associar a reprodução ao ciclo de vida do Compose observando o Lifecycle e pausando em ON_PAUSE.
Isso evita reproduzir um vídeo que o usuário não pode ver e economiza bateria.
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) }
}
}Áudio em segundo plano com MediaSession
Para áudios que devem continuar sendo reproduzidos quando o aplicativo estiver em segundo plano (músicas e podcasts), envolva a reprodução em um MediaSessionService. Isso integra o player aos controles do sistema, à tela de bloqueio e aos botões do Bluetooth.
É uma solução mais complexa, mas a ideia central é expor seu player por meio de uma 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()
}
}Verificação rápida
Em uma tela Compose que mantém um ExoPlayer, qual API do Compose você deve usar para liberar o player quando a tela deixar a composição?
Recapitulação
Você adicionou reprodução de áudio e vídeo:
- Use o Media3 ExoPlayer, a substituição moderna do MediaPlayer.
- Crie um player, defina um
MediaItem, chameprepare()e depoisplay(). - No Compose, mantenha o player com
remembere libere-o emDisposableEffect, dentro deonDispose. - Exiba vídeos incorporando
PlayerViewcomAndroidView. - Acompanhe o estado com um
Player.Listener; use umMediaSessionServicepara áudio em segundo plano.
Isso conclui o curso Imagens e carregamento de mídia com Coil. Agora você pode carregar imagens suavemente e reproduzir mídia da maneira moderna do Android.
Perguntas Frequentes
A aula “Reproduzindo áudio e vídeo” é grátis?
Sim — o texto completo de “Reproduzindo áudio e vídeo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Android Academy, atualize para CoddyKit PRO. O curso de Android Academy inclui 4 aulas no total.
O que vou aprender em “Reproduzindo áudio e vídeo”?
Reprodução simples de mídia no Android. Você pratica Android Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Android Academy?
Nenhuma experiência prévia é necessária. Android Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Reproduzindo áudio e vídeo”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Android Academy?
Sim. Cada aula de Android Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Carregando imagens com Coil
- Marcadores e estados de erro
- Cache e desempenho
- Reproduzindo áudio e vídeo