react-native-sound icon indicating copy to clipboard operation
react-native-sound copied to clipboard

Sounds won't stop - Android

Open javoescan opened this issue 7 years ago • 10 comments

In Android Marshmallow (6.0) whenever I play sound and then stop it, not only it won't stop but also it would loop itself and overlap with the next sound. The weird thing is that in Lollipop it doesn't happen. I'm using the same code. "react-native": "^0.46.1", "react-native-sound": "^0.10.3", Thank you!

javoescan avatar Sep 14 '17 17:09 javoescan

find anything here @javoescan ?

aaronbuchanan avatar Sep 21 '17 17:09 aaronbuchanan

Can you post your code?

gvenk avatar Sep 26 '17 09:09 gvenk

Same issue 👍 (Android v6.0.1)

gaboelnuevo avatar Sep 29 '17 07:09 gaboelnuevo

My code is _playLocal(audioUri){ console.log('playing... ' + audioUri); var sound = new Sound(audioUri.replace('file://', ''), '', (error) => { console.log(sound.isLoaded()); if (sound.isLoaded()) { sound.setVolume(1); //sound.setNumberOfLoops(1); } if (error) { console.log('failed to load the sound', error); return; } // loaded successfully console.log('loops: ' + sound.getNumberOfLoops()); console.log('duration in seconds: ' + sound.getDuration() + 'number of channels: ' + sound.getNumberOfChannels()); this.setState({ status: 'PLAYING', localSound: sound }, () => { // Play the sound with an onEnd callback this.state.localSound.play((success) => { if (success) { this.setState({ status: 'FINISHED', localSound: null, }, () => { //this._next(); }); console.log('successfully finished playing'); } else { console.log('playback failed due to audio decoding errors'); // reset the player to its uninitialized state (android only) // this is the only option to recover after an error occured and use the player again //sound.reset(); } console.log('...'); sound.release(); }); }); }); }

gaboelnuevo avatar Sep 29 '17 07:09 gaboelnuevo

Hi apparently the problem is while playing ogg files.

See: https://stackoverflow.com/questions/12834727/android-loop-true-how-to-avoid-mediaplayer-looping-audios-with-this-metadat

gaboelnuevo avatar Sep 29 '17 17:09 gaboelnuevo

I know it's a bit late but I had the same problem and solved it by changing player.pause(); to player.stop(); on react-native-sound/android/src/main/java/com/zmxv/RNSound/RNSoundModule.java stop method.

I changed this: @ReactMethod public void stop(final Integer key, final Callback callback) { MediaPlayer player = this.playerPool.get(key); if (player != null && player.isPlaying()) { player.pause(); player.seekTo(0); } callback.invoke(); }

to this:

@ReactMethod public void stop(final Integer key, final Callback callback) { MediaPlayer player = this.playerPool.get(key); if (player != null && player.isPlaying()) { player.stop(); player.seekTo(0); } callback.invoke(); }

and now everything works fine!! Hope it helps someone.

@zmxv maybe you can check this out. I'd be glad to submit a PR if you want.

gisellezeitoune avatar Oct 26 '17 12:10 gisellezeitoune

I'm using mp3's and have this problem on Android 7.1.1. I tried the above and it didn't fix it for me unfortunately

Jarrio avatar Nov 03 '17 22:11 Jarrio

Hi guys, I have the same problem. I solved it by @gisellezeitoune 's way but the sound stop and cannot be played again, I am using Android Virtual Device of Android Studio, Nexus 4 API 23.

Later on, I solved it by a strange way. Whenever I stop the sound, I seek it to 1 minute because all of my sounds only last for a few seconds. This is my code change in RNSoundModule.java

@ReactMethod
public void stop(final Double key, final Callback callback) {
  MediaPlayer player = this.playerPool.get(key);
  if (player != null && player.isPlaying()) {
//      player.pause();
    player.seekTo(60000);
  }

  // Release audio focus in Android system
  if (!this.mixWithOthers && key == this.focusedPlayerKey) {
    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    audioManager.abandonAudioFocus(this);
  }

  callback.invoke();
}

I know this is not the best solution but hope it can help

LuongTruong avatar Aug 29 '18 07:08 LuongTruong

I don't think there's a stopAll() function. You need to keep track of the instances you create. I use a single global variable. With some logic I can make sure that only one sound is being played at a time.

When you create a new sound object, assign it to a global variable. Before you create a new sound object, stop the sound on global instance Add a null check on the global variable for the first click

var whoosh = new Sound(/storage/sdcard0/Android/data/com.myapp/files/Download/${name}.mp3, '', (error) => { if (error) { alert('failed to load the sound', error); return; } if (global.sound) global.sound.stop(); global.sound = whoosh; whoosh.play( success => { console.log('Playing') } ); } People think global variables bad in JS. If you misuse yes. But this case it really is a global object and there's nothing wrong using it. It's not a misuse.

https://stackoverflow.com/questions/49620303/react-native-sound-stop-all-sounds

busykid avatar May 17 '21 18:05 busykid

I use "react-native-sound": "^0.11.2" and i fixed this problem as below

useEffect(() => {
    const sound = new Sound('tick.mp3', Sound.MAIN_BUNDLE, error => {
      if (error) {
        console.error('Failed to load sound', error);
      } else {
        setMetronomeSound(sound);
      }
    });


    return () => {
      // Release the sound when the component unmounts
      if (metronomeSound) {
        metronomeSound.release();
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

just call if (metronomeSound) { metronomeSound.play(); }

and for stop

const stopPlayMetronome = () => { if (metronomeSound) { metronomeSound.stop(); } };

ahmeturganci avatar Jan 14 '24 16:01 ahmeturganci