首发于公众号 前端混合开发,欢迎关注。
为你的应用添加声音是吸引用户的好方法。新通知的小铃声,发送邮件的“嗖”的声音,或者删除文件的崩溃声,都能在很大程度上为你的React Native应用构建更好的用户体验。
在这个指南中,我们将探索 react-native-sound
,这是一个强大的音频组件,可以处理你的 React Native 应用的声音相关任务。
什么是react-native-sound?
react-native-sound 是一个React Native模块,用于在iOS、Android和Windows上播放声音片段。此模块使我们能够从各种来源添加音频,例如应用程序包(原生)、JavaScript包,或远程路径(本地存储或远程URL)。
react-native-sound
更像是一个类而不是类组件,它通过预定义的方法帮助控制实例,无需更新状态或属性。这缓解了与应用程序慢速重新渲染相关的问题。
尽管 react-native-sound
的文档警告称它是"alpha版本可能有 bug",但它是当今最流行、使用最广泛的 React Native 声音库之一。
设置react-native-sound(iOS和Android)
要开始使用 react-native-sound
,如果你想在应用中播放的声音不是远程可用的(即,它们在应用的包内,而不是在设备的外部存储或远程服务器上),你需要准备这些声音。
要在你的应用中添加 react-native-sound
,只需在你的应用目录中使用你喜欢的包管理器(例如,npm
或 yarn
)输入以下命令:
$ yarn add react-native-sound
如果你正在为 Android 构建应用,链接过程会在构建过程中处理。
对于 iOS,只需导航到 iOS 目录并调用 pod install
即可。这将添加 react-native-sound 所需的 pod。
为应用添加声音
现在是时候添加你想要播放的声音了。这个步骤只是为了学习如何将音频文件打包到原生包中。我们还会介绍一种更简单的方法,从资产目录中获取音频文件。
对于Android,创建 raw
目录并将声音复制到该目录:
{appDirectory}/android/app/src/main/res/raw
对于iOS,打开Xcode中的工作区,然后右键点击项目并点击添加文件到{项目名称},如下图所示:
结果应该看起来像这样:
在添加了声音文件后,只需构建应用并在模拟器上运行,或者更好的是在真实设备上运行。
从包中播放声音
首先,我们需要在应用中导入声音组件:
import Sound from 'react-native-sound';
在设置我们要播放的声音之前,我们需要指定声音的类别:
Sound.setCategory('Playback');
要初始化声音,请使用以下代码:
var ding = new Sound('ding.mp3', Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// when loaded successfully
console.log('duration in seconds: ' + whoosh.getDuration() + 'number of channels: ' + whoosh.getNumberOfChannels());
});
上面的代码使用第一个参数 ding.mp3
,这是来自使用第二个参数 Sound.MAIN_BUNDLE
指定的包中的文件,并在第三个参数中返回一个回调函数。
getDuration
用于获取音频文件的持续时间(以秒为单位),getNumberOfChannels
用于获取音频通道的数量。
要设置播放音量,我们可以使用以下方法:
ding.setVolume(1);
这里, 1
是最高音量, 0
是最低音量,它们之间的差异用小数表示 —— 例如,要将音量降低到 50%,你可以将其设置为 0.5
。
要播放文件,我们可以使用 Sound
的 play
方法,如下所示:
ding.play(success => {
if (success) {
console.log('successfully finished playing');
} else {
console.log('playback failed due to audio decoding errors');
}
});
成功完成回款后会有一个回调(或者如果出了任何问题,也是如此)。
总结以上所述的步骤:
- 设置要播放的声音的类别
- 初始化一个声音文件
- 如有必要,调整音量
- 播放声音
这是从包中播放声音的最终代码:
import React, {useEffect} from 'react';
import {View, StyleSheet, TouchableOpacity} from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
var Sound = require('react-native-sound');
Sound.setCategory('Playback');
var ding = new Sound('ding.mp3', Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// if loaded successfully
console.log('duration in seconds: ' + ding.getDuration() + 'number of channels: ' + ding.getNumberOfChannels());
});
const App = () => {
useEffect(() => {
ding.setVolume(1);
return () => {
ding.release();
};
}, []);
const playPause = () => {
ding.play(success => {
if (success) {
console.log('successfully finished playing');
} else {
console.log('playback failed due to audio decoding errors');
}
});
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.playBtn} onPress={playPause}>
<Ionicons name={'ios-play-outline'} size={36} color={'#fff'} />
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
},
playBtn: {
padding: 20,
},
});
export default App;
导入声音文件
现在,对于来自资源目录(或应用程序中的任何目录)的文件,我们可以使用相同的旧 require
或 import
来获取文件的实例,并使用 react-native-sound 播放它。
import dings from './src/assets/ding.mp3';
并在 Sound 包中使用它,如下所示:
var ding = new Sound(dings, error => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// if loaded successfully
console.log('duration in seconds: ' + ding.getDuration() + 'number of channels: ' + ding.getNumberOfChannels());
});
与使用捆绑文件相比,使用从资源导入或引用的文件的不同之处在于,你不必为文件指定 basePath
。相反,回调函数取代了它的位置。
这是播放导入文件的组件的代码:
import React, {useEffect} from 'react';
import {View, StyleSheet, TouchableOpacity} from 'react-native';
import dings from './src/assets/ding.mp3';
import Ionicons from 'react-native-vector-icons/Ionicons';
var Sound = require('react-native-sound');
Sound.setCategory('Playback');
var ding = new Sound(dings, error => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// if loaded successfully
console.log(
'duration in seconds: ' +
ding.getDuration() +
'number of channels: ' +
ding.getNumberOfChannels(),
);
});
const App = () => {
useEffect(() => {
ding.setVolume(1);
return () => {
ding.release();
};
}, []);
const playPause = () => {
ding.play(success => {
if (success) {
console.log('successfully finished playing');
} else {
console.log('playback failed due to audio decoding errors');
}
});
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.playBtn} onPress={playPause}>
<Ionicons name={'ios-play-outline'} size={36} color={'#fff'} />
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
},
playBtn: {
padding: 20,
},
});
export default App;
以下是上述代码的结果。只需点击播放按钮即可播放声音。
111111
从远程路径播放声音文件
你可能想播放远程文件或本地存储中的文件。使用 react-native-sound
播放这些文件基本上和播放捆绑文件一样简单。你只需要将 URL 作为第一个参数添加到 Sound
中,并将第二个参数设置为 null
,因为文件来自远程或本地存储,而不是来自应用程序。
var audio = new Sound(
'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3',
null,
error => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// if loaded successfully
console.log(
'duration in seconds: ' +
audio.getDuration() +
'number of channels: ' +
audio.getNumberOfChannels(),
);
},
);
以下是一个完整的示例,说明如何在应用关闭或组件卸载后播放、暂停和释放音频:
import React, {useEffect, useState} from 'react';
import {View, StyleSheet, TouchableOpacity} from 'react-native';
import Ionicons from 'react-native-vector-icons/Ionicons';
var Sound = require('react-native-sound');
Sound.setCategory('Playback');
var audio = new Sound(
'https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3',
null,
error => {
if (error) {
console.log('failed to load the sound', error);
return;
}
// if loaded successfully
console.log(
'duration in seconds: ' +
audio.getDuration() +
'number of channels: ' +
audio.getNumberOfChannels(),
);
},
);
const App = () => {
const [playing, setPlaying] = useState();
useEffect(() => {
audio.setVolume(1);
return () => {
audio.release();
};
}, []);
const playPause = () => {
if (audio.isPlaying()) {
audio.pause();
setPlaying(false);
} else {
setPlaying(true);
audio.play(success => {
if (success) {
setPlaying(false);
console.log('successfully finished playing');
} else {
setPlaying(false);
console.log('playback failed due to audio decoding errors');
}
});
}
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.playBtn} onPress={playPause}>
<Ionicons
name={playing ? 'ios-pause-outline' : 'ios-play-outline'}
size={36}
color={'#fff'}
/>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#000',
},
playBtn: {
padding: 20,
},
});
export default App;
.release()
用于释放预留给播放音频文件的内存。在组件卸载或音频不再播放后释放内存非常重要。这有助于避免内存泄漏或其他错误。
总结
react-native-sound是一个很好的模块,用于为你的React Native应用添加声音或构建一个简单的音频播放器。
在这个教程中,我们介绍了如何从本地包添加和播放音频,以及如何从远程文件播放音频。如果你想在这方面探索更多选项,我建议尝试使用Expo unimodules的expo-av模块在你的React Native应用中播放音频或视频文件。
交流
首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。