Android - 如何一次只允许播放一个 MediaPlayer 实例?
我正在尝试创建一个简单的 Sound-board Android 应用程序,使用 ListView 项目作为按钮。 (顺便说一句,我是一名新手程序员)
这个想法是,我按下一个按钮,然后播放特定的声音文件。如果我在播放声音时按下任何按钮,它应该首先停止该声音,然后开始播放新的声音。
目前,声音的播放不会停止任何当前正在播放的声音,因此,如果我向按钮发送垃圾邮件,我会同时播放多个声音(如果我一次按太多声音,应用程序会强制关闭)。
我尝试使用以下几种变体:
if (mp.isPlaying()) {
mp.stop();
}
但根据我在其他一些来源上读到的内容,我正在创建 MediaPlayer 类的多个实例,即使它们具有相同的名称, stop() 方法也会尝试在最新的版本上停止mp 的实例(在某些情况下它甚至还没有创建)。
我猜我对 MediaPlayer 类的一般实现是错误的,但这是我能想到的最好的方法。
无论如何,这是相关的代码块:
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.
}
});
}
}
任何帮助将不胜感激,谢谢。
编辑(3 月 22 日):
我发现以下代码应该可以工作:
mp.setDataSource(context, Uri.parse("android.resource://" + Config.PACKAGE + "/" + resId));
但是,我无法弄清楚“Config.PACKAGE”部分是如何工作的。我刚刚收到错误“PACKAGE 无法解析,或者不是字段”。
我尝试用包名称替换“PACKAGE”,同样的错误。我也尝试过:
try {
mp.setDataSource(getApplicationContext(),Uri.parse("android.resource://com.mptest/" + R.raw.test2));
} catch (IOException e) {
e.printStackTrace();
}
但我无法确定到底用什么来代替“//com.mptest/”。
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/".
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
全局变量
MediaPlayer
需要设置为private static
。这已经让我抓到好几次了。The global variable
MediaPlayer
needs to be setprivate static
. This has caught me several times.不要使用全局。使用单例模式。这就是它的用途,这样您就可以拥有一个不使用全局变量的实例。
对于这种模式,有很多很好的 Java 代码示例,从 http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html 你不会出错的。
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.
考虑将 MediaPlayer 保留为全局变量,而不是拥有它的多个实例。
Consider keeping your MediaPlayer as a global variable instead of having multiple instances of it.
您可能会在 VideoView 中找到很好的参考Source,因为它处理一个
MediaPlayer
对象,并且您可以在播放期间更改内容。You might find a good reference in the VideoView Source, since it handles one
MediaPlayer
object and you may change content during playback.