0

我正在为 android 做一个非常简单的应用程序,但我遇到了一个我真的不知道如何解决的问题。我的应用程序有一个包含 8 个按钮的布局,当您单击它时,每个按钮都会发出声音。我只有一个活动,在 oncreate 方法中我定义了 8 个 MediaPlayer 变量,这些变量是我原始文件夹中 mp3 格式的 8 种不同声音。然后我将它们关联到每个按钮。当我在模拟器上编译应用程序时,一切正常,但是当我在手机上编译它时,声音 8 不起作用。我的意思是,当我按下与声音 8 相关联的按钮时,应用程序崩溃。我还注意到,如果我添加更多带有更多声音的按钮,则只有前 7 个声音有效,其他声音不会再起作用,其他声音会使应用程序崩溃。似乎我的 MediaPlayer 变量不能超过七个。但这没有任何意义,不是吗?

谁能帮我解决这个问题??

提前致谢。

这是我的java代码:

package com.f22rumaj.org;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MyMain extends Activity {
/** Called when the activity is first created. */

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //set up the button sound
    final MediaPlayer mpBoton1 = MediaPlayer.create(this, R.raw.button1); 
    final MediaPlayer mpBoton2 = MediaPlayer.create(this, R.raw.button2); 
    final MediaPlayer mpBoton3 = MediaPlayer.create(this, R.raw.button3); 
    final MediaPlayer mpBoton4 = MediaPlayer.create(this, R.raw.button4); 
    final MediaPlayer mpBoton5 = MediaPlayer.create(this, R.raw.button5); 
    final MediaPlayer mpBoton6 = MediaPlayer.create(this, R.raw.button6); 
    final MediaPlayer mpBoton7 = MediaPlayer.create(this, R.raw.button7); 
    final MediaPlayer mpBoton8 = MediaPlayer.create(this, R.raw.button8);


    Button boton1=  (Button) findViewById(R.id.button_1);
    Button boton2=  (Button) findViewById(R.id.button_2);
    Button boton3=  (Button) findViewById(R.id.button_3);
    Button boton4=  (Button) findViewById(R.id.button_4);
    Button boton5=  (Button) findViewById(R.id.button_5);
    Button boton6=  (Button) findViewById(R.id.button_6);
    Button boton7=  (Button) findViewById(R.id.button_7);
    Button boton8=  (Button) findViewById(R.id.button_8);

    boton1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton1.start();

        }
    });

    boton2.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton2.start();

        }
    });

    boton3.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton3.start();

        }
    });

    boton4.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton4.start();

        }
    });

    boton5.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton5.start();

        }
    });

    boton6.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton6.start();

        }
    });

    boton7.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton7.start();

        }
    });

    boton8.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mpBoton8.start();

        }
    });

}
}
4

3 回答 3

2

哇!您不应该创建多个 MediaPlayer 实例。巨大的资源浪费,可能是导致您崩溃的原因。你没有说,但我想这是一个内存问题。将来,请包括 logcat 输出或崩溃的堆栈跟踪。

看一下 SoundPool 类。

http://developer.android.com/reference/android/media/SoundPool.html

网络上有很多例子。例如

http://www.techrepublic.com/blog/app-builder/getting-your-feet-wet-in-androids-soundpool/877

于 2012-04-23T19:52:41.803 回答
1
  1. 考虑SoundPool改用。
  2. 如果您有这么多项目,它们的名称被索引,您可能应该将它们放在地图中。这样您就可以避免为每个按钮创建单独的侦听器。例如:

    Map<Button, MediaPlayer> buttonMap = new HashMap<Button, MediaPlayer>();
    map.put((Button)findViewById(R.id.button_1), MediaPlayer.create(this, R.raw.button1));
    // same for the rest
    
    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            MediaPlayer selected = buttonMap.get(v);
            selected.start();
        }
    };
    for (Button b : buttonMap.keySet()) {
        b.setOnClickListener(listener);
    }
    
于 2012-04-23T19:48:50.167 回答
0

是的,绝对不应该使用那么多实例MediaPlayer,但一开始很容易犯错误。考虑这样的事情,使用单个MediaPlayer实例:

MediaPlayer mediaPlayer = new MediaPlayer();

int[] buttonIds = { R.id.button_1, R.id.button_2, R.id.button_3,
    R.id.button_4, R.id.button_5, R.id.button_6, R.id.button_7,
    R.id.button_8 };

int[] soundIds = { R.raw.button1, R.raw.button2, R.raw.button3,
    R.raw.button4, R.raw.button5, R.raw.button6, R.raw.button7, 
    R.raw.button8 };

int size = buttonIds.length;

for(int i = 0; i < size; i++) {
    (Button)findViewById(buttonIds[i]).setOnClickListener(
            new View.OnClickListener() {
        @Override public void onClick(View v) {
            if(mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            }
            mediaPlayer.reset();
            AssetFileDescriptor afd = 
                getResources().openRawResourceFd(soundIds[i]);
            mediaPlayer.setDataSource(afd.getFileDescriptor(), 
                afd.getStartOffset(), afd.getLength());
            mediaPlayer.prepare();
            mediaPlayer.start();
        }
    }
}

考虑它是伪代码,因为我还没有测试过它(虽然它应该很接近),然后就接受这个想法。保留按钮 ID 数组和声音 ID 数组(将它们一起编入索引,即按钮 ID 1 应与声音 ID 1 位于同一位置)。对于每个按钮 ID,找到 View,将其转换为 Button,然后添加 onClickListener,它会重置播放器(如果正在播放),将数据源设置为关联的声音 ID,准备播放器并启动它。

作为一般规则,任何时候你看到自己重复这样的代码,你应该寻找一个更好的设计来避免它。

于 2012-04-23T19:59:42.373 回答