I want to play a sound when the user touch the button and have the sound stop when the finger is lifted. This is my trial code which works as I wanted:
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
// -1 so it keeps looping
fStream = soundPool.play(F4, 1, 1,0,-1,1);
return true;
case MotionEvent.ACTION_UP:
soundPool.stop(fStream);
}
return false;
}
This is the code I want to put in my app after I apply some conditions:
int A4, A5, aStream; //global variable in MainActivity
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if(up){
horizontal_method(A5, A5_sharp, aStream);
} else if(down){
horizontal_method(A4, A4_sharp, aStream);
}
return true;
case MotionEvent.ACTION_UP:
stop_audio_method(aStream);
//soundPool.stop(aStream);
}
return false;
}
public void horizontal_method(int note, int sharp, int stream){
if(horizontal){ //if phone is moving
loop_num = -1;
} else { //if phone is not moving
loop_num = 0;
}
rotate_method(note, sharp, stream, loop_num);
}
public void rotate_method(int note, int sharp, int stream, int loop_num){
if(rotate){ //if it's sharp
stream = soundPool.play(sharp, 1, 1,0,loop_num,1);
} else { // if it's normal note
stream = soundPool.play(note, 1, 1,0,loop_num,1);
}
}
public void stop_audio_method(int stream){
soundPool.stop(stream);
}
The problem:
In the trial code, when I press and hold the button, the sound loops. When I lift my finger, it stops. But in my app, when I lift my finger, the sound doesn't immediately stop. It plays the whole audio instead, doesn't matter whether it's looping or not. (Now when it loops it never stops). I tried putting the soundpool.stop(aStream)
directly in the MotionEvent.ACTION_UP
but it's still the same.
In the rotate_method
, the stream
variable has an underline and it says "The value soundPool.play(sharp, 1, 1, 0, loop_num, 1) assigned to stream is never used." Like yeah it's not used, it's just for playing the audio.
The trial code doesn't have this 'disclaimer'.
What did I do wrong? Why is the soundpool behaving differently in the trial code and in my app?
SoundPool.play()
returns a streamID that you need if you want to stop the playback.
In your trial code you assign that value to some field fStream
:
fStream = soundPool.play(F4, 1, 1,0,-1,1);
and use it to stop the playback when you want to stop it:
soundPool.stop(fStream);
In your "production" code you assign that value to a parameter:
public void rotate_method(int note, int sharp, int stream, int loop_num){
stream = soundPool.play(sharp, 1, 1,0,loop_num,1);
// stream is a method parameter here and changes are lost!
}
You must instead store the returned value in some field - why not reuse the field from the previous sample:
public void rotate_method(int note, int sharp, int stream, int loop_num){
fStream = soundPool.play(sharp, 1, 1,0,loop_num,1);
}
And since you now no longer need the parameter you should remove it from the method:
public void rotate_method(int note, int sharp, int loop_num){
fStream = soundPool.play(sharp, 1, 1,0,loop_num,1);
}
This change will propagate back to the calling methods.