I created a singleton class for managing sound effects on Android. This class will only be instanced and loaded once at the beginning, and each activity will use the loaded songs.
I don't know either if this is the good approach for Singleton, nor if this is the good way to play sounds in Android. This is working like a charm, and I'm wondering about the resource utilizations.
public class SoundManager {
private static SoundManager mInstance;
private SoundPool mSoundPool;
private HashMap<Integer, Integer> mSoundPoolMap;
private Vector<Integer> mAvailibleSounds = new Vector<Integer>();
private Vector<Integer> mKillSoundQueue = new Vector<Integer>();
private Handler mHandler = new Handler();
private boolean mMuted = false;
private static final int MAX_STREAMS = 2;
private static final int KILL_AFTER = 3000;
public static final int SOUND_SELECT = 0;
public static final int SOUND_LOCKED = 1;
@SuppressLint("UseSparseArrays")
private SoundManager(Context context) {
mSoundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
loadSounds(context);
}
public static SoundManager getInstance(Context context){
if(mInstance == null){
mInstance = new SoundManager(context);
Log.d("SPARTA", "Instanciation");
}
return mInstance;
}
/**
* Load all sounds and put them in their respective keys.
* @param context
*/
private void loadSounds(Context context){
addSound(context, SOUND_SELECT, R.raw.metallic_knock);
addSound(context, SOUND_LOCKED, R.raw.licorice);
}
/**
* Put the sounds to their correspondig keys in sound pool.
* @param context
* @param key
* @param soundID
*/
public void addSound(Context context, int key, int soundID) {
mAvailibleSounds.add(key);
mSoundPoolMap.put(key, mSoundPool.load(context, soundID, 1));
}
/**
* Find sound with the key and play it
* @param key
*/
public void playSound(int key) {
if(mMuted)
return;
//If we have the sound
if(mAvailibleSounds.contains(key)) {
//We play it
int soundId = mSoundPool.play(mSoundPoolMap.get(key), 1, 1, 1, 0, 1f);
mKillSoundQueue.add(soundId);
//And schedule the current sound to stop after set milliseconds
mHandler.postDelayed(new Runnable() {
public void run() {
if (!mKillSoundQueue.isEmpty()) {
mSoundPool.stop(mKillSoundQueue.firstElement());
}
}
}, KILL_AFTER);
}
}
/**
* Initialize the control stream with the activity to music
* @param activity
*/
public static void initStreamTypeMedia(Activity activity){
activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
/**
* Is sound muted
* @param muted
*/
public void setMuted(boolean muted) {
this.mMuted = muted;
}
}