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
B开发者_如何学JAVAutton 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 theonClickListener
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.
http://developer.android.com/reference/android/media/SoundPool.html This is better for small sounds http://www.vogella.com/articles/AndroidMedia/article.html#tutorial_soundpool - tutorial
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.
精彩评论