Guida completa a MediaPlayer in Android

Questa guida ti spiega cos’è MediaPlayer Android e come usarlo in Android Studio per riprodurre audio e video. Vedrai come inizializzare il player, quali sono i metodi più usati, come agganciarlo al ciclo di vita di Activity e Fragment, come gestire gli errori e come evitare memory leak.

MediaPlayer Android ciclo di vita: stati Idle, Initialized, Preparing, Prepared, Started, Paused, Stopped, End ed Error in Android Studio

Cos’è MediaPlayer Android

MediaPlayer Android è una classe del framework Android (pacchetto android.media, consulta la documentazione ufficiale) che serve per riprodurre contenuti multimediali: file audio, video e stream da rete. Gestisce decoder, buffering, sincronizzazione audio/video e stato della riproduzione, e ti offre un’API ad alto livello per controllare il playback.

In pratica, con MediaPlayer puoi:

  • Supporta file locali (memoria interna, external storage, raw/, assets/) e contenuti remoti via URL.
  • Puo’ riprodurre sia solo audio (ad esempio MP3) sia video (ad esempio MP4) associandolo a una SurfaceView o TextureView.
  • Ha uno stato interno (Idle, Initialized, Preparing, Prepared, Started, Paused, Stopped, End, Error) che deve essere rispettato.
  • Va sempre rilasciato con release() per evitare memory leak.

Inizializzare e usare MediaPlayer Android

Usare MediaPlayer in modo corretto richiede di seguire questo flusso:

  • Per prima cosa, crea un’istanza di MediaPlayer.
  • La sorgente dati va impostata con setDataSource(...) (file locale, URI, URL).
  • Il player va preparato con prepare() (sincrono) o prepareAsync() (asincrono).
  • Una volta pronto, avvia la riproduzione con start().
  • Pausa, stop e fine riproduzione vanno gestiti tramite i metodi appositi.
  • Al termine, le risorse vanno rilasciate con release() quando non servono più.

Esempio base (audio locale da risorsa raw/)

In questo esempio usi il metodo statico di comodo MediaPlayer.create(...), adatto a riprodurre file locali semplici:

public class MainActivity extends AppCompatActivity {

    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Inizializza da risorsa raw (es: res/raw/musica.mp3)
        mediaPlayer = MediaPlayer.create(this, R.raw.musica);

        // Avvia riproduzione
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

Versione Java equivalente:

public class MainActivity extends AppCompatActivity {

    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Inizializza da risorsa raw (es: res/raw/musica.mp3)
        mediaPlayer = MediaPlayer.create(this, R.raw.musica);

        // Avvia riproduzione
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

Con sorgenti più complesse (file da percorso, URL o stream) devi configurare MediaPlayer manualmente e impostare la sorgente con setDataSource().

Inizializzazione completa con setDataSource() e prepareAsync()

public class AudioPlayerActivity extends AppCompatActivity implements
        MediaPlayer.OnPreparedListener,
        MediaPlayer.OnCompletionListener,
        MediaPlayer.OnErrorListener {

    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_audio_player);

        // Esempio: URL remoto
        String audioUrl = "https://esempio.com/audio.mp3";

        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setOnCompletionListener(this);
        mediaPlayer.setOnErrorListener(this);

        try {
            mediaPlayer.setDataSource(audioUrl);
            mediaPlayer.prepareAsync(); // prepara in background
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        // Chiamato quando il player è pronto
        mediaPlayer.start();
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        // Riproduzione terminata
        Toast.makeText(this, "Riproduzione terminata", Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        // Gestisci errore
        Toast.makeText(this, "Errore di riproduzione", Toast.LENGTH_SHORT).show();
        return true; // true = errore gestito
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

Metodi principali di MediaPlayer Android

Questi sono i metodi più importanti che userai più spesso con MediaPlayer:

MetodoDescrizioneQuando usarlo
setDataSource(...)Imposta la sorgente dei dati multimediali (file, URI, URL, FileDescriptor).Sempre prima di preparare il player. Non disponibile se usi MediaPlayer.create.
prepare()Prepara la riproduzione in modo sincrono (bloccante).Solo per file locali piccoli e su thread in background.
prepareAsync()Prepara in modo asincrono, notificando tramite OnPreparedListener.Consigliato per la maggior parte dei casi (soprattutto da rete).
start()Avvia o riprende la riproduzione.Dopo onPrepared(), oppure per riprendere dopo una pausa.
pause()Mette in pausa la riproduzione mantenendo le risorse.Quando l’utente mette in pausa o l’attività va in background ma prevedi di riprendere.
stop()Ferma la riproduzione e mette il player in stato Stopped.Quando sai che non riprenderai immediatamente: dovrai poi richiamare prepare().
reset()Riporta il player allo stato Idle.Quando vuoi riutilizzare l’istanza con un’altra sorgente.
release()Rilascia tutte le risorse native e memoria associata.Sempre quando hai finito di usare il player (es. in onDestroy()).
seekTo(ms)Salta ad una posizione specifica (millisecondi).Per implementare lo scrub tramite una SeekBar.
setLooping(boolean)Imposta la riproduzione in loop.Per suoni di sottofondo, musiche di gioco, ecc.

Gestione del ciclo di vita di MediaPlayer Android

Gestire correttamente il ciclo di vita di MediaPlayer Android è fondamentale per evitare crash e sprechi di risorse.

  • In onCreate() crea e configura il MediaPlayer, ma non avviare subito la riproduzione se l’utente non ha ancora interagito.
  • Al ripristino dell’Activity (onStart() / onResume()), riprendi la riproduzione se era in corso prima di una pausa.
  • Quando l’app va in background, onPause() mette in pausa la riproduzione se il contenuto non deve continuare in background.
  • Con onStop() ferma o rilascia il player se l’attività non sarà più visibile.
  • Prima di distruggere l’Activity, onDestroy() deve chiamare sempre release() e azzerare il riferimento (mediaPlayer = null).
@Override
protected void onPause() {
    super.onPause();
    if (isFinishing()) {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    } else {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
        }
    }
}

Gestione degli stati di MediaPlayer Android Java (Idle, Initialized, Prepared, Started, Paused, Stopped, End)

Ogni istanza di MediaPlayer Android Java passa attraverso una serie di stati: Idle, Initialized, Preparing, Prepared, Started, Paused, Stopped, End ed Error. Conoscere questi stati è essenziale per riprodurre audio Android senza errori IllegalStateException e per capire quando è possibile chiamare ciascun metodo.

  • Idle: stato iniziale dopo il costruttore o dopo reset(). Si può chiamare solo setDataSource().
  • Initialized: dopo setDataSource(). Puoi chiamare prepare(), prepareAsync() o reset().
  • Preparing: mentre prepareAsync() è in corso. Non vanno chiamati start() o pause() prima di onPrepared().
  • Prepared: il media è pronto. Puoi chiamare start(), seekTo(), setLooping().
  • Started: l'audio o il video sta riproducendo. Sono ammessi pause(), seekTo(), stop(), release().
  • Paused: riproduzione in pausa, mantenendo le risorse. Puoi chiamare start(), stop(), seekTo(), release().
  • Stopped: riproduzione fermata. Devi richiamare prepare() o prepareAsync() prima di poter usare start() di nuovo.
  • End: dopo release(). Qualsiasi altro metodo (tranne release() stesso) genera eccezioni.
  • Error: stato non valido dopo un problema grave. Di solito è necessario chiamare reset() o creare una nuova istanza.

Esempio di gestione sicura degli stati per evitare chiamate non valide su MediaPlayer:

private void safeStart() {
    if (mediaPlayer == null) {
        return;
    }

    try {
        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }
    } catch (IllegalStateException e) {
        Log.e("MediaPlayer", "Chiamata start() in stato non valido", e);
        try {
            mediaPlayer.reset();
            // Reimposta la sorgente e richiama prepareAsync()
        } catch (IllegalStateException ignored) {
        }
    }
}

private void safeStopAndRelease() {
    if (mediaPlayer == null) {
        return;
    }

    try {
        mediaPlayer.stop(); // valido solo da Started, Paused, Preparing/Prepared (con cautela)
    } catch (IllegalStateException e) {
        Log.w("MediaPlayer", "stop() chiamato in stato errato", e);
    } finally {
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

Come usare MediaPlayer Android Java in background con un Service

Per continuare a riprodurre audio Android quando l'Activity viene chiusa o l'utente cambia app, puoi spostare la logica di MediaPlayer in un Service o in un ForegroundService. Di seguito un esempio Java semplificato di Service che riproduce un file audio da risorsa raw/.

public class BackgroundAudioService extends Service
        implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener {

    private MediaPlayer mediaPlayer;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer.create(this, R.raw.musica);
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setOnCompletionListener(this);
        }

        if (!mediaPlayer.isPlaying()) {
            mediaPlayer.start();
        }

        // START_STICKY: il Service viene ricreato dal sistema se necessario
        return START_STICKY;
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        // Opzionale: stop del servizio alla fine
        stopSelf();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Non supportiamo il binding in questo esempio
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            try {
                mediaPlayer.stop();
            } catch (IllegalStateException ignored) {
            } finally {
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    }
}

Per avviare la riproduzione in background dalla tua Activity:

Intent intent = new Intent(this, BackgroundAudioService.class);
startService(intent);

Per applicazioni di produzione, considera l'uso di un ForegroundService con notifica persistente e la classe MediaSessionCompat per controlli avanzati di riproduzione.

Riprodurre file audio con MediaPlayer Android

Audio da risorsa raw/

I file statici inclusi nell’app (cartella res/raw) si riproducono meglio con MediaPlayer.create(...) oppure setDataSource() con un AssetFileDescriptor.

AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.musica);
mediaPlayer = new MediaPlayer();
try {
    mediaPlayer.setDataSource(
        afd.getFileDescriptor(),
        afd.getStartOffset(),
        afd.getLength()
    );
    afd.close();
    mediaPlayer.prepare();
    mediaPlayer.start();
} catch (IOException e) {
    e.printStackTrace();
}

Audio da file locale

Quando il file è salvato nella memoria del dispositivo, è accessibile tramite percorso assoluto o Uri:

File file = new File(getFilesDir(), "musica.mp3");
Uri uri = FileProvider.getUriForFile(this, "com.example.app.fileprovider", file);

mediaPlayer = new MediaPlayer();
try {
    mediaPlayer.setDataSource(this, uri);
    mediaPlayer.prepare(); // o prepareAsync()
    mediaPlayer.start();
} catch (IOException e) {
    e.printStackTrace();
}

Audio da URL remoto

I contenuti caricati da rete richiedono sempre prepareAsync():

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
    mediaPlayer.setDataSource("https://esempio.com/stream.mp3");
} catch (IOException e) {
    e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
mediaPlayer.prepareAsync();

Come riprodurre un audio da URL remoto con MediaPlayer Android Java

Per riprodurre audio Android da un URL HTTP o HTTPS con MediaPlayer Android Java è consigliabile usare un thread in background o l'approccio asincrono con prepareAsync(). Nell'esempio seguente mostriamo un'Activity completa con pulsanti Play/Pause/Stop che riproduce un file MP3 remoto.

public class RemoteAudioActivity extends AppCompatActivity {

    private static final String AUDIO_URL = "https://www.example.com/audio/demo.mp3";

    private MediaPlayer mediaPlayer;
    private Button btnPlay;
    private Button btnPause;
    private Button btnStop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_remote_audio);

        btnPlay = findViewById(R.id.btnPlay);
        btnPause = findViewById(R.id.btnPause);
        btnStop = findViewById(R.id.btnStop);

        initMediaPlayer();

        btnPlay.setOnClickListener(v -> startPlayback());
        btnPause.setOnClickListener(v -> pausePlayback());
        btnStop.setOnClickListener(v -> stopPlayback());
    }

    private void initMediaPlayer() {
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

        mediaPlayer.setOnPreparedListener(mp -> {
            // Avvia automaticamente alla prima preparazione
            mp.start();
        });

        mediaPlayer.setOnCompletionListener(mp -> {
            Toast.makeText(this, "Riproduzione remota terminata", Toast.LENGTH_SHORT).show();
        });

        mediaPlayer.setOnErrorListener((mp, what, extra) -> {
            Toast.makeText(this, "Errore di riproduzione remota", Toast.LENGTH_SHORT).show();
            mp.reset();
            return true;
        });

        try {
            mediaPlayer.setDataSource(AUDIO_URL);
            mediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Impossibile caricare l'audio remoto", Toast.LENGTH_SHORT).show();
        }
    }

    private void startPlayback() {
        if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
            try {
                mediaPlayer.start();
            } catch (IllegalStateException e) {
                // Se il player non è pronto, lo re-inizializzi
                initMediaPlayer();
            }
        }
    }

    private void pausePlayback() {
        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
        }
    }

    private void stopPlayback() {
        if (mediaPlayer != null) {
            try {
                mediaPlayer.stop();
                mediaPlayer.reset();
                mediaPlayer.setDataSource(AUDIO_URL);
                mediaPlayer.prepareAsync();
            } catch (IOException | IllegalStateException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            try {
                mediaPlayer.stop();
            } catch (IllegalStateException ignored) {
            } finally {
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    }
}

Riprodurre file video con MediaPlayer Android

Riprodurre video richiede di configurare MediaPlayer e fornire una superficie di rendering, ad esempio una SurfaceView o una TextureView. Una soluzione pratica è VideoView, che internamente usa MediaPlayer. Se invece ti serve più controllo puoi collegare direttamente il player a un SurfaceHolder.

Esempio base con VideoView

// layout.xml
// <VideoView
//     android:id="@+id/videoView"
//     android:layout_width="match_parent"
//     android:layout_height="wrap_content" />

public class VideoActivity extends AppCompatActivity {

    private VideoView videoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video);

        videoView = findViewById(R.id.videoView);

        Uri videoUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.video);
        videoView.setVideoURI(videoUri);

        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.setLooping(true);
                videoView.start();
            }
        });
    }
}

Esempio con MediaPlayer + SurfaceView

public class CustomVideoActivity extends AppCompatActivity implements SurfaceHolder.Callback {

    private MediaPlayer mediaPlayer;
    private SurfaceView surfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_video);

        surfaceView = findViewById(R.id.surfaceView);
        surfaceView.getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setDataSource("https://esempio.com/video.mp4");
        } catch (IOException e) {
            e.printStackTrace();
        }
        mediaPlayer.setDisplay(holder);
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });
        mediaPlayer.prepareAsync();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { }
}

Gestione dei listener di MediaPlayer Android

MediaPlayer espone diversi listener per reagire agli eventi di riproduzione. I principali sono:

  • Il listener OnPreparedListener viene chiamato quando il player è pronto per la riproduzione.
  • Tramite OnCompletionListener puoi reagire al termine della riproduzione.
  • Con OnErrorListener intercetti eventuali errori durante la riproduzione.

Esempio di configurazione dei listener

mediaPlayer = new MediaPlayer();
try {
    mediaPlayer.setDataSource("https://esempio.com/audio.mp3");
} catch (IOException e) {
    e.printStackTrace();
}

mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(MediaPlayer mp) {
        // UI pronta: puoi mostrare durata, abilitare pulsanti, ecc.
        mp.start();
    }
});

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mp) {
        // Reset UI, aggiorna pulsanti Play/Pause
        Toast.makeText(context, "Finito", Toast.LENGTH_SHORT).show();
    }
});

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        // Logga e mostra un messaggio all'utente
        Log.e("MediaPlayer", "Errore what=" + what + " extra=" + extra);
        Toast.makeText(context, "Impossibile riprodurre il file", Toast.LENGTH_SHORT).show();
        return true; // indica che l'errore è stato gestito
    }
});

mediaPlayer.prepareAsync();

Gestione degli errori con OnErrorListener in MediaPlayer Android Java

Una corretta gestione degli errori è fondamentale quando usi MediaPlayer Android Java per riprodurre audio Android. Gli errori possono verificarsi durante setDataSource(), la preparazione (prepare() / prepareAsync()) o in piena riproduzione.

  • Avvolgi sempre setDataSource() e prepare() in un blocco try/catch per intercettare IOException.
  • Registra un OnErrorListener per intercettare problemi a runtime (ad esempio formati non supportati, errori di rete, decoder non disponibile).
  • In caso di errore grave, chiama reset() o release(), mostra un messaggio all'utente e, se necessario, prova a ricreare il player.
  • Usa Log.e(...) per salvare dettagli utili al debug (codici what e extra).
mediaPlayer = new MediaPlayer();

try {
    mediaPlayer.setDataSource(url);
    mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            Log.e("MediaPlayer", "Errore what=" + what + " extra=" + extra);

            Toast.makeText(getApplicationContext(),
                    "Si è verificato un errore di riproduzione",
                    Toast.LENGTH_SHORT).show();

            // Rilascia o resetta il player per evitare stati inconsistenti
            try {
                mp.reset();
            } catch (IllegalStateException e) {
                mp.release();
            }

            // true indica che l'errore è stato gestito
            return true;
        }
    });

    mediaPlayer.prepareAsync();
} catch (IOException e) {
    Log.e("MediaPlayer", "Errore setDataSource", e);
    Toast.makeText(this, "File non accessibile o URL non valido", Toast.LENGTH_SHORT).show();
}

Come rilasciare correttamente le risorse con release() in MediaPlayer Android Java

Il metodo release() è l'ultimo passo del ciclo di vita di MediaPlayer Android Java. Quando chiami release(), tutte le risorse native (decoder, buffer, thread) vengono rilasciate e il player passa allo stato End. Da questo momento non devi più usarlo. Rilasciare tempestivamente le risorse è essenziale per evitare memory leak e crash.

private void releasePlayer() {
    if (mediaPlayer != null) {
        try {
            // Prova a fermare la riproduzione se è in corso
            mediaPlayer.stop();
        } catch (IllegalStateException ignored) {
            // Ignora: il player potrebbe non essere in stato Started
        } finally {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    releasePlayer();
}

Best practice MediaPlayer Android: evitare memory leak

Poiché MediaPlayer usa risorse di sistema (codec, buffer, thread), è fondamentale rilasciarlo correttamente. Seguire queste indicazioni aiuta a prevenire memory leak e comportamenti inattesi:

  • Rilascia sempre il player: chiama release() in onDestroy() (Activity) o onDestroyView() / onStop() (Fragment), poi imposta il riferimento a null.
  • Evita riferimenti statici: non memorizzare MediaPlayer in variabili static o singleton che vivono più a lungo del contesto UI.
  • Gestisci il contesto con attenzione: usa Application Context o WeakReference invece di Activity per evitare leak di contesto.
  • Non bloccare il thread principale: preferisci prepareAsync() al posto di prepare() per sorgenti lente o remote.
  • Controlla lo stato prima di operare: verifica che il player non sia null e che non sia già rilasciato prima di chiamare metodi come start() o pause().
  • Quando lo schermo si spegne, valuta di rilasciare il player se non è necessario continuare la riproduzione in background.
@Override
protected void onDestroy() {
    super.onDestroy();
    if (mediaPlayer != null) {
        try {
            mediaPlayer.stop();
        } catch (IllegalStateException e) {
            // ignorabile se il player non era in stato Started
        } finally {
            mediaPlayer.release();
        }
        mediaPlayer = null;
    }
}

FAQ su MediaPlayer Android Java

  • 1. Qual è la differenza tra MediaPlayer e ExoPlayer?
    MediaPlayer è la soluzione inclusa nel framework Android, più semplice ma meno flessibile. ExoPlayer (libreria Google) offre buffering avanzato, supporto migliorato per lo streaming e aggiornamenti più frequenti. Per casi base di riprodurre audio Android, MediaPlayer è sufficiente.
  • 2. Posso usare MediaPlayer Android Java per lo streaming HTTP?
    Sì, è possibile riprodurre stream HTTP/HTTPS passando un URL a setDataSource() e usando prepareAsync(). Assicurati di gestire time-out ed errori di rete tramite OnErrorListener.
  • 3. Quando devo usare prepare() e quando prepareAsync()?
    Usa prepare() solo per file locali piccoli e su thread in background, perché è bloccante. Per audio remoto o file pesanti, usa prepareAsync() e avvia la riproduzione in onPrepared().
  • 4. Come posso continuare la riproduzione quando l'app va in background?
    Sposta MediaPlayer in un Service o ForegroundService e controllalo dall'Activity con Intent o binding. Ricorda di mostrare una notifica persistente per rispettare le linee guida di Android.
  • 5. È obbligatorio chiamare sempre release() su MediaPlayer?
    Sì, ogni volta che hai finito di usare il player devi chiamare release() per liberare le risorse native. In caso contrario, potresti avere leak di memoria, consumo di batteria e crash difficili da tracciare.

Riepilogo

MediaPlayer Android è uno strumento potente, ma richiede attenzione nella gestione dello stato e del ciclo di vita. Usa setDataSource() e prepareAsync() per configurare la sorgente, avvia la riproduzione con start(), gestisci pausa e stop con pause() e stop() e rilascia sempre le risorse con release(). Configura i listener OnPreparedListener, OnCompletionListener e OnErrorListener per migliorare l’esperienza utente e rendere l’app più robusta, e segui le best practice indicate per evitare memory leak e comportamenti indesiderati.