017:RN音频播放

请添加图片描述

  • 导入
yarn add react-native-sound
yarn add @react-native-community/slider
  • 工具类sound.ts
 import Sound from 'react-native-sound'

// 在静音模式下启用播放
Sound.setCategory('Playback');

let sound: Sound;

const initPlayer = (filepath: string) => {
    return new Promise((resolve, reject) => {
        sound = new Sound(filepath, undefined, error => {
            if (error) {
                console.log('初始播放器失败', error);
                reject(error);
            } else {
                console.log('初始播放器成功');
                resolve(sound);
            }
        });
    });
};
/**
 * 
 * @returns 开始播放,直到播放完成才会返回
 */
const playComplete = () => {
    return new Promise((resolve, reject) => {
        if (sound) {
            sound.play(success => {
                if (success) {
                    console.log('播放完了');
                    resolve(sound);
                } else {
                    console.log('播放失败');
                    reject();
                }
                //释放资源
                sound.release()
            });
        } else {
            console.log('播放失败222');
            reject();
        }
    });
};

//释放
const playRelease = () => {
    if (sound) {
        console.log('释放');
        sound.release()
    }
}

//暂停
const playPause = () => {
    return new Promise<void>((resolve, reject) => {
        if (sound) {
            sound.pause(() => {
                console.log('暂停');
                resolve();
            });
        } else {
            console.log('暂停失败');
            reject();
        }
    });
};

//停止
const playStop = () => {
    return new Promise<void>((resolve, reject) => {
        if (sound) {
            sound.stop(() => {
                console.log('停止');
                resolve();
            });
        } else {
            console.log('停止失败');
            reject();
        }
    });
};

const getCurrentTime = () => {
    return new Promise((resolve, reject) => {
        if (sound && sound.isLoaded()) {
            sound.getCurrentTime(seconds => {
                resolve(seconds);
            });
        } else {
            reject();
        }
    });
};

//获取音频时长

const getDuration = () => {
    if (sound) {
        return sound.getDuration()
    }
    return 0
}

//设置播放位置
const setCurrentTime = (value: number) => {
    if (sound) {
        sound.setCurrentTime(value)
    }
}

//音频播放
export { initPlayer, playComplete, playPause, playStop, playRelease, setCurrentTime, getCurrentTime, getDuration };

/**
music.play();                // 播放声音
 
music.setVolume(0.5);        // 将音量减半
 
music.setPan(1);             // 英语不过关(这是右声道的意思?)
 
music.setNumberOfLoops(-1);  // 无限循环播放,直到调用stop()
 
music.setCurrentTime(2.5);   // 设置从某一秒开始
 
music.getCurrentTime(seconds);// 获取当前播放点的秒数
 
music.pause();               // 暂停
 
music.stop(()=>{
    music.play();
});                          // 停止播放并重新开始,不想重新开始取掉music.play()就可以
 */
  • 格式化时间
const getTimeString = (seconds: number) => {
    const m = parseInt((seconds % (60 * 60)) / 60 + '', 10);
    const s = parseInt((seconds % 60) + '', 10);
    return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
}
  • 播放页面
import React, { Component } from 'react';
import { RouteProp } from '@react-navigation/native';
import { RootStackNavigation, RootStackParamList } from '@/navigator/index';
import { View, StyleSheet, Image, Text } from 'react-native';
import { getAudioDetail } from '@/pages/home/audiodetail/service'
import { AudioDetailType } from '@/pages/home/audiodetail/data'
import { initPlayer, playComplete, playPause, playStop, setCurrentTime, getCurrentTime, getDuration, playRelease } from '@/utils/sound'
import Touchable from '@/components/touchable';
import IconFont from '@/assets/iconfont';
import { pTd, getTimeString } from '@/utils/index'
import Slider from '@react-native-community/slider';

type Iprops = {
    route: RouteProp<RootStackParamList, 'AudioDetail'>
    navigation: RootStackNavigation,
}
//确定state类型
type IState = {
    detailDatas: AudioDetailType,
    playState: 'playing' | 'paused' | 'finish' | String; // 是否显示播放按钮
    timer: any,
    sliderValue: number,
    sliderTime: string
}
//Component 的泛型第一个指的是接口类型,第二个指的是 state中的类型
class AudioDetail extends Component<Iprops, IState>{
    state = {
        detailDatas: {
            id: '',
            title: '',
            thumbnailUrl: '',
            soundUrl: ''
        },
        playState: 'paused', // 是否显示播放按钮
        timer: undefined,
        sliderValue: 0,
        sliderTime: '00:00'
    }
    componentDidMount() {
        this.onCreateFun()
        this.listenAudio()
    }
    componentWillUnmount() {
        const { timer } = this.state
        if (timer) {
            clearInterval(timer)
        }
        playStop().then(res => {
            playRelease()
        })

    }
    //定时任务:监听当前播放时间
    listenAudio = () => {
        let timer = setInterval(() => {
            const { playState } = this.state
            if (playState !== 'playing') return
            getCurrentTime()
                .then(seconds => {
                    if (playState !== 'playing') return
                    console.log(seconds)
                    this.setState({
                        sliderValue: Number(seconds),
                        sliderTime: getTimeString(Number(seconds))
                    })
                }).catch(err => {

                })
        }, 1000);
        this.setState({
            timer
        })
    }

    onCreateFun = async () => {
        const { route: { params: { id } }, navigation } = this.props
        const response = await getAudioDetail({ id }).catch(err => {
            //如果错误需要特殊处理,可在此处处理
            console.log('出错了', err)
        })
        if (response && response instanceof Object) {
            const { data, data: { soundUrl } } = response
            this.setState({
                detailDatas: { ...data }
            })
            navigation.setOptions({
                headerTitle: data.title
            })
            initPlayer(soundUrl).then(res => {

                this.setState({
                    playState: 'playing'
                })
                playComplete().then(res => {
                    //播放完了
                    this.setState({
                        playState: 'finish',
                        sliderValue: 0,
                        sliderTime: '00:00'
                    })
                }).catch(() => {
                    this.setState({
                        playState: 'paused'
                    })
                })
            }).catch(res => {
                this.setState({
                    playState: 'paused'
                })
            })
        }
    }

    render() {
        const { detailDatas, playState, sliderValue, sliderTime } = this.state
        return (
            <View style={styles.container}>
                <View style={styles.imageView}>
                    {
                        detailDatas.thumbnailUrl ? (
                            <Image style={styles.thumbnailUrl} source={{
                                uri: detailDatas?.thumbnailUrl
                            }} />
                        ) : null
                    }
                </View>
                <View style={styles.sliderView}>
                    <View style={styles.sliderTimeView}>
                        <Text style={styles.sliderTime}>{sliderTime}</Text>
                    </View>
                    <Slider
                        style={styles.slider}
                        minimumValue={0}
                        value={sliderValue}
                        thumbTintColor='#FF0000'
                        maximumValue={getDuration()}
                        minimumTrackTintColor="#FF0000"
                        maximumTrackTintColor="#cccccc"
                        onSlidingComplete={(value) => {
                            if (playState === 'playing') {
                                setCurrentTime(value)
                            } else if (playState === 'finish') {
                                initPlayer(detailDatas.soundUrl).then(res => {
                                    this.setState({
                                        playState: 'playing'
                                    })
                                    setCurrentTime(value)
                                    playComplete().then(res => {
                                        //播放完了
                                        this.setState({
                                            playState: 'finish',
                                            sliderValue: 0,
                                            sliderTime: '00:00'
                                        })
                                    }).catch(() => {
                                        this.setState({
                                            playState: 'paused'
                                        })
                                    })
                                }).catch(res => {
                                    this.setState({
                                        playState: 'paused'
                                    })
                                })
                            } else {
                                this.setState({
                                    playState: 'playing'
                                })
                                setCurrentTime(value)
                                playComplete().then(res => {
                                    //播放完了
                                    this.setState({
                                        playState: 'finish',
                                        sliderValue: 0,
                                        sliderTime: '00:00'
                                    })
                                }).catch(() => {
                                    this.setState({
                                        playState: 'paused'
                                    })
                                })
                            }
                        }}
                    />
                    <View style={styles.durationView}>
                        <Text style={styles.duration}>{getTimeString(getDuration())}</Text>
                    </View>
                </View>
                <View style={styles.playBtn}>
                    <Touchable onPress={() => {
                        if (playState === 'playing') {
                            playPause().then(res => {
                                this.setState({
                                    playState: 'paused'
                                })
                            })
                        } else if (playState === 'finish') {
                            initPlayer(detailDatas.soundUrl).then(res => {
                                this.setState({
                                    playState: 'playing'
                                })
                                playComplete().then(res => {
                                    //播放完了
                                    this.setState({
                                        playState: 'finish',
                                        sliderValue: 0,
                                        sliderTime: '00:00'
                                    })
                                }).catch(() => {
                                    this.setState({
                                        playState: 'paused'
                                    })
                                })
                            }).catch(res => {
                                this.setState({
                                    playState: 'paused'
                                })
                            })
                        } else {
                            this.setState({
                                playState: 'playing'
                            })
                            playComplete().then(res => {
                                //播放完了
                                this.setState({
                                    playState: 'finish'
                                })
                            }).catch(() => {
                                this.setState({
                                    playState: 'paused'
                                })
                            })
                        }
                    }}>
                        <IconFont name={playState === 'playing' ? 'iconzanting' : 'iconkaishi'} color={'#f00'} size={56} />
                    </Touchable>
                </View>

            </View>
        );
    }
}
const styles = StyleSheet.create({
    container: {
    },
    imageView: {
        padding: pTd(25),
    },
    thumbnailUrl: {
        height: pTd(600),
        borderRadius: pTd(20),
        backgroundColor: 'red',
    },
    sliderView: {
        paddingTop: pTd(10),
        paddingRight: pTd(40),
        paddingLeft: pTd(40),
        flexDirection: 'row',
        alignItems: 'center'
    },
    sliderTimeView: {},
    sliderTime: {
        fontSize: pTd(28),
        color: 'red'
    },
    durationView: {

    },
    duration: {
        fontSize: pTd(28),
        color: '#000000'
    },
    slider: {
        flex: 1,
        height: pTd(30),
        borderRadius: pTd(10)
    },
    playBtn: {
        marginTop: pTd(20),
        alignItems: 'center',
    },


})
export default AudioDetail;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值