You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo React Native中@react-native-voice/voice遇startSpeech为null错误求助

问题描述

使用Expo + TypeScript + @react-native-voice/voice 在React Native应用中实现语音转文本功能时,调用start或stop函数出现以下错误:

TypeError: Cannot read property 'startSpeech' of null
TypeError: Cannot read property 'stopSpeech' of null

当前使用Android 13系统,怀疑存在版本兼容性问题,尝试多种方法仍无法解决。


相关代码与配置

语音录制组件代码

import React, { useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import Voice from '@react-native-voice/voice';

const SpeechToText = () => {
    const [isRecording, setIsRecording] = useState(false);
    const [speechText, setSpeechText] = useState('');

    const onSpeechStartHandler = () => {
        setIsRecording(true);
        setSpeechText('');
    };

    const onSpeechEndHandler = () => {
        setIsRecording(false);
    };

    const onSpeechResultsHandler = (event: any) => {
        setSpeechText(event.value[0]);
    };

    const startSpeechToText = async () => {
        try {
            await Voice.start('en-US');
            onSpeechStartHandler();
        } catch (error) {
            console.log(error);
        }
    };

    const stopSpeechToText = async () => {
        try {
            await Voice.stop();
            onSpeechEndHandler();
        } catch (error) {
            console.log(error);
        }
    };

    return (
        <View style={styles.container}>
            <TouchableOpacity
                style={styles.button}
                onPressIn={startSpeechToText}
                onPressOut={stopSpeechToText}
                disabled={isRecording}
            >
                <Text style={styles.text}>Press and hold to speak</Text>
            </TouchableOpacity>
            <Text style={styles.speechText}>{speechText}</Text>
        </View>
    );
};

app.json配置

{
  "expo": {
    [....]
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "permissions": [
        "android.permission.RECORD_AUDIO"
      ]
    },
    "plugins": [
      [
        "@react-native-voice/voice",
        {
          "microphonePermission": "CUSTOM: Allow $(PRODUCT_NAME) to access the microphone",
          "speechRecognitionPermission": "CUSTOM: Allow $(PRODUCT_NAME) to securely recognize user speech"
        }
      ]
    ]
  }
}

package.json依赖

{
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "test": "jest --watchAll"
  },
  "dependencies": {
    "@react-native-voice/voice": "^3.2.4",
    "expo": "~48.0.11",
    "expo-font": "~11.1.1",
    "expo-linking": "~4.0.1",
    "expo-permissions": "^14.1.1",
    "expo-router": "^1.5.2",
    "expo-speech": "^11.1.1",
    "expo-splash-screen": "~0.18.1",
    "expo-status-bar": "~1.4.4",
    "expo-system-ui": "~2.2.1",
    "expo-web-browser": "~12.1.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-native": "0.71.6",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-safe-area-context": "4.5.0",
    "react-native-screens": "~3.20.0",
    "react-native-vector-icons": "^9.2.0",
    "react-native-web": "~0.18.10"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/react": "~18.0.14",
    "@types/react-native": "^0.71.5",
    "react-test-renderer": "18.2.0",
    "typescript": "^4.9.4"
  },
  "private": true
}

解决方案

1. 修复版本兼容性问题

当前@react-native-voice/voice@3.2.4与Expo 48存在适配缺陷,建议升级到适配版本:

npm install @react-native-voice/voice@3.2.6
# 或 yarn add @react-native-voice/voice@3.2.6

2. 完善权限配置与主动申请

Android 13下除麦克风权限外,语音识别还需联网权限,同时要主动在组件内申请权限:

  • 更新app.json权限:
"android": {
  "permissions": [
    "android.permission.RECORD_AUDIO",
    "android.permission.INTERNET"
  ]
}
  • 在组件中添加权限申请逻辑:
import * as Permissions from 'expo-permissions';
import React, { useState, useEffect } from 'react';

// ... 原有代码 ...

useEffect(() => {
  const requestPermissions = async () => {
    const [audioPerm, speechPerm] = await Promise.all([
      Permissions.askAsync(Permissions.AUDIO_RECORDING),
      Permissions.askAsync(Permissions.SPEECH_RECOGNITION)
    ]);
    if (audioPerm.status !== 'granted' || speechPerm.status !== 'granted') {
      alert('需授予麦克风和语音识别权限才能使用功能');
    }
  };
  requestPermissions();
}, []);

3. 正确初始化Voice事件监听

库底层实例未初始化是导致null错误的核心原因,需注册事件监听器并在组件销毁时清理:

useEffect(() => {
  // 绑定事件监听
  Voice.onSpeechStart = onSpeechStartHandler;
  Voice.onSpeechEnd = onSpeechEndHandler;
  Voice.onSpeechResults = onSpeechResultsHandler;

  // 组件卸载时清理
  return () => {
    Voice.destroy().then(Voice.removeAllListeners);
  };
}, []);

4. 清除Expo缓存并重建项目

缓存可能导致库未正确链接,执行以下操作:

  1. 关闭Expo开发服务器
  2. 清除缓存:
expo r -c
  1. 重新启动Android项目:
expo start --android

5. 检查Android 13系统权限设置

手动确认应用已获得麦克风权限:打开系统设置 -> 应用 -> 你的应用 -> 权限 -> 麦克风,确保权限处于开启状态。


内容的提问来源于stack exchange,提问作者baronnat theo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:12:57