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

React Native动态加载本地JSON音频文件播放失败求助

React Native 本地音频播放(支持安卓)问题解决

你遇到的错误根源是:Expo AV 在 React Native 环境中无法直接解析字符串形式的相对路径,它会把这个路径当成网络请求去访问,最终返回了 HTML 错误页面(所以 Content-Type 是 text/html),自然无法播放音频。以下是适配安卓的完整解决方案,包含播放/暂停功能:

1. 调整本地音频资源的引用方式

React Native 中本地资源必须通过 require() 引入,不能直接使用字符串路径。你可以按以下两种方式处理:

方式一:修改 JSON 文件(推荐)

把 JSON 中的音频路径改为仅存文件名:

"audio": "Lite Saturation - Nostalgia.mp3"

然后在代码中拼接路径并引入:

const audioSource = require(`./audio/${tune.audio}`);

方式二:路径映射表(不修改 JSON 时使用)

如果无法修改原 JSON,提前建立路径与资源的映射:

const audioMap = {
  "./audio/Lite Saturation - Nostalgia.mp3": require("./audio/Lite Saturation - Nostalgia.mp3"),
  // 其他音频文件按需添加
};
const audioSource = audioMap[tune.audio];

2. 完整播放/暂停实现(基于 Expo AV)

下面是支持播放、暂停、资源自动释放的代码:

import { useState, useEffect } from 'react';
import { Audio } from 'expo-av';
import { Button } from 'react-native';

const AudioPlayer = ({ tune }) => {
  const [sound, setSound] = useState(null);
  const [isPlaying, setIsPlaying] = useState(false);

  // 按实际情况选择上面的方式获取 audioSource
  const audioSource = require(`./audio/${tune.audio}`);

  const togglePlayPause = async () => {
    try {
      if (!sound) {
        // 初始化并播放音频
        const newSound = new Audio.Sound();
        await newSound.loadAsync(audioSource);
        await newSound.playAsync();
        setSound(newSound);
        setIsPlaying(true);
        
        // 监听播放结束,自动重置状态
        newSound.setOnPlaybackStatusUpdate(status => {
          if (status.didJustFinish) {
            setIsPlaying(false);
            setSound(null);
          }
        });
      } else if (isPlaying) {
        // 暂停音频
        await sound.pauseAsync();
        setIsPlaying(false);
      } else {
        // 恢复播放
        await sound.playAsync();
        setIsPlaying(true);
      }
    } catch (error) {
      console.log("音频播放错误:", error);
    }
  };

  // 组件卸载时释放音频资源,避免内存泄漏
  useEffect(() => {
    return () => {
      if (sound) {
        sound.unloadAsync();
      }
    };
  }, [sound]);

  return (
    <Button
      title={isPlaying ? "暂停" : "播放"}
      onPress={togglePlayPause}
    />
  );
};

export default AudioPlayer;

3. 关键注意事项

  • 资源打包配置:确保 metro.config.js 支持 mp3 格式(Expo 项目默认已支持,自定义配置时需确认):
    // metro.config.js
    const { getDefaultConfig } = require('expo/metro-config');
    const config = getDefaultConfig(__dirname);
    config.resolver.assetExts.push('mp3');
    module.exports = config;
    
  • 安卓权限:Expo 项目无需额外配置;裸 React Native 项目需在 AndroidManifest.xml 中添加:
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    
  • 动态路径限制:React Native 的 metro 打包器无法处理完全动态的路径(如 require(./audio/${randomName})),必须提前明确所有需要打包的音频资源。

内容的提问来源于stack exchange,提问作者Mila Oktay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:00:14