简体   繁体   中英

How to Play sound when button is clicked in Android?

I'm trying to play a sound file when a button is clicked but keeps getting an error.

The error is:

 "The method create(Context, int) in the type MediaPlayer is not applicable for the arguments (new View.OnClickListener(){}, int)"

Here's my code:

@Override
public void onClick(View v) {
    // TODO Auto-generated method stub
    Button zero = (Button)this.findViewById(R.id.btnZero);
    zero.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            mp = MediaPlayer.create(this, R.raw.mamacita_zero);
        }
    });
}

Any help or tips would be appreciated. Thnx!

There are a few things going on here (disclaimer, this is just how I'm used to using it, there may be a better way):

  • You seem to be doing a lot more work per click than you need to. You're creating and adding a new onClickListener for every click in the Activity's View, not the Button . You only need to set the listener once, and for the Button rather than the overarching View; I tend to do that in the constructor of the Activity.

  • Regarding your error, MediaPlayer works fine for me when the Context I pass it is the overriding Activity. When you pass this , it's passing the onClickListener you are creating, throwing off the MediaPlayer.

  • Finally, to actually play the sound, you have to call start() .

So for the constructor in the Activity, you can create the MediaPlayer once, find the Button, and attach an onClickListener that will play the sound from the MediaPlayer you've just created. It would look something like:

public class MyActivity extends Activity {

    public MyActivity(Bundle onSavedStateInstance) {
        // eliding some bookkeepping

        MediaPlayer mp = MediaPlayer.create(this, R.raw.mamacita_zero);

        Button zero = (Button)this.findViewById(R.id.btnZero);
        zero.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mp.start();
            }
        });
    }
}

Hope that helps!

I have played around with media-player, and it is easy to get in trouble. I followed the advice of Volodymyr, and SoundPool is much easier to manage.

MediaPlayer does not like to play more than one sound at the time, like for instance when you have lots of quick tabs on your buttons. I managed with the following method:

private void playSound(Uri uri) {
    try {
        mMediaPlayer.reset();
        mMediaPlayer.setDataSource(this, uri);
        mMediaPlayer.prepare();
        mMediaPlayer.start();
    } catch (Exception e) {
        // don't care
    }

}

In the constructor I did:

mMediaPlayer = new MediaPlayer();
mSoundLess = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.less);
mSoundMore = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.more);

On click I would then call playSound(mSoundLess):

Instead I have created a SoundPool helper:

package com.mycompany.myapp.util;

import java.util.HashSet;
import java.util.Set;

import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;

public class SoundPoolHelper extends SoundPool {
    private Set<Integer> mLoaded;
    private Context mContext;

    public SoundPoolHelper(int maxStreams, Context context) {
        this(maxStreams, AudioManager.STREAM_MUSIC, 0, context);
    }

    public SoundPoolHelper(int maxStreams, int streamType, int srcQuality, Context context) {
        super(maxStreams, streamType, srcQuality);
        mContext = context;
        mLoaded = new HashSet<Integer>();
        setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                mLoaded.add(sampleId);
            }
        });
    }

    public void play(int soundID) {
        AudioManager audioManager = (AudioManager) mContext.getSystemService( Context.AUDIO_SERVICE);
        float actualVolume = (float) audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        float maxVolume = (float) audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        float volume = actualVolume / maxVolume;
        // Is the sound loaded already?
        if (mLoaded.contains(soundID)) {
            play(soundID, volume, volume, 1, 0, 1f);
        }
    }
}

Now I init like this:

mSoundPoolHelper = new SoundPoolHelper(1, this);
mSoundLessId = mSoundPoolHelper.load(this, R.raw.less, 1);
mSoundMoreId = mSoundPoolHelper.load(this, R.raw.more, 1);

and play a sound like this:

private void playSound(int soundId) {
    mSoundPoolHelper.play(soundId);
}

Don't forget to call mSoundPoolHelper.release(); , for instance in your onDestroy() . Something similar is needed if you use MediaPlayer.

MediaPlayer mp = MediaPlayer.create(getBaseContext(),
R.raw.yoursoundfile);
mp.start();

the file yoursoundfile must to be in the res/raw folder

If you really have to invoke the click programmatically because the view has no own sound, i would solve it like that, its the simplest solution and a oneliner

view.playSoundEffect(SoundEffectConstants.CLICK);

very simple and works, if you want to make a layout play a sound you need to put

android:soundEffectsEnabled="true"

in your xml.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM