I have audio files hosted on a server that I'd like my app to access after authenticating. Users send a GET request which includes an authentication token, and the server returns the binary audio data.
As far as I can see there is no way to save this 'blob' as an audio file to the filesystem. The current implementation of fetch in react-native doesn't support blobs: link
... and the ideally-suited react-native-fetch-blob library isn't supported in expo either: link
Additionally I can see no way of streaming the audio file from the server. The included audio library with expo allows streaming of audio from a url (e.g. http://example.com/myaudio.mp3) however I can't see any way to attach an authorisation header to the request (e.g. "Authorization": "Bearer [my-token]").
Is there a way of achieving this, either by downloading and saving the audio blob, or streaming from a url with an authorisation header included in the request? I could detach my project from Expo but I'd like to leave that as a last-resort.
Yes, it is. You need to use the Audio module exposed by expo to do it. Below are the steps that you have to follow to load and play an audio file from a given URL. I've also copied over the code for my component that is doing the same for me.
Load Audio module exposed by expo
import { Audio } from 'expo'
Create a new sound Object from it
soundObject = new Audio.Sound()
Asynchronously load your file
await this.soundObject.loadAsync({ uri: this.props.source })
Once loaded play the loaded file using
this.soundObject.playAsync()
Below is a simple component that I wrote for doing it -
import React, { Component } from 'react';
import { View, TouchableNativeFeedback } from 'react-native';
import { Audio } from 'expo';
class AudioPlayer extends Component {
  constructor(props) {
    super(props);
    this.state = { isPlaying: false };
    this.loadAudio = this.loadAudio.bind(this);
    this.toggleAudioPlayback = this.toggleAudioPlayback.bind(this);
  }
  componentDidMount() {
    this.loadAudio();
  }
  componentWillUnmount() {
    this.soundObject.stopAsync();
  }
  async loadAudio() {
    this.soundObject = new Audio.Sound();
    try {
      await this.soundObject.loadAsync({ uri: this.props.source /* url for your audio file */ });
    } catch (e) {
      console.log('ERROR Loading Audio', e);
    }
  }
  toggleAudioPlayback() {
    this.setState({
      isPlaying: !this.state.isPlaying,
    }, () => (this.state.isPlaying
      ? this.soundObject.playAsync()
      : this.soundObject.stopAsync()));
  }
  render() {
    return (
      <TouchableNativeFeedback onPress={this.toggleAudioPlayback}>
        <View style={this.props.style}>
          {this.props.children}
        </View>
      </TouchableNativeFeedback>
    );
  }
}
export default AudioPlayer;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With