Reputation: 6522
I have a custom view (a button) and I want it to have a certain sound when pressed.
private void playSound() {
if (mediaPlayer == null)
initMediaPlayer();
try {
if (mediaPlayer.isPlaying())
mediaPlayer.stop();
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
private void initMediaPlayer() {
try {
AssetFileDescriptor afd = getContext().getAssets().openFd("music/number_tap.m4a");
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IOException e) {
e.printStackTrace();
}
}
I call the playSound
method every time the button is clicked. It works well as long as there is only one button on screen. No problem at all.
It crashes if I have more buttons on the screen and I press the first button a couple of times (works) and then some other button 2 times (crashes on the second press of the second button).
Any idea what could be wrong? Here's the crash stacktrace.
FATAL EXCEPTION: main Process: com.matejhacin.multiflow, PID: 20991 java.lang.IllegalStateException at android.media.MediaPlayer._prepare(Native Method) at android.media.MediaPlayer.prepare(MediaPlayer.java:1163) at com.matejhacin.multiflow.views.KeyButtonView.playSound(KeyButtonView.java:126) at com.matejhacin.multiflow.views.KeyButtonView.onTouch(KeyButtonView.java:77)
Upvotes: 0
Views: 112
Reputation: 671
From what I can see, you have your own implementation of that button KeyButtonView.java, and in that class you have mediaPlayer as a member variable, so when you have two buttons, respectively you have two instances of KeyButtonView class and two instances of mediaPlayer. Why don't you use one instance of mediaPlayer, let's say you make it static, and make playSound() and initMediaPlayer() methods synchronized and static, this should be a quick and simple change, just to test if there is the issue. And something else, you use onTouch() to handle a click, why don't you try with OnClickListener? If you do not use onTouch properly you will end with bunch of calls on the UI thread, and each blocking at prepare(), this is not good. Once you fix this issue, you should consider rewrite it with prepareAsync() and setOnPreparedListener().
Upvotes: 2