0

I'm doing a very simple app for android but I'm having a problem that I really have no idea how to solve. My app has a layout with 8 buttons, and every button makes a sound when you click on it. I have just one activity and within the oncreate method I define 8 MediaPlayer variables which are the 8 different sounds on mp3 format I have on my raw folder. Then I associate them to each button. When I compile the app on the emulator, everything works fine, but when I compile it on the phone the sound 8 does not work. I mean, when I press a button which has associated the sound 8, the app crashes. I also noticed that if I add more buttons with more sounds only the first 7 sounds work, no more, the others make the app to crash. It seems like I cannot have more than seven MediaPlayer variables. But that doesn't make any sense, does it?

Can anyone help me to solve this??

Thanks in advance.

Here is my java code:

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();

        }
    });

}
}
f22rumaj
  • 1
  • 1

3 Answers3

2

Woah! You should not be creating multiple instances of MediaPlayer. Huge waste of resources and probably what's causing your crash. You didn't say but I guess it's a memory problem. In future, please include the logcat output or a stack trace for a crash.

Take a look at the SoundPool class.

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

Plenty of examples on the web. e.g.

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

Simon
  • 14,407
  • 8
  • 46
  • 61
1
  1. Consider using SoundPool instead.
  2. If you have so many items, which their names are indexed, you should probably put them in a map. This way you can avoid creating a separate listener for each button. For example:

    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);
    }
    
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
MByD
  • 135,866
  • 28
  • 264
  • 277
0

Yeah, definitely shouldn't be using that many instances of MediaPlayer, but it's an easy mistake to make starting out. Consider something like this instead, using a single MediaPlayer instance:

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();
        }
    }
}

Consider it pseudocode, as I haven't tested it (although it should be close), and just take the idea. Keep an array of button IDs and an array of sound IDs (keep them indexed together, i.e. button ID 1 should be in the same position as sound ID 1). For each button ID, find the View, cast it to a Button, and add on onClickListener which resets the player (if playing), sets the data source to the associated sound ID, prepares the player, and starts it.

As a general rule, any time you see yourself repeating code like that, you should look for a better design to avoid it.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274