Android Academy · Lezione

Riprodurre audio e video

Riproduzione multimediale di base in Android

Lezione 4 di 413 passaggi

Riprodurre audio e video è una lezione Android Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Android Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Android Academy include 4 lezioni in totale.

Oltre le immagini: riproduzione multimediale

Coil mostra le immagini in modo eccellente, ma le app riproducono anche audio e video: il suono di una notifica, un podcast, un clip in background o un feed video. Android offre API dedicate per i contenuti multimediali.

La libreria moderna consigliata è Media3 (ExoPlayer). Gestisce streaming, formati, buffering e controlli di riproduzione molto meglio del vecchio MediaPlayer. In questa lezione riprodurrà audio e video semplici in un'app Compose.

Aggiungere le dipendenze di Media3

Media3 è suddiviso in moduli. Per la maggior parte delle app servono media3-exoplayer (il motore del player) e media3-ui (viste del player già pronte). Per i video in Compose può anche utilizzare PlayerView tramite AndroidView.

// build.gradle.kts (module level)
dependencies {
    implementation("androidx.media3:media3-exoplayer:1.5.0")
    implementation("androidx.media3:media3-ui:1.5.0")
}

Creare un ExoPlayer

Un ExoPlayer viene creato a partire da un Context. Gli si fornisce un MediaItem (un URL o un file locale), si chiama prepare() e si avvia la riproduzione. Il player utilizza thread propri, quindi non blocca l'interfaccia utente.

È fondamentale ricordare che un player mantiene risorse di sistema e deve essere rilasciato; lo vedremo tra poco.

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
}

Riprodurre audio

Per la riproduzione del solo audio la configurazione è identica: basta indicare nel MediaItem un URL audio (mp3, aac ecc.). Non c'è alcuna vista da mostrare, quindi lo si controlla tramite l'oggetto player: play(), pause(), seekTo().

Questo è sufficiente per creare un player per podcast o musica.

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()
}

Ricordare il player in Compose

In Compose dovrebbe creare il player una sola volta e conservarlo tra le ricomposizioni. Utilizzi remember per evitare di creare un nuovo player a ogni ricomposizione.

Abbini questa soluzione a una corretta pulizia delle risorse (nella scena successiva) per evitare perdite di risorse.

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()
        }
    }
}

Rilasciare il player

Un player mantiene attivi codec, buffer e focus audio. Se dimentica di rilasciarlo, causa una perdita di memoria e potrebbe continuare a riprodurre contenuti anche dopo la chiusura della schermata. In Compose, DisposableEffect esegue la pulizia quando il composable esce dalla composizione.

Chiami sempre player.release() in quel punto.

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
}

Mostrare video con PlayerView

Media3 fornisce un PlayerView già pronto, con i controlli. Compose non dispone di un composable video nativo, quindi incorpori la View utilizzando AndroidView e colleghi il player.

In questo modo ottiene gratuitamente riproduzione/pausa, una barra di ricerca e la modalità a schermo intero.

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
    )
}

Una schermata video completa

Uniamo tutti gli elementi: crei il player, lo memorizzi, lo colleghi a un PlayerView e lo rilasci al momento della distruzione. Questa è una schermata video autonoma che può riutilizzare.

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)
    )
}

Monitorare lo stato della riproduzione

Per aggiornare l'interfaccia (un'icona di riproduzione/pausa o una barra di avanzamento), ascolti il player con un Player.Listener. Questo segnala cambiamenti di stato come buffering, pronto e terminato, oltre a indicare se la riproduzione è attiva.

Aggiunga il listener quando la schermata viene visualizzata e lo rimuova alla sua distruzione.

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
}

Mettere in pausa quando l'app passa in background

Per i video incorporati (non per un'app musicale), di solito si desidera mettere in pausa la riproduzione quando l'utente lascia la schermata e riprenderla quando torna. Può collegare la riproduzione al ciclo di vita di Compose osservando il Lifecycle e mettendo in pausa su ON_PAUSE.

In questo modo evita di riprodurre video che l'utente non può vedere e risparmia batteria.

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) }
    }
}

Audio in background con MediaSession

Per l'audio che deve continuare a essere riprodotto quando l'app passa in background (musica, podcast), racchiuda la riproduzione in un MediaSessionService. Questo si integra con i controlli di sistema, la schermata di blocco e i pulsanti Bluetooth.

È più complesso, ma l'idea fondamentale è esporre il player tramite una 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 rapida

In una schermata Compose che contiene un ExoPlayer, quale API di Compose dovrebbe utilizzare per rilasciare il player quando la schermata esce dalla composizione?

Riepilogo

Ha aggiunto la riproduzione audio e video:

  • Utilizzi Media3 ExoPlayer, il moderno sostituto di MediaPlayer.
  • Crei un player, imposti un MediaItem, chiami prepare() e poi play().
  • In Compose, memorizzi il player con remember e lo rilasci in onDispose di DisposableEffect.
  • Mostri i video incorporando PlayerView con AndroidView.
  • Monitori lo stato con un Player.Listener; utilizzi MediaSessionService per l'audio in background.

Ha completato il corso Images & Media Loading with Coil. Ora può caricare le immagini in modo fluido e riprodurre contenuti multimediali secondo l'approccio moderno di Android.

Gratis per iniziare

Impara Kotlin con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
36
Lezioni
152

Domande Frequenti

La lezione «Riprodurre audio e video» è gratuita?

Sì — il testo completo di «Riprodurre audio e video» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Android Academy, passa a CoddyKit PRO. Il corso Android Academy include 4 lezioni in totale.

Cosa imparerò in «Riprodurre audio e video»?

Riproduzione multimediale di base in Android Eserciti Android Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Android Academy?

Non è richiesta alcuna esperienza precedente. Android Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Riprodurre audio e video»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Android Academy?

Sì. Ogni lezione Android Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Caricare immagini con Coil
  2. Placeholder e stati di errore
  3. Caching e prestazioni
  4. Riprodurre audio e video
← Torna a Android Academy