In questa guida pratica su SoundPool Android scoprirai come riprodurre effetti sonori rapidi e reattivi nelle tue app, senza ritardi e con più suoni in parallelo. Vedremo cos’è SoundPool, a cosa serve e perché è la scelta ideale per giochi, notifiche ed effetti audio leggeri. Gli esempi sono scritti in Java e pensati per essere seguiti passo passo in Android Studio, così puoi copiarli e adattarli subito ai tuoi progetti. Continua a leggere per capire come configurare al meglio SoundPool e sfruttarne tutte le potenzialità.

Cos’è SoundPool Android Java e quando usarlo
SoundPool è una classe di Android pensata per riprodurre in modo rapido suoni brevi, come effetti sonori e notifiche. A differenza di MediaPlayer, carica i file audio in memoria e li mantiene pronti, così la riproduzione è immediata e puoi far partire più suoni in parallelo. Il metodo setMaxStreams() definisce quanti stream possono essere attivi contemporaneamente. AudioAttributes specifica invece il tipo di utilizzo dell’audio (gioco, notifica, contenuti multimediali, ecc.) e aiuta il sistema a gestirlo correttamente.
Configurare SoundPool Android Java con AudioAttributes e Builder
Dalla API 21 in poi si usa SoundPool.Builder al posto del costruttore ora deprecato. Il Builder riceve un oggetto AudioAttributes che descrive come verrà usato il suono. In base a queste informazioni Android gestisce in modo più preciso il percorso dell’audio, il volume e le priorità rispetto ad altre sorgenti.
Struttura del progetto
Aggiungi il file audio alla cartella res/raw/ del progetto. Nell’esempio usiamo un file chiamato sound_1.wav, ma puoi scegliere un altro nome, purché sia lo stesso che utilizzi poi nel codice.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button_play"
android:text="Play"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.soundPool;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
SoundPool soundPool;
int soundID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(5)
.setAudioAttributes(audioAttributes)
.build();
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
if (status == 0) {
// Suono caricato con successo, pronto per la riproduzione
}
}
});
// Carica il file audio dalla cartella res/raw
soundID = soundPool.load(this, R.raw.sound_1, 1);
Button button_play = findViewById(R.id.button_play);
button_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Riproduci il suono
soundPool.play(soundID, 1, 1, 0, 0, 1);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
}
}
Parametri del metodo play() in SoundPool Android Java
Il metodo soundPool.play() accetta sei parametri, riassunti nella tabella seguente:
| Parametro | Tipo | Descrizione |
|---|---|---|
soundID | int | ID del suono restituito da load() |
leftVolume | float | Volume canale sinistro (0.0 – 1.0) |
rightVolume | float | Volume canale destro (0.0 – 1.0) |
priority | int | Priorità dello stream (0 = più bassa) |
loop | int | 0 = nessun loop, -1 = loop infinito |
rate | float | Velocità di riproduzione (1.0 = normale, 0.5–2.0) |
Gestione delle risorse SoundPool Android
È buona norma rilasciare sempre SoundPool quando non ti serve più, per evitare memory leak e inutili sprechi delle risorse audio di sistema. Chiama soundPool.release() nel metodo onDestroy() e poi imposta la variabile soundPool a null.
@Override
protected void onDestroy() {
super.onDestroy();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
}
SoundPool Android Java vs MediaPlayer: quando usare quale
| Caratteristica | SoundPool | MediaPlayer |
|---|---|---|
| Tipo di contenuto | Effetti sonori Android brevi (click, esplosioni, notifiche) | Musica di sottofondo, tracce lunghe, video, streaming |
| Dimensione file consigliata | Piccola (< 1 MB, pochi secondi) | Qualsiasi dimensione |
| Latenza | Molto bassa (file in memoria) | Più alta (buffering da disco o rete) |
| Stream simultanei | Sì, multipli (configurabili con maxStreams) | In pratica uno alla volta per istanza |
| Supporto URL / streaming | No | Sì (file locali e URL remoti) |
| Controlli avanzati | Rate/pitch e volume per singolo effetto sonoro | Seek, pause, ripresa, controlli multimediali completi |
In sintesi, usa SoundPool Android Java per riprodurre effetti sonori Android brevi e reattivi (giochi, feedback UI, notifiche interne all’app), mentre scegli MediaPlayer per musica di sottofondo, brani lunghi o audio/video da file e URL.
Esempio: combinare SoundPool e MediaPlayer nella stessa app
Nell’esempio seguente usiamo SoundPool per gli effetti sonori e MediaPlayer per la musica di sottofondo, in un’unica MainActivity Java.
package com.example.soundpoolmediaplayer;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private SoundPool soundPool;
private int clickSoundId;
private MediaPlayer bgMusicPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// SoundPool per effetti sonori Android brevi
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(5)
.setAudioAttributes(audioAttributes)
.build();
clickSoundId = soundPool.load(this, R.raw.ui_click, 1);
// MediaPlayer per musica di sottofondo
bgMusicPlayer = MediaPlayer.create(this, R.raw.background_music);
bgMusicPlayer.setLooping(true);
Button buttonClick = findViewById(R.id.button_click);
Button buttonMusic = findViewById(R.id.button_music);
buttonClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(clickSoundId, 1f, 1f, 1, 0, 1f);
}
});
buttonMusic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (bgMusicPlayer != null) {
if (bgMusicPlayer.isPlaying()) {
bgMusicPlayer.pause();
} else {
bgMusicPlayer.start();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
if (bgMusicPlayer != null) {
bgMusicPlayer.release();
bgMusicPlayer = null;
}
}
}
Caricare effetti sonori Android da assets con SoundPool Android Java
Oltre alla cartella res/raw, puoi caricare i file audio anche dalla cartella assets/ usando AssetFileDescriptor. Questo è utile quando vuoi mantenere una struttura di file personalizzata o riutilizzare le stesse risorse audio tra più moduli.
package com.example.soundpoolassets;
import android.content.res.AssetFileDescriptor;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private SoundPool soundPool;
private int assetSoundId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(5)
.setAudioAttributes(audioAttributes)
.build();
try {
AssetFileDescriptor afd = getAssets().openFd("sounds/jump.wav");
assetSoundId = soundPool.load(afd, 1);
afd.close();
} catch (IOException e) {
e.printStackTrace();
}
Button buttonPlayAsset = findViewById(R.id.button_play_asset);
buttonPlayAsset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(assetSoundId, 1f, 1f, 1, 0, 1f);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
}
}
In questo esempio il file jump.wav si trova in app/src/main/assets/sounds/jump.wav. Ricorda di creare manualmente la cartella assets se non esiste.
Gestire più effetti sonori Android contemporaneamente con maxStreams
Il parametro setMaxStreams(int maxStreams) del SoundPool.Builder definisce quanti suoni possono essere riprodotti contemporaneamente. Per un gioco con molti effetti sonori Android sovrapposti (esplosioni, salti, colpi) conviene usare valori tra 5 e 10, in base al dispositivo target.
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
// Esempio: fino a 10 stream contemporanei
SoundPool soundPool = new SoundPool.Builder()
.setMaxStreams(10)
.setAudioAttributes(audioAttributes)
.build();
int laserId = soundPool.load(this, R.raw.laser, 1);
int explosionId = soundPool.load(this, R.raw.explosion, 1);
int jumpId = soundPool.load(this, R.raw.jump, 1);
// Puoi chiamare play() più volte, SoundPool gestirà gli stream fino a maxStreams
soundPool.play(laserId, 1f, 1f, 1, 0, 1f);
soundPool.play(explosionId, 1f, 1f, 1, 0, 1f);
soundPool.play(jumpId, 1f, 1f, 1, 0, 1f);
Se viene superato il numero massimo di stream, SoundPool potrebbe interrompere quelli a priorità più bassa. Puoi controllare la priorità con il parametro priority di play(), assegnando valori più alti agli effetti sonori più importanti.
Cambiare pitch e velocità di riproduzione con rate in SoundPool Android Java
Il sesto parametro di play(), chiamato rate, controlla sia la velocità di riproduzione sia il pitch (altezza) del suono. Il valore 1.0f corrisponde alla velocità normale, 0.5f è metà velocità (e pitch più basso) e 2.0f è il doppio (pitch più alto).
package com.example.soundpoolrate;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private SoundPool soundPool;
private int effectId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(5)
.setAudioAttributes(audioAttributes)
.build();
effectId = soundPool.load(this, R.raw.effect, 1);
Button buttonSlow = findViewById(R.id.button_slow);
Button buttonNormal = findViewById(R.id.button_normal);
Button buttonFast = findViewById(R.id.button_fast);
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
float rate = 1.0f;
int id = v.getId();
if (id == R.id.button_slow) {
rate = 0.7f; // più lento, pitch più basso
} else if (id == R.id.button_fast) {
rate = 1.5f; // più veloce, pitch più alto
}
soundPool.play(effectId, 1f, 1f, 1, 0, rate);
}
};
buttonSlow.setOnClickListener(listener);
buttonNormal.setOnClickListener(listener);
buttonFast.setOnClickListener(listener);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (soundPool != null) {
soundPool.release();
soundPool = null;
}
}
}
Tieni presente che il range supportato da SoundPool per rate è in genere compreso tra 0.5f e 2.0f. Valori fuori da questo intervallo potrebbero essere ignorati o causare distorsioni indesiderate.
FAQ SoundPool Android Java ed effetti sonori Android
1. Qual è la dimensione massima consigliata per un effetto sonoro in SoundPool?
In generale è meglio tenersi sotto 1 MB e pochi secondi di durata. File più grandi aumentano l’uso di memoria e i tempi di caricamento: per tracce lunghe è preferibile usare MediaPlayer.
2. Posso usare SoundPool per riprodurre musica di sottofondo?
Sebbene tecnicamente sia possibile, non è consigliato. SoundPool è ottimizzato per effetti sonori Android brevi; per musica continua, streaming o brani lunghi usa MediaPlayer o le API multimediali più recenti.
Quando i suoni servono solo in una singola Activity, puoi caricarli nel onCreate() e rilasciarli in onDestroy(). Per riutilizzarli in più schermate puoi incapsulare SoundPool in un singleton o in un componente di più alto livello, ricordandoti comunque di chiamare release() quando l’app viene chiusa.
Risorse ufficiali
Per approfondire SoundPool e la gestione audio in Android, puoi consultare la documentazione ufficiale di SoundPool; inoltre, è disponibile la guida Media Router di Android sul sito Android Developers.
4. Come posso controllare il volume degli effetti sonori separatamente dalla musica?
Per farlo puoi salvare un fattore di volume per gli effetti sonori (ad esempio da SharedPreferences) e moltiplicarlo per il volume di sistema quando chiami play(). In alternativa, puoi usare stream diversi e gestire i volumi a livello di app.
5. Cosa succede se non chiamo release() su SoundPool?
Nel caso in cui le risorse di SoundPool non vengano correttamente liberate, rischi memory leak e un consumo inutile dei canali audio. In alcuni casi estremi questo può causare crash o problemi di riproduzione audio in altre parti dell’app o del sistema, quindi è fondamentale chiamare sempre soundPool.release() quando non ti serve più.