react-native-sound: [Android] java.lang.RuntimeException - Possible Race Condition

I’ve just observed this Crash in the wild - i could imagine that it could be some sort of Race Condition or maybe both - onError and onCompletion - is called at a certain condition.

Fatal Exception: java.lang.RuntimeException: Illegal callback invocation from native module. This callback type only permits a single invocation from native code.
       at com.facebook.react.bridge.CallbackImpl.invoke(CallbackImpl.java:32)
       at com.zmxv.RNSound.RNSoundModule$1.onCompletion(RNSoundModule.java:81)
       at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:2538)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:135)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:196)
       at java.lang.Thread.run(Thread.java:818)

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 32 (10 by maintainers)

Commits related to this issue

Most upvoted comments

Faced the same issue and figured out that this only happens (so far is I could check this for now) when two ore more sounds are played at the same time. So I used the callback of play to workaround this in my js code - maybe this will help you:

../helper/Sound.js:

import Sound from 'react-native-sound';

Sound.setCategory('Ambient');

let soundPlaying = false;

const soundLoadedCallback = (error) => {
    // ...
};

const soundPlayedCallback = (success) => {
    soundPlaying = false;
};

const beep_off = new Sound('beep_off.wav', Sound.MAIN_BUNDLE, soundLoadedCallback);
const beep_on  = new Sound('beep_on.wav',  Sound.MAIN_BUNDLE, soundLoadedCallback);


export default class SoundManager {
    static allowedToPlay() {
        if (soundPlaying) {
            console.log('Prevented sound from playing');

            return false;
        }

        soundPlaying = true;

        return true;
    }

    static flashLightOff() {
        if (SoundManager.allowedToPlay()) {
            beep_off.play(soundPlayedCallback);
        }
    }

    static flashLightOn() {
        if (SoundManager.allowedToPlay()) {
            beep_on.play(soundPlayedCallback);
        }
    }

    // ...
}

So in my case I can call Sound.flashLightOn() (import Sound from '../helper/Sound';) as often as I want but it is only one sound played at the same time - this seems to workaround this issue.