Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for SoundPool to load before moving on with application

I was following a tutorial to integrate SoundPool into my app, and this is the code which was given in the tutorial:

package com.example.soundpoolexample;

import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.media.SoundPool.OnLoadCompleteListener;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class SoundPoolExample extends Activity implements OnTouchListener {
    private SoundPool soundPool;
    private int soundID;
    boolean loaded = false;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        View view = findViewById(R.id.textView1);
        view.setOnTouchListener(this);
        // Set the hardware buttons to control the music
        this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        // Load the sound
        soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
        soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId,
                    int status) {
                loaded = true;
            }
        });
        soundID = soundPool.load(this, R.raw.sound1, 1);

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // Getting the user sound settings
            AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
            float actualVolume = (float) audioManager
                    .getStreamVolume(AudioManager.STREAM_MUSIC);
            float maxVolume = (float) audioManager
                    .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            float volume = actualVolume / maxVolume;
            // Is the sound loaded already?
            if (loaded) {
                soundPool.play(soundID, volume, volume, 1, 0, 1f);
                Log.e("Test", "Played sound");
            }
        }
        return false;
    }
}

The problem is, I want to make sure that the application only moves forward once the SoundPool is loaded successfully, and not have to check if it is loaded before playing a sound each time. How would I do this?

I am sure this is an atrocious solution, but would something like this work after I load the sound file in onCreate?:

...

    soundID = soundPool.load(this, R.raw.sound1, 1);
    while (!loaded) {}

...

I am sure there is a better way.

like image 910
capcom Avatar asked Nov 03 '22 05:11

capcom


2 Answers

You can have an elegant solution using Semaphore, however try to avoid blocking onCreate(), since the app will not be responsive, the code here is just to illustrate the use of Semaphore

public class SoundPoolExample extends Activity implements OnTouchListener {

public static final Semaphore semaphore = new Semaphore(0);

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
        @Override
        public void onLoadComplete(SoundPool soundPool, int sampleId,
                int status) {

            semaphore.release();
        }
    });
    soundID = soundPool.load(this, R.raw.sound1, 1);

    // Will block since there is not permits (the semaphore is initialized with 0)
    // then will continue once semaphore.release(); is called i.e. after loading is finished
    semaphore.acquire();
} 

// rest of your class

}
like image 185
iTech Avatar answered Nov 14 '22 23:11

iTech


I think while using SoundPool, everyone should pay attention to two cases:

  1. SoundPool is deprecated for API+21, instead you should use SoundPool.Builder
  2. If your SoundPool runs in the main thread, take it to another thread as it blocks your UI
like image 27
sam Avatar answered Nov 15 '22 01:11

sam