0

I have two button and it will play a sound to notify about right choice, or wrong one. This is how I do it:

MediaPlayer playError = MediaPlayer.create(QuizActivity.this, R.raw.error);
playError.start();

Same with correct sound. It works fine most of the time, but when I click it many times, at random times I get this error:

Basically it says line playError.start(); gives me NullPointerException (only sometimes)

07-21 23:05:32.767: ERROR/PlayerDriver(1287): Command PLAYER_PREPARE completed with an error or info PVMFErrResource, -17
07-21 23:05:32.767: ERROR/MediaPlayer(14449): error (1, -17)
07-21 23:05:32.767: ERROR/MediaPlayer(14449): MEDIA_ERROR(mPrepareSync) signal application thread
07-21 23:05:32.777: ERROR/AndroidRuntime(14449): FATAL EXCEPTION: main
07-21 23:05:32.777: ERROR/AndroidRuntime(14449): java.lang.NullPointerException
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at com.quiz.QuizActivity.falseAnswerPoints(QuizActivity.java:148)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at com.quiz.QuizActivity$5.onClick(QuizActivity.java:86)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.view.View.performClick(View.java:2408)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.view.View$PerformClick.run(View.java:8816)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.os.Handler.handleCallback(Handler.java:587)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.os.Looper.loop(Looper.java:123)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at android.app.ActivityThread.main(ActivityThread.java:4627)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at java.lang.reflect.Method.invokeNative(Native Method)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at java.lang.reflect.Method.invoke(Method.java:521)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
07-21 23:05:32.777: ERROR/AndroidRuntime(14449):     at dalvik.system.NativeStart.main(Native Method)

Edit:

Line is 148: playError.start();

And falseAnswerPoints() is:

public void falseAnswerPoints() {
    MediaPlayer playError = MediaPlayer.create(QuizActivity.this, R.raw.error);
    playError.start();
}

Same is correctAnswerPoints, but with different sound. That's about it. Sometimes it gives NullPointerException with one, sometimes with another...

Answer:

MediaPlayer playSuccess = MediaPlayer.create(QuizActivity.this, R.raw.success);
playSuccess.start();
playSuccess.setOnCompletionListener(new OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer playSuccess) {
        playSuccess.release();
    }
});
Badr Hari
  • 8,114
  • 18
  • 67
  • 100

3 Answers3

1

It seems the MediaPlayer cannot be created, the create() method returning a null pointer. The official doc says this happens when the creation fails, with no further details.

You said this happens when you click several times in a row on the button that leads this method to be called. This is probably due to a non reentrancy issue.

You should try to surround the MediaPlayer creation and usage by a flag that would prevent reentrancy:

public void falseAnswerPoints() {
    if (!mPlayingSound) {
        mPlayingSound = true;

        MediaPlayer playError = MediaPlayer.create(QuizActivity.this, R.raw.error);
        playError.start();
    }
}

mPlayingSound being a private boolean member initialized to false and that you would reset to false once the MediaPlayer would have finished playing (using public void setOnCompletionListener (MediaPlayer.OnCompletionListener listener) should be fine, although I am not sure whether it is called in case of abnormal or anticipated termination of the play).

EDIT: There is a NullPointerException so there is a stack trace. To capture the stack trace, in debug only (the code below is not suitable for release), you can do as follows:

public void falseAnswerPoints() {
    try {
        MediaPlayer playError = MediaPlayer.create(QuizActivity.this, R.raw.error);
        playError.start();
    }
    catch (NullPointerException e) {
        // Set a breakpoint there to inspect the state of your app
        // Then rethrow the exception to have it logged, and why not
        // log extra info.
    }
}
Shlublu
  • 10,917
  • 4
  • 51
  • 70
  • I already did something like this, but this doesnt seem to work. I only get an error when I debug the app with my phone. I have currently only one Android phone to test with. With an emulator I am not able to reproduce the error... – Badr Hari Jul 21 '11 at 20:35
  • In that case, I suggest setting a conditional breakpoint that would act when playError is null. Did you manage to come to a scenario that makes the bug 100% reproduceable (such as "clicking 10 times in a row", or stng like this)? – Shlublu Jul 21 '11 at 20:38
  • Yes, the bug is reproduceable by clicking things in row. It doesnt matter how fast... but usually around 10 clicks. It's not always the same number. Now I was able to get same error with emulator also. With emulator it also gives me errors like: 07-21 20:39:24.770: ERROR/AudioService(67): Media server died. 07-21 20:39:28.890: ERROR/AudioService(67): Media server started. I also tried try catch to find an excpetion, but it doesnt give me anything... but thanks for thinking with my about my problem, Shlubu ☺ – Badr Hari Jul 21 '11 at 20:43
  • You are welcome! This kind of issue is annoying. As there is a NullPointerEXception there is a stack trace. I've edited my answer above to suggest a way to capture it and to inspect the state of the app at the same time. – Shlublu Jul 21 '11 at 20:52
  • Thank you again, Shlublu, thx to your ideas I got it working... I am using MediaPlayer.OnCompletionListener to realese the audio and this seems to do the trick. I added the code to my question... – Badr Hari Jul 21 '11 at 20:53
  • Yipii \o/ Good news ! Too bad for the NPE. Maybe I should have suggested Exception instead of NullPointerException. – Shlublu Jul 21 '11 at 20:54
0

I'm afraid all answers here are wrong. I encountered this issue, albeit more than a year later, but after some research found the answer. It's in two parts.

  1. Best to start the mediaplayer AFTER the declaration of the onCompleteListener. This insures that the mediaplayer has a full list of instructions declared before it even start playing.
  2. Use a statically declared object called an AtomicBoolean. This insures that there is only one boolean parameter, and that the process is locked until it finishes the process. This is the only way to insure a process is thread safe.

Hope you found this useful (all future programmers that encounter this problem) ;-)

iDev
  • 23,310
  • 7
  • 60
  • 85
user1487034
  • 13
  • 1
  • 6
-3

To solve your problem you can try to write a permission <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

in manifest

Prashant Kumar
  • 20,069
  • 14
  • 47
  • 63
sergannn
  • 11
  • 2