0

I want to play long audio files from the list, the files are downloaded on first tap, all next taps play the audio. But the problem is that when playing one file and I tap another, the first one is still playing and the next one is playing too. Is there a way to stop all currently playing files when I tap any list item?

 onPressHandler = (file, title) => {
    let name = file.substring(file.lastIndexOf("/") + 1);

    RNFetchBlob.fs.exists(`/storage/sdcard0/Android/data/com.myapp/files/Download/${name}.mp3`)
        .then((exist) => {
            if (exist) {
                /* I want to stop all playing audios here */
                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;
                    }
                    alert('duration in seconds: ' + whoosh.getDuration() + 'number of channels: ' + whoosh.getNumberOfChannels());
                    alert(whoosh.isLoaded());

                    whoosh.play((success) => {
                        if (success) {
                            alert('successfully finished playing');
                        } else {
                            alert('playback failed due to audio decoding errors');
                            whoosh.reset();
                        }
                    });
                });
            } else {
                const url = `http://myresourcesite/${file}.mp3`;
                const headers = {};
                const config = {
                    downloadTitle: name,
                    downloadDescription: 'Downloading ...',
                    saveAsName: `${name}.mp3`,
                    allowedInRoaming: true,
                    allowedInMetered: true,
                    showInDownloads: true
                };
                downloadManager.download(url, headers, config).then((response) => {
                    alert('Download success!');
                }).catch(err => {
                    alert('Download failed!');
                });
            }
        })
        .catch(() => {
            alert('error has occured');
        });
}
user9581969
  • 1
  • 1
  • 2

2 Answers2

1

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.

0

As you describe, I think you need to play only one sound at time. Maybe you can verify if player isPlaying().

  mySound = null;

  PlayLocalSoundFile = (nombreSonido) => {
    if(this.mySound != null){
      if(this.mySound.isPlaying()){
        this.mySound.stop();//Lo detiene si hay otro tocando
      }
    }
    Sound.setCategory('Playback');
    this.mySound = new Sound('./' + nombreSonido, Sound.MAIN_BUNDLE, (error) => {
      if (error) {
        console.log('Error loading sound: ' + error);
        return;
      } else {
        this.mySound.play((success) => {
          if (success) {
            console.log('End playing ' + nombreSonido)
          } else {
            console.log('Issue playing file' + nombreSonido);
          }
        })
      }
    });
    this.mySound.setVolume(0.9);
    this.mySound.release();
  }