Play sound using soundpool example
Create a folder named as raw under your_app/res/
. Then paste your ringtone in this folder, for example your_app/res/raw/ringtone.mp3
. Now use the following code:
SoundPool soundPool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
int soundId = soundPool.load(context, R.raw.ringtone, 1);
// soundId for reuse later on
soundPool.play(soundId, 1, 1, 0, 0, 1);
Be sure to release the SoundPool resources after use:
soundPool.release();
soundPool = null;
How to play a sound simultaneously using SoundPool for a specific period of time
I'm doing something similar with my app Beat Shaker and I was having the same problem. I solved it using the onLoadCompleteListener:
// Sound pool new instance
SoundPool spool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
// Sound pool on load complete listener
spool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
Log.i("OnLoadCompleteListener","Sound "+sampleId+" loaded.");
boolean loaded = true;
}
});
// Load the sample IDs
int soundId = new int[3];
soundId[0] = spool.load(this, R.raw.sound1, 1);
soundId[1] = spool.load(this, R.raw.sound2, 1);
soundId[2] = spool.load(this, R.raw.sound3, 1);
Later before playing the sound you can check if it is properly loaded using the boolean "loaded".
Android SoundPool is not playing wav format sound
It takes time to load the sound file into memory so change val sound1
to var sound1
, make it global and instantiate it at the end of the onCreate
method like so:
class MainActivity : AppCompatActivity() {
lateinit var soundPool: SoundPool
var sound1 : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
var audioAttrs: AudioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
soundPool = SoundPool.Builder()
.setMaxStreams(2)
.setAudioAttributes(audioAttrs)
.build()
}
else{
soundPool = SoundPool(2, AudioManager.STREAM_MUSIC, 0)
}
sound1 = soundPool.load(this, R.raw.sound1, 1)
}
fun playSound1(view: View) {
if(sound1 != 0) {
soundPool.play(sound1, 1.0f, 1.0f, 1, 0, 1.0f)
}
}
}
Then you could check sound1
value and if it's not equal to 0
so it loaded completely. Also you could use setOnLoadCompleteListener
method of SoundPool
to check this.
Using SoundPool, Timer and TimerTask to play a random sound every minute
So, after much stressing, I have a working solution! I still think there must be a better way to do it but this is what I have come up with. The setOnLoadCompleteListener now plays the sound only once loaded and timerTask2 runs 5 seconds behind the timerTask1. The reason for the 5 seconds delay is that my sounds are all under 1-3 second long.
public class TouchscreenDashboard extends AppCompatActivity implements View.OnClickListener {
int[] sounds={R.raw.decrease_fan_speed_by_2, R.raw.decrease_fan_speed_by_5,
R.raw.increase_fan_speed1, R.raw.increase_fan_speed_by_3,R.raw.lower_temp1,
R.raw.lower_temp4, R.raw.raise_temp2, R.raw.raise_temp3 ,R.raw.skip_backwards_2_songs,
R.raw.skip_backwards_4_songs,R.raw.skip_forward_1_song, R.raw.skip_forward_5_songs,
R.raw.volume_down3,R.raw.volume_down6, R.raw.volume_up3, R.raw.volume_up5};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
Log.i("DashboardActivity", "Dashboard has started");
startTimer();
}
public void startTimer() {
timer = new Timer();
timer2 = new Timer();
initializeTimerTask();
initializeTimerTask2();
timer.schedule(timerTask, randomTimeInt, randomTimeInt); //
timer2.schedule(timerTask2, randomTimeInt + 5000, randomTimeInt);
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
@Override
public void run() {
audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.build();
soundPool = new SoundPool.Builder()
.setAudioAttributes(audioAttributes)
.build();
releaseSoundpool = true;
Random r = new Random();
int Low = 0;
int High = 16;
int random = r.nextInt(High-Low) + Low;
final int soundId = soundPool.load(getApplicationContext(), sounds[random], 1);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
soundPool.play(soundId, 1, 1, 1, 0, 1);
}
});
Log.d("TouchscreenDashboard", "soundID played: " + random);
}
};
}
public void initializeTimerTask2() {
timerTask2 = new TimerTask() {
@Override
public void run() {
soundPool.release();
Log.d("TouchscreenDashboard", "SoundPool released");
}
};
}
I really hope this helps someone else.
SoundPool.Builder explained to a newbie
I haven't used SoundPool
but I can try and give you some help. First of all, have a look at the docs if you haven't already - near the bottom of the intro they describe something like what you're doing. Looks like what you basically need to do is:
- call
SoundPool.Builder().build()
(the defaults look fine for testing) - take the resulting
SoundPool
and call one of theload
methods for each file you want to add - call
play
on it, passing the ID for a sound (which theload
call gives you)
That should work pretty easily - I'd set it up in a single activity so you can test it, maybe add a button that makes a noise when you click it. Your biggest problem is probably gonna be loading the sounds - personally, I'd stick them in assets
and use the load call that takes an AssetFileDescriptor
val assetManager = context.getAssets()
val winSoundFile = assetManager.openFd("sounds/winners.wav")
val winSoundID = soundPool.load(winSoundFile, 1)
but that's more for an ease of organisation thing - you can keep them in res/raw
if you like, and just do
val winSoundId = soundPool.load(context, R.raw.winners, 1)
The other stuff in the docs is what you need to care about, e.g. you should be calling release()
on the sound pool when you're not using it. That means if you don't expect to be playing sounds in the near future, like if the game ends, or if your app goes into the background (so call release
in onPause
or onStop
). Recreate the sound pool when you need it again.
And remember if you switch activities, and the pool was held in the other one, that's gone (and should have been release
d!) and you need to create a new one. Just focus on a simple test first though, get it working and then make it fit what your app needs to do
Related Topics
Error: Failed to Resolve: Com.Android.Support:Appcompat-V7:29.0.1'
Intent Does Not Set the Camera Parameters
Unable to Execute Adb in Ubuntu. Downloaded File Is Meant for X86-64 While I Have I686
Navigation Drawer with Backword Compatibility Android
Buttons Not Visible on the Application. What's Wrong
Javafxports How to Call Android Native Media Player
Can't Get File Uri from Intent Onactivityresult
How to Import a Native Library (.So File) into Eclipse
Save Data and Change Orientation
Stop Asynctask Doinbackground Method
Firebase Cloud Messaging Send Click_Action
How to Read Contacts in Android Using Realm
Most Memory Efficient Way to Resize Bitmaps on Android
Android Studio Project Structure (V.S. Eclipse Project Structure)
How to Decompile an APK or Dex File on Android Platform
View the Task's Activity Stack
Using Build Types in Gradle to Run Same App That Uses Contentprovider on One Device