Javascript 音频输入为react native时间歇性崩溃

Javascript 音频输入为react native时间歇性崩溃,javascript,ios,react-native,audio,crash,Javascript,Ios,React Native,Audio,Crash,播放音频时崩溃: import React, { Component } from 'react'; var Sound = require('react-native-sound'); Sound.setCategory("Playback"); //Needed for audio to play on IOS devices import { Image, ImageBackground, SafeAreaView, ScrollVi

播放音频时崩溃:

import React, { Component } from 'react';

var Sound = require('react-native-sound');
Sound.setCategory("Playback"); //Needed for audio to play on IOS devices

import {
    Image,
    ImageBackground,
    SafeAreaView,
    ScrollView,
    View,
    Text,
    TouchableOpacity
} from 'react-native';

export default class AudioList extends Component {


    constructor(props) {
        super(props)

    }

    playAudio = (file) => {
        console.log(file)

        if (this.sound) {
            console.log("SOUND")

            try {
                this.sound.release()
            } catch (error) {
                console.log("A sound release error has occured 111")
            } finally {
                this.sound = null
            }
        }

        this.sound = new Sound('audio/' + file, Sound.MAIN_BUNDLE, (error) => {
            if (error) {
                console.log('error', error);
                this.sound = null;
            } else {
                this.sound.play(() => {
                    try {
                        if (this.sound) {
                            this.sound.release()
                        }
                    } catch (error) {
                        console.log("A sound release error has occured 222")
                    } finally {
                        this.sound = null
                    }
                })
            }
        })


        this.willBlurSubscription = this.props.navigation.addListener(
            'blur',
            () => {
                try {
                    if (this.sound) {
                        this.sound.release()
                    }
                } catch (error) {
                    console.log("A sound release error has occured 333")
                } finally {
                    this.sound = null
                }

            }
        )



    }

    componentWillUnmount() {

        try {
            this.willBlurSubscription &&
                this.willBlurSubscription.remove &&
                this.willBlurSubscription.remove()
        } catch (error) {} finally {
            this.willBlurSubscription = null
        }
    }


    render() {

        /* list and new_list removed for brevity */
        /* styles removed for brevity */

        let audio_clips = new_list.map((item, index) => {
            return <View key={index}>
                {item.audio ? 
                    <TouchableOpacity onPress={()=>this.playAudio(item.audio)}>
                        <Image source={require('../assets/images/audio-icon.png')} />
                    </TouchableOpacity>
                    :
                    <View></View>
                }
                <Text>{item.text}</Text>
        </View>
        })



        return (
            <SafeAreaView>
            <Text>{list.category_name}</Text>
            <ImageBackground source={require('../assets/images/background.jpg')}>
                <ScrollView>
                    <View>
                        {audio_clips}
                    </View>
                </ScrollView>
            </ImageBackground>
        </SafeAreaView>
        )



    }
}
我正在创建一个包含多个不同屏幕音频剪辑的应用程序。我们正在使用Testflight在iPhone/iPad上测试该应用程序,播放音频剪辑时会出现间歇性崩溃。音频剪辑本身似乎没有什么问题,因为它们大部分时间都在工作,问题并不总是同一个音频剪辑

我猜这可能与
新声音
有关,但我不确定如何测试这一点。我还认为我通过确保在声音播放后和屏幕卸载时释放声音组件来解决这个问题

在确保正确清理
this.sound
组件时,我是否遗漏了什么

我的代码:

import React, { Component } from 'react';

var Sound = require('react-native-sound');
Sound.setCategory("Playback"); //Needed for audio to play on IOS devices

import {
    Image,
    ImageBackground,
    SafeAreaView,
    ScrollView,
    View,
    Text,
    TouchableOpacity
} from 'react-native';

export default class AudioList extends Component {


    constructor(props) {
        super(props)

    }

    playAudio = (file) => {
        console.log(file)

        if (this.sound) {
            console.log("SOUND")

            try {
                this.sound.release()
            } catch (error) {
                console.log("A sound release error has occured 111")
            } finally {
                this.sound = null
            }
        }

        this.sound = new Sound('audio/' + file, Sound.MAIN_BUNDLE, (error) => {
            if (error) {
                console.log('error', error);
                this.sound = null;
            } else {
                this.sound.play(() => {
                    try {
                        if (this.sound) {
                            this.sound.release()
                        }
                    } catch (error) {
                        console.log("A sound release error has occured 222")
                    } finally {
                        this.sound = null
                    }
                })
            }
        })


        this.willBlurSubscription = this.props.navigation.addListener(
            'blur',
            () => {
                try {
                    if (this.sound) {
                        this.sound.release()
                    }
                } catch (error) {
                    console.log("A sound release error has occured 333")
                } finally {
                    this.sound = null
                }

            }
        )



    }

    componentWillUnmount() {

        try {
            this.willBlurSubscription &&
                this.willBlurSubscription.remove &&
                this.willBlurSubscription.remove()
        } catch (error) {} finally {
            this.willBlurSubscription = null
        }
    }


    render() {

        /* list and new_list removed for brevity */
        /* styles removed for brevity */

        let audio_clips = new_list.map((item, index) => {
            return <View key={index}>
                {item.audio ? 
                    <TouchableOpacity onPress={()=>this.playAudio(item.audio)}>
                        <Image source={require('../assets/images/audio-icon.png')} />
                    </TouchableOpacity>
                    :
                    <View></View>
                }
                <Text>{item.text}</Text>
        </View>
        })



        return (
            <SafeAreaView>
            <Text>{list.category_name}</Text>
            <ImageBackground source={require('../assets/images/background.jpg')}>
                <ScrollView>
                    <View>
                        {audio_clips}
                    </View>
                </ScrollView>
            </ImageBackground>
        </SafeAreaView>
        )



    }
}
import React,{Component}来自'React';
var-Sound=require('react-native-Sound');
Sound.setCategory(“回放”)//需要在IOS设备上播放音频
进口{
形象
图像背景,
安全区域视图,
滚动视图,
看法
文本
可触摸不透明度
}从“反应本机”;
导出默认类AudioList扩展组件{
建造师(道具){
超级(道具)
}
播放音频=(文件)=>{
console.log(文件)
如果(这个声音){
控制台日志(“声音”)
试一试{
this.sound.release()
}捕获(错误){
console.log(“发生声音释放错误111”)
}最后{
this.sound=null
}
}
this.sound=新声音('audio/'+文件,sound.MAIN_BUNDLE,(错误)=>{
如果(错误){
console.log('error',error);
this.sound=null;
}否则{
这个。声音。播放(()=>{
试一试{
如果(这个声音){
this.sound.release()
}
}捕获(错误){
console.log(“发生声音释放错误”)
}最后{
this.sound=null
}
})
}
})
this.willBlurSubscription=this.props.navigation.addListener(
“模糊”,
() => {
试一试{
如果(这个声音){
this.sound.release()
}
}捕获(错误){
console.log(“发生声音释放错误333”)
}最后{
this.sound=null
}
}
)
}
组件将卸载(){
试一试{
这是我的订阅&&
this.willBlurSubscription.remove&&
this.willBlurSubscription.remove()
}捕获(错误){}{
this.willBlurSubscription=null
}
}
render(){
/*为简洁起见,删除了列表和新列表*/
/*为简洁起见,删除了样式*/
让音频剪辑=新建列表.map((项目,索引)=>{
回来
{item.audio?
this.playAudio(item.audio)}>
:
}
{item.text}
})
返回(
{list.category_name}
{音频剪辑}
)
}
}

检查声音是否已经是对象:

if(!this.sound){
   this.sound = new Sound('audio/' + file, Sound.MAIN_BUNDLE, (error) => {
            if (error) {
                console.log('error', error);
                this.sound = null;
            } else {
                this.sound.play(() => {
                    try {
                        if (this.sound) {
                            this.sound.release()
                        }
                    } catch (error) {
                        console.log("A sound release error has occured 222")
                    } finally {
                        this.sound = null
                    }
                })
            }
        });
}

这可能是一种竞争条件,其中调用了两次
this.sound.release()
?因此,第二次它被调用为null,然后它就消失了。我的意思是,它在声音播放后,在“模糊”的东西上被同步调用。然后可能会被异常块捕获,但我没有使用js的经验,因此不知道..

这可能会有所帮助,请查看它

import React, { Component } from "react";    
var Sound = require("react-native-sound");

Sound.setCategory("PlayAndRecord", true);
Sound.setActive(true); // add this

export default class AudioList extends Component {
  playAudio = (file) => {
    if (this.sound) {
      try {
        this.sound.release();
      } catch (error) {
        console.log("A sound release error has occured 111");
      } finally {
        this.sound = null;
      }
    }

    const pathType =
      Platform.OS === "ios"
        ? encodeURIComponent(Sound.MAIN_BUNDLE)
        : Sound.MAIN_BUNDLE;

    this.sound = new Sound("audio/" + file, pathType, (error) => {
      /* .... */
    });
  };

  componentWillUnmount() {
    try {
      if (this.sound) {
        this.sound.release();
      }
    } catch (error) {
      console.log("A sound release error has occured 333");
    } finally {
      this.sound = null;
    }
  }

  render() {
    /* .... */
  }
}

我认为加载音频文件时可能会发生崩溃,
blur
事件会发生。你没有检查这个状态。所以当你使用

this.sound = new Sound('audio/' + file, Sound.MAIN_BUNDLE, (error) => ...)
此.sound
生效,音频文件开始加载。但立即
blur
事件发生,您释放
这个声音。同时,加载完成并尝试播放!什么都没有,你会撞车

解决方案:在模糊事件中,您必须同时检查
this.sound
this.sound.isLoaded()
()。

反应本机:如何加载和播放音频

'react本机音频已超过2年未更新。。应该避免…使用expo av代替…“-摘自文章

Expo AV

导出类控制器{
Apidenthttps:///audio/load';
audioFemale=新的Audio.Sound();
audioMale=新的Audio.Sound();
/*重置音频剪辑
*异步停止和卸载任何现有音频剪辑,
*不阻塞执行
*/
resetAudioClips=async()=>{
this.audioFemale.unloadAsync();
this.audioMale.unloadAsync();
}
/*谨慎地使用音频剪辑
*异步停止和卸载任何现有音频剪辑,
*正在获取,请先检查音频状态。
*也会阻止执行,直到卸载音频。
*/
cautiousResetAudioClips=async()=>{
让femaleStatus=wait this.audioFemale.getStatusAsync();
让maleStatus=wait this.audioMale.getStatusAsync();
if(femaleStatus.isLoaded==true){
等待此消息。audioFemale.stopAsync()
等待此消息。audiofemal.unloadAsync();
}
如果(maleStatus.isLoaded==真){
等待此消息。audioMale.stopAsync()
等待此消息。audioMale.unloadAsync();
}
}
/*负荷夹
*token:您的API的一些身份验证令牌
*女性:通往圣母院的道路