Android - 如何一次只允许播放一个 MediaPlayer 实例?

发布于 2024-10-24 12:52:11 字数 2393 浏览 1 评论 0原文

我正在尝试创建一个简单的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

糖粟与秋泊 2024-10-31 12:52:11

全局变量MediaPlayer需要设置为private static。这已经让我抓到好几次了。

The global variable MediaPlayer needs to be set private static. This has caught me several times.

一袭白衣梦中忆 2024-10-31 12:52:11

不要使用全局。使用单例模式。这就是它的用途,这样您就可以拥有一个不使用全局变量的实例。

对于这种模式,有很多很好的 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.

霊感 2024-10-31 12:52:11

考虑将 MediaPlayer 保留为全局变量,而不是拥有它的多个实例。

Consider keeping your MediaPlayer as a global variable instead of having multiple instances of it.

雨轻弹 2024-10-31 12:52:11

您可能会在 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文