0Pricing
Android Academy · Aula

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, chame prepare() e depois play().
  • No Compose, mantenha o player com remember e libere-o em DisposableEffect, dentro de onDispose.
  • Exiba vídeos incorporando PlayerView com AndroidView.
  • Acompanhe o estado com um Player.Listener; use um MediaSessionService para á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

  1. Carregando imagens com Coil
  2. Marcadores e estados de erro
  3. Cache e desempenho
  4. Reproduzindo áudio e vídeo
← Voltar para Android Academy