Sound manager for Android 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&lt;Integer, Integer&gt; mSoundPoolMap;

    private Vector&lt;Integer&gt; mAvailibleSounds = new Vector&lt;Integer&gt;();
    private Vector&lt;Integer&gt; mKillSoundQueue = new Vector&lt;Integer&gt;();

    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&lt;Integer, Integer&gt;();

        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;
    }
}
Let me start by saying I have very limited Android experience. That said, I did look into the SoundPool class a bit and have some questions/comments about your implementation:


If you aren't already aware of some of the reasons why people consider Singletons an anti-pattern, I suggest you do some research on the topic and make sure you're ok with the downsides.
Your class, for the most part, seems to be wrapping a SoundPool with a key value pair structure despite SoundPool already being a key value pair structure. I would imagine you could do away with most of this class and just use the SoundPool class directly.
If you don't want to use SoundPool directly for some reason, why not at least use the soundId as a key? It already appears to be unique, and it's what the calling code probably wants anyway. If not, you may want to do some checking to make sure that duplicate keys aren't entered, or take the key assignment out of the hands of the caller and simply return an id as the result of the addSound function.
Using both mSoundPoolMap and mAvailibleSounds means you have to manage keys in two locations which could lead to them getting out of sync or some confusion as to why there are two fields holding the same information. Using only mSoundPoolMap would be sufficient and avoid duplication. This highly voted question isn't quite the same, but it touches on a lot of good points why this kind of duplication can be bad.


Hope this helps!