问题
I'm trying to create a simple Sound-board Android app, using ListView items as buttons. (Btw, I'm a novice programmer)
The idea is that I press a button, and a specific sound file plays. If I press any button while a sound is playing, it should first stop that sound and then start to play the new one.
Currently the sounds play without stopping any currently playing sounds, so that if I spam the buttons I get multiple sounds playing at the same time (and if I press too many at once, the app force closes).
I have tried using a few variations of:
if (mp.isPlaying()) {
mp.stop();
}
But according to what I read on a few other sources, I am creating multiple instances of the MediaPlayer class, and even though they have the same name the stop() method tries to stop on the latest instance of mp (in some cases it isn't even created yet).
I'm guessing my general implementation of the MediaPlayer class is wrong, but it's the best I could figure out to do.
Anyways, here's the relevant block of code:
public class soundTest extends Activity {
private ListView lv1;
private String lv_arr[]={"test 1","test 2","test 3","test 4","test 5"};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv1=(ListView)findViewById(R.id.ListView01);
lv1.setAdapter(new ArrayAdapter<String>(this,R.layout.list_item, lv_arr));
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,int position, long id) {
if (lv1.getItemAtPosition(position)=="test 1") {
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.sound1);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
if (lv1.getItemAtPosition(position)=="test 2") {
MediaPlayer mp = MediaPlayer.create(getApplicationContext(),R.raw.sound2);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
//And the rest of the sounds 3,4,5.
}
});
}
}
Any help would be appreciated, thanks.
Edit (22nd March):
I've found the following piece of code that should work:
mp.setDataSource(context, Uri.parse("android.resource://" + Config.PACKAGE + "/" + resId));
But, I can't figure out how the "Config.PACKAGE" part works. I just get an error "PACKAGE cannot be resolved, or is not a field".
I tried replacing "PACKAGE" with the package name, same error. I also tried:
try {
mp.setDataSource(getApplicationContext(),Uri.parse("android.resource://com.mptest/" + R.raw.test2));
} catch (IOException e) {
e.printStackTrace();
}
But I can't work what exactly to put in place of "//com.mptest/".
回答1:
The global variable MediaPlayer
needs to be set private static
. This has caught me several times.
回答2:
Don't use a global. Use the singleton pattern. That is what it is for, so that you can have exactly one instance w/o using a global variable.
There are lots of good examples of Java code for this pattern, start with http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html and you can't go wrong.
回答3:
Consider keeping your MediaPlayer as a global variable instead of having multiple instances of it.
回答4:
You might find a good reference in the VideoView Source, since it handles one MediaPlayer
object and you may change content during playback.
来源:https://stackoverflow.com/questions/5367982/android-how-do-i-only-allow-one-instance-of-mediaplayer-to-play-at-a-time