React Native 应用程序开发人员构建各种应用程序,其中一些涉及实现音乐播放列表。如果您计划使用 React Native 构建一个音频播放器,您无疑需要一个播放列表实现,其中包括一个可管理的音乐曲目队列,该队列对用户可见或作为后台服务运行以按特定顺序播放音乐曲目。
音乐播放列表通常连接到播放所选音乐曲目的音乐播放器实现。如何修复Windows更新错误0x800b0003?从用户的角度来看,他们应该能够在播放列表中添加、删除、随机播放和重新排序音乐曲目。从开发人员的角度来看,dpi转换器是什么?推荐5款DPI转换器软件他们还应该能够以编程方式更新播放列表。
在 React Native 中创建和管理播放列表有几种可能的方法。我们可以在没有第三方库的情况下从头开始构建播放列表和播放器,但这很耗时。Windows11如何设置以保护隐私?我们也可以使用库来播放音乐曲目,并根据音乐播放器事件从头开始开发音乐队列。如何在Windows10上启用Gmail深色模式?我们可以使用功能齐全的音乐曲目播放器库进一步加快开发过程。
该库提供功能齐全的 API,用于在 React Native 如何修复 Windows 10 上找不到 Rockalldll.dll 的问题?中创建基于播放列表的音乐应用程序。如何修复Windows10滚动问题?windows10滚动条为什么自己往下跑在本教程中,如何在Windows10上查看YouTube历史评论记录?我将通过实现一个包含可见播放列表的音乐播放器来解释功能。如何修复Spotify指定用户没有有效配置文件?react-native-track-playerreact-native-track-player
跳跃前进:
突出特点react-native-track-player
react-native-track-player教程
在我们开始实用教程之前,让我们检查一下库的功能。
该库具有以下用于构建音乐应用程序的有用功能:
该库由两个逻辑模块组成:
音乐播放器模块
播放列表实现
音乐播放器模块播放播放列表中的曲目。这个库提供了函数和 React Hooks 来控制音乐播放器的状态和订阅播放器事件。这些对开发人员友好的播放器状态管理功能使跟踪播放器 UI 集成变得容易。此外,基于事件的 React Hooks 降低了 React 状态管理要求的复杂性。
该库为开发人员提供了一个简单的 API 来管理音乐曲目队列。您可以通过不言自明的功能以编程方式添加、删除、重复和跳过音乐曲目。使用此库可以轻松创建您自己的基于播放列表的音乐播放器。
对于播放列表管理和播放,这个库使用两个本地模块:
KotlinAudio:Android 的跟踪播放器实现
SwiftAudioEx:iOS 的跟踪播放器实现
JavaScript实现调用上述原生模块进行音乐播放和播放列表管理,因此该库致力于为您的音乐应用程序提供原生性能。播放列表存储在最佳本机数据结构中以获得更好的性能(即Kotlin 中的LinkedList)。react-native-track-player
该库提供对开发人员友好、一致的异步 API,因此您可以轻松地在 React Native 应用程序代码库中使用现代模式。async/await
该库适用于 Android、iOS 和 Windows 平台。它使用WinRT 媒体播放 API在 Windows 上播放音乐内容,因此您可以使用此包构建现代 Windows 应用程序!
轨道播放器库从不通过仅提供通用的跨平台 API 来限制开发人员——它为高级用例提供特定于平台的配置。例如,它可以让您更改 Android 上的通知面板播放器图标。
现在,我们将通过开发带有播放列表的音乐播放器应用程序来学习如何使用该库。在构建音乐播放器应用程序时,我将向您展示一些额外的示例代码片段,以进一步解释库 API 函数。react-native-track-player
从安装包开始。首先,创建一个新的 React Native 项目来构建音乐播放器:react-native-track-player
npx react-native init MusicTrackPlayer
cd MusicTrackPlayer
接下来,运行新创建的应用程序以确保一切正常:
npx react-native run-android
# --- or ---
npx react-native run-ios
现在,安装库:
npm install react-native-track-player
# --- or ---
yarn add react-native-track-player
我正在 Android 上开发这个示例应用程序,因此运行上面的命令足以设置库。但是,在 iOS 上,您需要手动安装原生依赖项:
cd ios && pod install
再次构建应用程序并运行它以验证包安装状态。
注意:在 Android 上,如果Gradle 构建任务失败,请在您的. 有关详细信息,请参阅此参考资料。:app:checkDebugAarMetadatacompileSdkVersion = 33android/build.gradle
让我们开始使用音轨播放器库播放音乐。在为播放列表实现 UI 组件之前,我们将以编程方式创建播放列表以了解播放列表管理 API。
首先,在您的应用程序源目录中创建一个名为的新目录,并将这些音乐曲目(来自Pixabay Musicassets的三个 MP3 音频文件)下载到其中。
在初始化曲目播放器实例以播放您下载的 MP3 文件之前,我们需要定义几个服务来帮助我们配置、初始化和控制曲目播放器实例。创建一个名为的新文件并添加以下代码:trackPlayerServices.js
import TrackPlayer, {
AppKilledPlaybackBehavior,
Capability,
RepeatMode,
Event
} from 'react-native-track-player';
export async function setupPlayer() {
let isSetup = false;
try {
await TrackPlayer.getCurrentTrack();
isSetup = true;
}
catch {
await TrackPlayer.setupPlayer();
await TrackPlayer.updateOptions({
android: {
appKilledPlaybackBehavior:
AppKilledPlaybackBehavior.StopPlaybackAndRemoveNotification,
},
capabilities: [
Capability.Play,
Capability.Pause,
Capability.SkipToNext,
Capability.SkipToPrevious,
Capability.SeekTo,
],
compactCapabilities: [
Capability.Play,
Capability.Pause,
Capability.SkipToNext,
],
progressUpdateEventInterval: 2,
});
isSetup = true;
}
finally {
return isSetup;
}
}
export async function addTracks() {
await TrackPlayer.add([
{
id: '1',
url: require('./assets/fluidity-100-ig-edit-4558.mp3'),
title: 'Fluidity',
artist: 'tobylane',
duration: 60,
}
]);
await TrackPlayer.setRepeatMode(RepeatMode.Queue);
}
export async function playbackService() {
// TODO: Attach remote event handlers
}
上面的代码实现了三个服务:
setupPlayer:仅使用多个播放器功能和默认行为(即应用程序终止行为)初始化一次轨道播放器实例
addTracks:从捆绑资源中将一首曲目添加到当前播放列表
playbackService:此服务接收远程事件。我们将在接下来的部分讨论播放服务事件,所以让我们暂时将此功能留空
在这里,我们通过函数从应用程序包中加载一个 MP3 文件require。该库支持通过http协议加载远程音频文件和通过协议加载本地音频文件file。
接下来,我们需要将上述函数注册playbackService为播放事件处理程序。在您的文件中使用以下代码:index.js
import { AppRegistry } from 'react-native';
import TrackPlayer from 'react-native-track-player';
import App from './App';
import { name as appName } from './app.json';
import { playbackService } from './trackPlayerServices';
AppRegistry.registerComponent(appName, () => App);
TrackPlayer.registerPlaybackService(() => playbackService);
现在,我们可以开始构建应用程序 UI,因为我们的轨道播放器服务已准备就绪。将以下代码添加到您的文件中:App.js
import React, { useEffect, useState } from 'react';
import {
SafeAreaView,
StyleSheet,
View,
Button,
ActivityIndicator,
} from 'react-native';
import TrackPlayer from 'react-native-track-player';
import { setupPlayer, addTracks } from './trackPlayerServices';
function App() {
const [isPlayerReady, setIsPlayerReady] = useState(false);
useEffect(() => {
async function setup() {
let isSetup = await setupPlayer();
const queue = await TrackPlayer.getQueue();
if(isSetup && queue.length <= 0) {
await addTracks();
}
setIsPlayerReady(isSetup);
}
setup();
}, []);
if(!isPlayerReady) {
return (
);
}
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
backgroundColor: '#112'
},
});
export default App;
上述App组件调用setupPlayer服务viauseEffect初始化原生端的track player。addTracks接下来,如果当前播放列表为空,它会调用服务来初始化播放列表。该组件使用如下条件渲染逻辑:
如果播放器未准备好(设置正在进行中),则呈现加载动画
如果播放器设置过程成功,则呈现一个 播放按钮
播放按钮调用函数开始播放曲目队列。运行上面的应用程序代码并按下播放 按钮。播放列表将开始!看下面的预览:TrackPlayer.play
使用以下代码为addTracks服务播放所有下载的音乐曲目:
export async function addTracks() {
await TrackPlayer.add([
{
id: '1',
url: require('./assets/fluidity-100-ig-edit-4558.mp3'),
title: 'Fluidity',
artist: 'tobylane',
duration: 60,
},
{
id: '2',
url: require('./assets/penguinmusic-modern-chillout-future-calm-12641.mp3'),
title: 'Modern Chillout',
artist: 'penguinmusic',
duration: 66,
},
{
id: '3',
url: require('./assets/powerful-beat-121791.mp3'),
title: 'Powerful Beat',
artist: 'penguinmusic',
duration: 73,
}
]);
await TrackPlayer.setRepeatMode(RepeatMode.Queue);
}
由于该模式,播放列表将在结束时重新开始。RepeatMode.Queue
TrackPlayer.remove:按曲目索引删除音乐曲目
TrackPlayer.skip:按给定索引跳转到音乐曲目
TrackPlayer.next:转到下一首音乐曲目
TrackPlayer.previous:转到上一个音乐曲目
TrackPlayer.reset:清除当前播放列表并停止播放音乐
在官方文档中浏览所有支持的播放列表管理功能。
按下播放按钮后 ,使用热重载功能一一执行以下函数调用,以熟悉播放列表管理功能:
TrackPlayer.remove(0)
TrackPlayer.skip(2)
TrackPlayer.next()
TrackPlayer.previous()
TrackPlayer.reset()
让我们在实际场景中使用上面的播放列表管理功能。我们可以开始改进示例应用程序,将其变成基于播放列表的音乐播放器。
第一步,让我们创建一个 React 组件来显示当前播放列表并让用户播放喜欢的音乐曲目。为简单起见,在本教程中,我们将在我们的文件中开发所有组件,但请确保在开发生产级应用程序时将您的应用程序正确分解为单独的源文件。App.js
首先,将以下导入行添加到:App.js
import {
SafeAreaView,
StyleSheet,
Text,
View,
Button,
FlatList,
ActivityIndicator,
TouchableOpacity,
} from 'react-native';
import TrackPlayer, {
useTrackPlayerEvents,
Event,
State
} from 'react-native-track-player';
接下来,将Playlist组件实现添加到源文件中:
function Playlist() {
const [queue, setQueue] = useState([]);
const [currentTrack, setCurrentTrack] = useState(0);
async function loadPlaylist() {
const queue = await TrackPlayer.getQueue();
setQueue(queue);
}
useEffect(() => {
loadPlaylist();
}, []);
useTrackPlayerEvents([Event.PlaybackTrackChanged], async (event) => {
if(event.state == State.nextTrack) {
let index = await TrackPlayer.getCurrentTrack();
setCurrentTrack(index);
}
});
function PlaylistItem({index, title, isCurrent}) {
function handleItemPress() {
TrackPlayer.skip(index);
}
return (
style={{...styles.playlistItem,
...{backgroundColor: isCurrent ? '#666' : 'transparent'}}}>
{title}
);
}
return(
data={queue}
renderItem={({item, index}) =>
index={index}
title={item.title}
isCurrent={currentTrack == index }/>
}
/>
);
}
在这里,我们使用FlatList组件渲染当前播放列表。该FlatList组件使用queue状态变量加载当前播放列表的详细信息。同时,useEffect调用将当前播放列表捕获到.TrackPlayer.getQueuequeue
播放列表 UI 还会突出显示当前音乐曲目,因此我们将当前音乐曲目索引存储在currentTrack状态变量中。一旦用户按下列表项,我们就要求曲目播放器实例通过调用该函数来播放选定的曲目。我们通过库 Hook跟踪更改。TrackPlayer.skipcurrentTrackuseTrackPlayerEvents
return (
);
将以下样式定义添加到您的样式表中:
playlist: {
marginTop: 40,
marginBottom: 40
},
playlistItem: {
fontSize: 16,
paddingTop: 4,
paddingBottom: 4,
paddingLeft: 8,
paddingRight: 8,
borderRadius: 4
},
运行应用程序。现在,您可以按下并选择音乐曲目。等到音乐曲目结束——播放列表组件将自动设置下一个当前音乐曲目,如下面的预览所示:
之前,我们调用函数开始播放曲目队列。我们在构建音乐应用时,经常需要暂停、控制播放速度、调节音乐音量、跳转到当前音乐曲目的特定位置。除了播放操作之外,该库还允许您使用以下功能控制播放和播放器状态:TrackPlayer.playreact-native-track-player
TrackPlayer.pause:暂停当前播放曲目;您可以使用该功能再次播放TrackPlayer.play
TrackPlayer.seekTo:根据输入的秒数跳转到特定位置
TrackPlayer.setRate:改变播放速度
TrackPlayer.setVolume:设置音乐播放器音量
以上函数影响当前播放/播放器状态。您还可以在调用上述函数之前获取播放/播放器状态。下面是一些我们经常需要的getter:
TrackPlayer.getState: 返回当前播放状态
TrackPlayer.getVolume: 返回当前音量
注意:如前所述,该库提供了一个异步 API,因此您必须使用令牌await从已解析的承诺中提取返回的数据。从官方文档中浏览所有支持的播放状态控制功能。
按下播放 按钮后,通过热重载一一执行以下函数调用,以熟悉播放器/播放状态函数:
TrackPlayer.pause()
TrackPlayer.seekTo(10)
TrackPlayer.setRate(0.5)
TrackPlayer.setVolume(0.2)
现在,我们将使用上述函数为我们的音乐播放器添加一个控制框。用户可以使用控制箱按钮播放/暂停、转到上一个音乐曲目和转到下一个音乐曲目。我们将使用该包来构建控制框图标按钮。react-native-vector-icons
首先按照官方安装指南安装并重建项目。然后,在您的文件中添加以下导入:App.js
import TrackPlayer, {
useTrackPlayerEvents,
usePlaybackState,
Event,
State
} from 'react-native-track-player';
import Icon from 'react-native-vector-icons/FontAwesome';
现在,更新现有Playlist组件并添加新Controls组件源:
function Playlist() {
const [queue, setQueue] = useState([]);
const [currentTrack, setCurrentTrack] = useState(0);
async function loadPlaylist() {
const queue = await TrackPlayer.getQueue();
setQueue(queue);
}
useEffect(() => {
loadPlaylist();
}, []);
useTrackPlayerEvents([Event.PlaybackTrackChanged], (event) => {
if(event.state == State.nextTrack) {
TrackPlayer.getCurrentTrack().then((index) => setCurrentTrack(index));
}
});
function PlaylistItem({index, title, isCurrent}) {
function handleItemPress() {
TrackPlayer.skip(index);
}
return (
style={{...styles.playlistItem,
...{backgroundColor: isCurrent ? '#666' : 'transparent'}}}>
{title}
);
}
return(
data={queue}
renderItem={({item, index}) =>
index={index}
title={item.title}
isCurrent={currentTrack == index }/>
}
/>
);
}
function Controls({ onShuffle }) {
const playerState = usePlaybackState();
async function handlePlayPress() {
if(await TrackPlayer.getState() == State.Playing) {
TrackPlayer.pause();
}
else {
TrackPlayer.play();
}
}
return(
flexWrap: 'wrap', alignItems: 'center'}}>
name="arrow-left"
size={28}
backgroundColor="transparent"
onPress={() => TrackPlayer.skipToPrevious()}/>
name={playerState == State.Playing ? 'pause' : 'play'}
size={28}
backgroundColor="transparent"
onPress={handlePlayPress}/>
name="arrow-right"
size={28}
backgroundColor="transparent"
onPress={() => TrackPlayer.skipToNext()}/>
);
}
这里我们使用一个图标按钮来切换播放/暂停状态,条件如下:
await TrackPlayer.getState() == State.Playing
从组件中移除之前的播放按钮,App因为它不再需要了:
return (
);
运行应用程序。现在,您可以使用控制框:
该库提供了useProgressHook 来跟踪音乐曲目进度。默认情况下,此 Hook 每秒轮询一次跟踪进度,但您可以根据需要配置间隔(即)。useProgress(200)
创建一个新组件以使用 Hook 显示音乐曲目进度useProgress:
function TrackProgress() {
const { position, duration } = useProgress(200);
function format(seconds) {
let mins = (parseInt(seconds / 60)).toString().padStart(2, '0');
let secs = (Math.trunc(seconds) % 60).toString().padStart(2, '0');
return `${mins}:${secs}`;
}
return(
{ format(position) } / { format(duration) }
);
}
上面的组件使用曲目持续时间TrackProgress以格式显示当前曲目进度。mm:ss
添加另一个组件以显示当前音乐曲目信息:
function Header() {
const [info, setInfo] = useState({});
useEffect(() => {
setTrackInfo();
}, []);
useTrackPlayerEvents([Event.PlaybackTrackChanged], (event) => {
if(event.state == State.nextTrack) {
setTrackInfo();
}
});
async function setTrackInfo() {
const track = await TrackPlayer.getCurrentTrack();
const info = await TrackPlayer.getTrack(track);
setInfo(info);
}
return(
);
}
在这里,我们使用useTrackPlayerEventsHook 在当前曲目发生变化时更新当前曲目详细信息。接下来,将useProgressHook 添加到导入列表中:
import TrackPlayer, {
useTrackPlayerEvents,
usePlaybackState,
useProgress,
Event,
State
} from 'react-native-track-player';
现在,将上述组件呈现在App:
return (
);
将以下样式定义添加到您的样式表中:
trackProgress: {
marginTop: 40,
textAlign: 'center',
fontSize: 24,
color: '#eee'
},
songTitle: {
fontSize: 32,
marginTop: 50,
color: '#ccc'
},
artistName: {
fontSize: 24,
color: '#888'
},
运行应用程序。现在,您将看到带有音乐曲目的详细信息、曲目进度、播放列表和控制框组件:
您可以通过使用 添加搜索栏来改进音乐曲目播放器,但我们不会在本教程中深入介绍集成。通过以下步骤可以轻松添加搜索栏:react-native-sliderreact-native-slider
useProgress使用Hook更新滑块
为滑块附加一个事件处理程序并调用以更改播放状态TrackPlayer.seekTo
您可以使用我们之前测试过的源代码转到上一个或下一个音乐曲目。自从我们在服务中使用该模式以来,播放列表将在播放列表结束时重新开始(循环)。您可以通过函数使用循环当前曲目。尝试自己在控制框中添加一个播放列表重复模式选择器按钮!RepeatMode.QueueaddTracksRepeatMode.TrackTrackPlayer.setRepeatMode
如果您需要随机播放播放列表怎么办?本机播放列表随机播放功能仍然是一个正在进行的功能请求(问题 #1711),但目前,我们可以在 JavaScript 端实现播放列表随机播放。
首先,在组件中实现播放列表随机播放Playlist:
async function handleShuffle() {
let queue = await TrackPlayer.getQueue();
await TrackPlayer.reset();
queue.sort(() => Math.random() - 0.5);
await TrackPlayer.add(queue);
loadPlaylist()
}
return(
data={queue}
renderItem={({item, index}) =>
index={index}
title={item.title}
isCurrent={currentTrack == index }/>
}
/>
);
在这里,我们提取当前队列,对其进行随机播放,然后通过该handleShuffle函数将其重新加载到播放列表。接下来,为洗牌添加一个新的图标按钮:
function Controls({ onShuffle }) {
const playerState = usePlaybackState();
async function handlePlayPress() {
if(await TrackPlayer.getState() == State.Playing) {
TrackPlayer.pause();
}
else {
TrackPlayer.play();
}
}
return(
flexWrap: 'wrap', alignItems: 'center'}}>
name="arrow-left"
size={28}
backgroundColor="transparent"
onPress={() => TrackPlayer.skipToPrevious()}/>
name={playerState == State.Playing ? 'pause' : 'play'}
size={28}
backgroundColor="transparent"
onPress={handlePlayPress}/>
name="arrow-right"
size={28}
backgroundColor="transparent"
onPress={() => TrackPlayer.skipToNext()}/>
name="random"
size={28}
backgroundColor="transparent"
onPress={onShuffle}/>
);
}
运行该应用程序后,您可以使用随机播放功能:
添加一个按钮来自己播放随机音乐曲目!同样,您可以重新排序播放列表项并通过操纵曲目播放器队列来创建多个播放列表。播放列表管理操作将有效地工作,因为该库使用适当的数据结构在本机端处理播放列表。
我们已经在上述组件中使用了一些轨道播放器事件。例如,在Header组件中,我们使用useTrackPlayerEventsHook 来检测音乐曲目变化事件。
该库允许您为两种事件类型附加函数:
应用内事件:这些事件在应用内自动发生或由用户启动,即播放/暂停事件。库提供useTrackPlayerEvents和usePlaybackStateHooks 来订阅这些应用内事件
远程事件:这些事件由操作系统发起,即当用户按下通知区域迷你播放器的播放 按钮时,库会调度该事件。我们将在下一节讨论处理远程事件Event.RemoteNext
您可以从官方文档中浏览所有支持的事件详细信息。
用户通常在使用音乐应用程序时同时处理多项任务。例如,移动用户可能会在听音乐的同时使用消息传递应用程序。
音乐应用程序通常即使在后台模式下也会播放当前播放列表,但如果用户想播放下一首歌曲怎么办?用户可以按下通知面板中的下一步 按钮,而不是再次打开音乐播放器应用程序。
运行示例应用程序并检查通知栏。您会看到一个小型的、特定于平台的播放器组件,如下所示:
但是,您还不能用这个迷你播放器控制播放列表。原因是库触发远程事件处理程序而不是更改轨道播放器状态。这种情况为开发人员提供了按照他们的意愿处理远程事件的灵活性。
您还记得我们在演示应用程序代码库的某处发表过评论吗?这就是我们将 附加到库的地方——但我们还没有为远程事件实现操作。TODO:playbackService
使用以下代码playbackService根据远程事件控制轨道播放器:
export async function playbackService() {
TrackPlayer.addEventListener(Event.RemotePause, () => {
console.log('Event.RemotePause');
TrackPlayer.pause();
});
TrackPlayer.addEventListener(Event.RemotePlay, () => {
console.log('Event.RemotePlay');
TrackPlayer.play();
});
TrackPlayer.addEventListener(Event.RemoteNext, () => {
console.log('Event.RemoteNext');
TrackPlayer.skipToNext();
});
TrackPlayer.addEventListener(Event.RemotePrevious, () => {
console.log('Event.RemotePrevious');
TrackPlayer.skipToPrevious();
});
}
即使应用程序在后台播放,上述服务也会执行。播放/播放器事件应该在后台模式下按预期工作——换句话说,该库支持后台模式而无需自定义调整!react-native-track-player
运行该应用程序,在音乐播放器上打开另一个应用程序,然后使用通知区域的迷你播放器播放下一首音乐曲目——一切都会正常进行。
在 Android 上,音乐播放器应用会删除通知区域的迷你播放器并在终止时停止播放音乐,但您可以通过在服务中使用以下设置来避免此行为setupPlayer:
await TrackPlayer.updateOptions({
android: {
appKilledPlaybackBehavior:
AppKilledPlaybackBehavior.ContinuePlayback,
},
// ---
在本教程中,我们使用硬编码播放列表进行演示。但是,在制作音乐应用程序中,您可能需要以更易于管理的方式存储播放列表。考虑以下用于存储播放列表信息的选项:
如果您的应用程序自动从设备存储中获取音乐文件(即使用,请考虑将播放列表缓存在应用程序首选项或临时文件中react-native-fs)
如果您让用户管理播放列表,您还可以缓存播放列表并提供导出/导入播放列表的功能
如果您的音乐应用程序是远程音乐播放器(例如 Spotify),您无疑可以将播放列表存储在服务器中并提供用于播放列表管理的 CRUD API
在本教程中,我们开发了一个基于播放列表的音乐曲目播放器来学习库功能。该库允许您创建和管理可播放的音乐播放列表。react-native-track-playerreact-native-track-player
或者,您可以使用库来播放音乐并使用 JavaScript 自己处理播放列表——然后,您将必须为基于事件的整个播放列表队列实现编写代码。即使您肯定可以开发这样的实现,您也可能会遇到应用程序性能问题,因为您在 JavaScript 中同时处理播放事件和播放列表状态。react-native-soundreact-native-sound
该库处理本机端的所有内容,并将事件分派给 JavaScript 以供 UI 更新使用。因此,使用可播放的音乐播放列表管理可以提高您的工作效率,并为您提供性能优先、生产就绪的解决方案。react-native-track-playerreact-native-track-player