使用 工具 rn-fetch-blob 下载
使用 react native sound 播放
贡献代码
import Reactfrom 'react';
import {
StyleSheet,
Image,
View,
Text,
TouchableOpacity,
Alert
}from 'react-native';
import Sound from 'react-native-sound';
import RNFS from "react-native-fs";
import RNFetchBlobfrom 'rn-fetch-blob'
import FastImage from 'react-native-fast-image'
// const MAIN_DIR = RNFetchBlob.fs.dirs.CacheDir;
const RegHttp = /^http:\/\/|^https:\/\//;
const MAIN_DIR = Sound.DOCUMENT;
const MAIN_URL = this.props;
export default class MessageAudio extends React.Component {
constructor(props) {
super(props);
this.state = {
currentMessage: this.props.item,
playing: false,
currentTime: 0,
duration: this.props.item.length || 0,
progressNum:0
};
this.sound = null;
this._isMounted = false;
}
componentWillReceiveProps(nextProps) {
// console.log('点击吓一条语音',nextProps)
if (nextProps.item !== this.state.currentMessage) {
this.setState({
duration: nextProps.item.length
})
}
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
fetchRemoteFile = (url,filename,callback)=> {
return RNFetchBlob
.config({
useDownloadManager : true,
path: `${MAIN_DIR}/${filename}`,//文件存放地址
// path: `${MAIN_DIR}/`, //文件存放地址
fileCache:true,
// appendExt: '.wav'
})
.fetch('GET',url, {})
.then(res => {
console.log('!!!!!!!!!!!!!!!!!!!',res);
console.log('这个音频文件保存到 了====> :',res.path());
callback(res.path())
})
.catch((errorMessage,statusCode)=> {
// error handling
})
}
downloadFile=(url,filename,callback)=> {
// const downloadDest = `${RNFS.MainBundlePath}/${'chatMessageAudio'}/${this.props.item.to}/${((Math.random() * 1000) | 0)}.mp3`;
const downloadDest = `${MAIN_DIR}/chatMessageVoice/`;
const options = {
fromUrl: url,
toFile: downloadDest,
background: true,
begin: (res)=> {
console.log('begin',res);
console.log('contentLength:',res.contentLength/ 1024 / 1024,'M');
},
progress: (res)=> {
let pro = res.bytesWritten/ res.contentLength;
this.setState({
progressNum: pro,
});
},
headers : {
'Accept': 'audio/amr'
}
};
try {
console.log('12121',options);
const ret = RNFS.downloadFile(options);
ret.promise.then(res => {
console.log('语音下载成功success',res);
console.log('文件大下载地址是file:/' + downloadDest);
callback(downloadDest)
}).catch(err => {
console.log('err',err);
callback('error')
});
}
catch (e) {
console.log(error);
}
}
tick = ()=> {
if (!this._isMounted) {
return
}
this.sound.getCurrentTime((seconds)=> {
if (this.tickInterval) {
let currentTime = Math.floor(seconds);
if (currentTime >= this.state.duration) {
currentTime = this.state.duration;
}
this.setState({
currentTime: currentTime,
},_ => {
if (this.state.currentTime >= this.state.duration) {
this.setState({
playing: false
})
}
});
}
});
};
play = ()=> {
console.warn('11111已经加载完成');
if (!this._isMounted) {
return
}
console.warn('22222播放状态this.state.playing',this.state.playing);
// if (this.state.playing) {
// this.stop();
// return;
// }
console.warn('33333设置间隔');
// this.tickInterval = setInterval(() => {
// this.tick()
// }, 250);
console.warn('44444');
Sound.setCategory('Playback');
this.setState({
playing: true
});
if (RegHttp.test(this.props.item.url)) {
// this.downloadFile(this.props.item.url,this.props.item.filename,response=>{
this.fetchRemoteFile(this.props.item.url,this.props.item.ext.filename,response=>{
if (response=='error'){
console.warn('下载失败了,请重试');
}else {
console.log('我已经下载好了 文件 可以播放了',response)
setTimeout(()=> {
//https://cimili-cdn-audio-of-word.cimili.com/uploads/audio/mp3/us/abandon.mp3
// console.log('我要播放的是','\n',Sound.MAIN_BUNDLE,'\n',Sound.DOCUMENT,'\n',Sound.CACHES,'\n',this.props.item.filename,'\n',MAIN_DIR)
let souneName = response.substring(response.lastIndexOf('/')+ 1,response.length);
this.sound = new Sound(souneName,MAIN_DIR, (error)=> {
if (error) {
console.warn(error)
}else {
console.log('播放准备',souneName);
setTimeout(()=> {
this.sound.play((success)=> {
if (this.tickInterval) {
clearInterval(this.tickInterval);
this.tickInterval = null;
}
if (!success) {
Alert.alert('播放失败');
}
});
},100);
console.warn('77777')
if (!this.state.duration) {
this.setState({
duration: Math.floor(this.sound.getDuration())
});
}
}
});
},100)
}
})
}else {
console.log('播放本地的录音',this.props.item.url)
let souneName = this.props.item.url.substring(this.props.item.url.lastIndexOf('/')+ 1,this.props.item.url.length);
this.song = new Sound(souneName, Sound.DOCUMENT, (error)=> {
if (error){
console.error('播放错误',error)
}else {
this.song.play((success)=>{
if (this.tickInterval) {
clearInterval(this.tickInterval);
this.tickInterval = null;
}
});
if (!this.state.duration) {
this.setState({
duration: Math.floor(this.sound.getDuration())
});
}
}
});
}
};
stop = ()=> {
if (!this._isMounted) {
return
}
if (this.sound) {
if (this.tickInterval) {
clearInterval(this.tickInterval);
this.tickInterval = null;
}
this.sound.stop(()=> {
this.setState({playing: false});
});
}
};
onLongPress() {
alert('1');
if (this.props.onMessageLongPress) {
this._root.measureInWindow((x,y,width,height)=> {
this.props.onMessageLongPress({
x: x,
y: y,
width: width,
height: height
},this.props.item);
})
}
}
render() {
let msg = this.props.item;
let image = "";
if (this.state.playing) {
image = msg.isOutgoing ? require("../../../images/ic_senderVoice.png"):
require("../../../images/ic_receiverVoice.png");
}else {
image = msg.isOutgoing? require("../../../images/ic_senderVoice.png"):
require("../../../images/ic_receiverVoice.png");
}
//max 180
let margin = (parseFloat(msg.length)/ 1000)* 3;
margin = Math.min(180,margin)+ 10;
return (
ref={component => this._root = component}
onPress={this.play}
onLongPress={this.onLongPress.bind(this)}
style={[styles.container, {
width: 40 + (msg.length)* 2
}]}>
style={[styles.image,msg.isOutgoing ? {marginLeft: margin}: {marginRight: margin}, {tintColor: msg ? 'white' : '#999'}]}
source={image}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
flex: 1,
alignItems: 'center',
maxWidth: 120
},
image: {
marginTop: 5,
marginBottom: 5,
marginLeft: 10,
marginRight: 10,
width: 20,
height: 20,
tintColor: 'white'
}
});