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