Skip to content
Matheus Alves edited this page May 15, 2019 · 25 revisions

The Sound Module

This module allow you to perform sound on media stream of the device, as well as having control over the volume of that stream.

Print of media stream control

First look

To use this module you will need to import it:

import { Sound } from 'react-native-androide';

The source of the song to be played must be one of these three options:

  • From the resources (Easiest)

In this case the song file must be placed on the res/raw directory: android/app/src/main/res/raw, if the path does not exist you can create. Example: if you want to play the click_effect.mp3 put it on raw dir and call Sound.playNow('click_effect.mp3');.

  • From the Internet

You can play a song directly from the internet if you have the direct link to it, but take care, a buffering will occur before the song start to play. Example: Sound.playNow('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3');.

  • From the File System

If the song is on the device file system you can play it calling Sound.playNow(path);. path must be the full path to the file, for example: Sound.playNow("/data/media/0/Download/good_music.mp3");. Unfortunately this method requires special permission: READ_EXTERNAL_STORAGE, see more bellow.

Note: All the examples uses Sound.playNow(), but this function does not considers the buffering time, see Sound.prepare() and Sound.play() to a better otimization if you song is a big size file or is from the internet.

Note2: All the functions on this module work asynchronously and return Promises.

The easiest way

If you just want to play a song, you can call the Sound.playNow(source). If there are no problems, the song will be played from beginning to end.

Note: This function just executes await Sound.prepare(source) and then Sound.play().

On your marks

Before play a song is recommended prepare(buffering) it. To prepare a song call Sound.prepare(source), source must be like described on session First look.

The Sound.prepare(source) return a promise that resolves with true when the song is ready to play, and, the promise can be rejected for some reasons:

  • If the resources does not exists, in case of source is a resource located in raw dir.
  • If the internet connection is offline, in case of source is a direct link from internet.
  • If you have no access to file system, in case of source is a file from the device disk.

Since there are several ways a song fails to prepare, it is important to take care of those rejections.

let source = 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-7.mp3';

try {
  await Sound.prepare(source);
  Sound.play();
} catch(error) {
  // Work around the error
  console.log(error.message);
}

// OR

Sound.prepare(source)
.then(() => Sound.play())
.catch(error => {
  // Work around the error
  console.log(error.message);
});

Playing

Sound.play();

When the promise of Sound.prepare(source) is already resolved you is able to perform Sound.play(). This functions can not be performed before Sound.prepare(source) or the promise will be rejected.

If the song started playing and no problem occurs, the promise will be resolved with true, but if an error occurs, the promise will be rejected and Sound.prepare(source) must be called again.

Pausing

Sound.pause();

If the sound is playing you can pause the execution and resume later. Just call Sound.pause() and then Sound.play() again to resume. If the module is not ready(Promise from Sound.prepare() is not resolved) the promise returned will reject.

Stoping

Sound.stop();

This function is very similar to previous(pause), the difference is that once called, Sound.play() will not work again. You must call Sound.repare() first. This function free the memory used to allocate the resource.

Getting position of playback

let positionOfCursor = await Sound.getCurrentPosition();
/*do something*/

// OR

Sound.getCurrentPosition().then(positionOfCursor => {/*do something*/});

With this function you can get the position(in milliseconds) of the cursor on the song currently playing. But it can only be called when the music is already loaded with Sound.prepare() or is playing with Sound.playNow() or Sound.play(). Otherwise the promise will be rejected.

Getting dutarion of song

let durationOfSong = await Sound.getDuration();
/*do something*/

// OR

Sound.getDuration().then(durationOfSong => {/*do something*/});

This function is similar to previous, but returns the complete duration of the song in milliseconds. The promise will be rejected if Sound.prepare () has not yet been called successfully.

Set the volume

Sound.setVolume(0.5);

Set the volume of song playing. The value must be on range of 0 to 1. If the Sound.prepare() has not been called yet the promise of this function will reject. Note: the initial volume is max(1.0).

Seeking

// Both cases position the music playback cursor in 10 seconds
await Sound.seekTo(10000);
/*do something*/

// OR

Sound.seekTo(10000).then(r => {/*do something*/});

This function reposition the cursor on a determinated position in milleconds. If a negative number is provided the cursor go to 0 and if a number grather than Sound.getDuration() is provided the cursor go to Sound.getDuration().

Listener to music finished playing

soundFinishedListener = null;

//...

someFunction() {
  this.soundFinishedListener = Sound.setOnCompletionListener(() => {
    /* Do something when the sound finished playing */
  });
}

//...

componentWillUnmount() {
  if(this.soundFinishedListener !== null) {
    this.soundFinishedListener.remove();
  }
}

Sound.setOnCompletionListener() register a callback function that is performed when any song is finished. It's important remove listener when component will be destroyed.

Other useful functions

Getting Audio Focus

Requires Android 8.0 (API level 26), otherwise the promise will be rejected.

Sound.getAudioFocus();

This function make any other player currently playing stop, then your music will not be playing on top of any other.

Getting System volume of Media

let mediaVolume = await Sound.getSystemVolume();
/*do something*/

// OR

Sound.getSystemVolume().then(mediaVolume => {/*do something*/});

When resolved, the promise give to you a number on range of 0 to 1.

Setting System volume of Media

Sound.setSystemVolume(0.5);

Volume must be on range of 0 to 1. Only the Media Stream Volume will be set. Take care, the promise will reject if the device is on Do Not Disturb mode, see more.

Play song from file system

To play a song from the file system you will need the READ_EXTERNAL_STORAGE permission. To grant the required permission, add this line: <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to the Manifest File located in android\app\src\main\AndroidManifest.xml. If this permission are not guaranteed the promises from Sound.prepare(pathToFile) and Sound.playNow(pathToFile) will be rejected.

In addition it will be necessary ask to the user this permision. To do this you have two option:

  • Use a native module on react-native called PermissionsAndroid.

  • Use the Sound.requestPermission() function.

On this case just call Sound.requestPermission() and if the user grant the permission the promisse will be resolved with true, otherwise the promise will be resolved with false. See example bellow:

if(await Sound.requestPermission()) {
  Sound.playNow("/data/media/0/Download/good_music.mp3");
} else {
  alert('Access Denied to filesystem');
  /* Work around */
}

Clone this wiki locally