3606 字
18 分钟
后台模式

React Native Track Player 后台模式#

React Native Track Player 支持在所有受支持平台上在应用处于后台时播放音频。本指南将详细介绍如何配置和使用后台音频播放功能,包括平台特定配置、通知自定义和最佳实践。

1. Android 后台音频#

1.1 基本配置#

在 Android 平台上,后台音频播放功能默认是启用的。默认行为是:

  • 当应用在后台时,音频会继续播放
  • 即使用户关闭应用,音频也会继续播放

1.2 应用关闭后的播放行为#

如果不希望在应用关闭后继续播放音频,可以使用 android.appKilledPlaybackBehavior 属性进行配置:

import TrackPlayer, { AppKilledPlaybackBehavior } from 'react-native-track-player';
await TrackPlayer.updateOptions({
android: {
// 配置应用关闭后的播放行为
appKilledPlaybackBehavior: AppKilledPlaybackBehavior.StopPlaybackAndRemoveNotification
},
// 其他配置...
});

1.3 AppKilledPlaybackBehavior 选项#

AppKilledPlaybackBehavior 支持以下几种行为模式:

选项描述
ContinuePlayback默认值,应用关闭后继续播放音频并显示通知
PausePlayback应用关闭后暂停播放但保留通知
StopPlaybackAndRemoveNotification应用关闭后停止播放并移除通知

2. Android 通知#

当应用在后台播放音频时,会显示一个媒体控制通知。

2.1 通知显示条件#

通知只有在以下情况下才会可见:

  • 选择了 AppKilledPlaybackBehavior.ContinuePlaybackAppKilledPlaybackBehavior.PausePlayback
  • Android 系统未因内存不足、崩溃或其他问题终止播放服务

2.2 通知点击行为#

点击通知会打开应用。你可以通过 Linking API 实现自定义初始化,例如直接打开播放器界面:

// 检测通知点击
import { Linking } from 'react-native';
Linking.addEventListener('url', (event) => {
if (event.url === 'trackplayer://notification.click') {
// 自定义通知点击行为,例如导航到播放器界面
navigation.navigate('Player');
}
});

2.3 Android 8.0+ 通知频道配置#

在 Android 8.0(API 级别 26)及以上版本,所有通知都必须属于一个通知频道。你可以通过 updateOptions 配置通知频道:

await TrackPlayer.updateOptions({
android: {
// 通知频道 ID
channelId: 'music-player',
// 通知频道名称
channelName: '音乐播放器',
// 通知频道描述
channelDescription: '控制音乐播放',
// 通知频道重要性
channelImportance: TrackPlayer.CHANNEL_IMPORTANCE_LOW,
// 是否显示通知计数
channelShowBadge: true
},
// 其他配置...
});

2.4 通知操作按钮配置#

你可以自定义通知上的操作按钮:

await TrackPlayer.updateOptions({
// 通知控制按钮
notificationCapabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_SKIP_TO_NEXT,
TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS,
TrackPlayer.CAPABILITY_STOP,
TrackPlayer.CAPABILITY_SEEK_TO
],
// 锁定屏幕控制按钮
capabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_SKIP_TO_NEXT,
TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS
],
// 其他配置...
});

3. iOS 后台音频#

3.1 启用后台模式#

要在 iOS 上允许后台音频播放,需要在 Xcode 中激活 ‘Audio, Airplay and Picture in Picture’ 后台模式:

  1. 打开项目的 Xcode 工作区
  2. 选择目标应用
  3. 点击 ‘Signing & Capabilities’ 标签
  4. 点击 ’+’ 添加 ‘Background Modes’ capability
  5. 勾选 ‘Audio, Airplay and Picture in Picture’ 选项

3.2 静音模式播放#

要在 iOS 静音模式下允许音频播放,需要配置音频会话:

import TrackPlayer from 'react-native-track-player';
await TrackPlayer.updateOptions({
ios: {
// 允许在静音模式下播放
playsInSilentModeIOS: true,
// 配置音频会话类别
category: TrackPlayer.IOSCategory.Playback,
// 配置音频会话模式
mode: TrackPlayer.IOSMode.Default
},
// 其他配置...
});

3.2 iOS 模拟器限制#

从 iOS Simulator 版本 11 开始,Apple 移除了模拟器上的 Control Center 和 Now Playing Info 支持。因此:

  • 无法在最新版本的 iOS 模拟器上测试锁屏控制
  • 建议在真实设备上测试后台音频功能
  • 或者使用旧版本的 iOS 模拟器进行测试

3.3 iOS 音频会话配置#

在 iOS 上,你可以通过 updateOptions 配置音频会话类别和模式:

import TrackPlayer from 'react-native-track-player';
await TrackPlayer.updateOptions({
ios: {
// 配置音频会话类别
category: TrackPlayer.IOSCategory.Playback,
// 配置音频会话模式
mode: TrackPlayer.IOSMode.Default,
// 是否允许混音
allowsMixingWithOthers: false
},
// 其他配置...
});

4. Web 后台音频#

4.1 Web Audio API 支持#

在 Web 平台上,后台音频播放依赖于浏览器的 Web Audio API 和媒体会话 API:

  • 现代浏览器(Chrome、Firefox、Safari、Edge)都支持后台音频播放
  • 但需要用户与页面进行交互才能开始播放
  • 浏览器可能会在一段时间无交互后停止后台播放
  • 需要使用 HTTPS 协议(本地开发环境除外)

4.2 媒体会话 API#

使用媒体会话 API 可以为 Web 应用添加后台控制支持:

// 注册媒体会话操作
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('play', () => TrackPlayer.play());
navigator.mediaSession.setActionHandler('pause', () => TrackPlayer.pause());
navigator.mediaSession.setActionHandler('previoustrack', () => TrackPlayer.skipToPrevious());
navigator.mediaSession.setActionHandler('nexttrack', () => TrackPlayer.skipToNext());
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.seekTime) {
TrackPlayer.seekTo(details.seekTime * 1000);
}
});
}
// 更新媒体会话元数据
function updateMediaSession(track) {
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: track.title,
artist: track.artist,
album: track.album,
artwork: [
{ src: track.artwork, sizes: '96x96', type: 'image/png' },
{ src: track.artwork, sizes: '128x128', type: 'image/png' },
{ src: track.artwork, sizes: '192x192', type: 'image/png' },
{ src: track.artwork, sizes: '256x256', type: 'image/png' },
{ src: track.artwork, sizes: '384x384', type: 'image/png' },
{ src: track.artwork, sizes: '512x512', type: 'image/png' },
]
});
}
}

4.3 Web 平台限制#

Web 平台的后台音频播放存在一些限制:

  • 交互要求:需要用户与页面进行明确交互后才能开始播放
  • 休眠策略:浏览器可能会在一段时间无交互后暂停后台播放
  • 移动端限制:在移动设备上,后台标签页可能会被浏览器限制资源使用
  • HTTPS 要求:在生产环境中需要使用 HTTPS 协议
  • 浏览器兼容性:不同浏览器的实现可能存在差异

4.4 Service Worker 支持#

在支持 Service Worker 的浏览器中,你可以使用 Service Worker 来增强后台音频功能:

service-worker.js
self.addEventListener('fetch', (event) => {
// 处理音频文件请求
if (event.request.url.endsWith('.mp3') || event.request.url.endsWith('.m4a')) {
event.respondWith(
caches.open('audio-cache').then((cache) => {
return cache.match(event.request).then((response) => {
return response || fetch(event.request).then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
});
});
})
);
}
});
// 注册 Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js')
.then((registration) => {
console.log('Service Worker 注册成功:', registration.scope);
})
.catch((error) => {
console.log('Service Worker 注册失败:', error);
});
});
}

5. 跨平台配置#

5.1 使用 updateOptions 配置后台行为#

你可以使用 updateOptions 方法来配置跨平台的后台音频行为:

import TrackPlayer from 'react-native-track-player';
await TrackPlayer.updateOptions({
// 媒体控制通知配置
notificationCapabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_SKIP_TO_NEXT,
TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS,
TrackPlayer.CAPABILITY_SEEK_TO
],
// 锁定屏幕控制配置
capabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_SKIP_TO_NEXT,
TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS
],
// Android 特定配置
android: {
appKilledPlaybackBehavior: AppKilledPlaybackBehavior.ContinuePlayback
}
});

5.2 自定义通知外观#

你可以自定义 Android 和 iOS 上的通知外观:

await TrackPlayer.updateOptions({
// 通知标题
notificationCapabilities: [
TrackPlayer.CAPABILITY_PLAY,
TrackPlayer.CAPABILITY_PAUSE,
TrackPlayer.CAPABILITY_SKIP_TO_NEXT,
TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS
],
// Android 通知自定义
android: {
// 通知频道 ID
channelId: 'music-player',
// 通知频道名称
channelName: '音乐播放器',
// 通知频道描述
channelDescription: '控制音乐播放',
// 通知小图标
smallIcon: 'ic_notification',
// 大图标
largeIcon: 'ic_launcher',
// 通知颜色
iconColor: '#FF0000',
// 通知控制按钮颜色
playIcon: 'ic_play',
pauseIcon: 'ic_pause',
previousIcon: 'ic_previous',
nextIcon: 'ic_next',
// 停止图标
stopIcon: 'ic_stop'
},
// iOS 通知自定义
ios: {
// 应用图标
appIcon: 'AppIcon',
// 播放图标
playIcon: 'play',
// 暂停图标
pauseIcon: 'pause',
// 上一曲图标
previousIcon: 'previous',
// 下一曲图标
nextIcon: 'next'
}
});

5.3 通知元数据更新#

当播放新曲目时,你需要更新通知中的元数据:

// 播放新曲目时更新元数据
await TrackPlayer.load({
id: 'track-1',
url: 'https://example.com/track.mp3',
title: '歌曲标题',
artist: '艺术家名称',
album: '专辑名称',
artwork: 'https://example.com/artwork.jpg'
});

6. 后台任务处理#

6.1 React Native 后台任务#

在后台播放音频时,你可能需要执行一些后台任务,如:

  • 下载歌词或专辑封面
  • 更新播放进度
  • 同步播放状态到服务器

使用 react-native-background-task 或其他后台任务库可以实现这些功能,但请注意平台限制。

6.2 避免后台任务过度使用#

  • 后台任务会消耗电池并可能被系统终止
  • 尽量减少后台任务的频率和复杂度
  • 使用适当的延迟和批量处理

6.3 监听应用生命周期#

监听应用生命周期事件可以帮助你管理后台播放状态:

import { AppState, AppStateStatus } from 'react-native';
const appState = AppState.currentState;
let backgroundTime = 0;
const handleAppStateChange = (nextAppState: AppStateStatus) => {
if (appState.match(/inactive|background/) && nextAppState === 'active') {
// 应用从后台返回前台
console.log('应用进入前台');
// 更新播放状态
} else if (appState === 'active' && nextAppState.match(/inactive|background/)) {
// 应用从前台进入后台
console.log('应用进入后台');
backgroundTime = Date.now();
}
appState = nextAppState;
};
AppState.addEventListener('change', handleAppStateChange);

6.4 音频焦点管理#

6.4.1 Android 音频焦点#

在 Android 上,音频焦点是指应用对音频输出设备的控制权。当多个应用尝试同时播放音频时,系统会根据音频焦点策略决定哪个应用应该获得焦点。

React Native Track Player 会自动处理音频焦点,但你也可以通过配置自定义行为:

await TrackPlayer.updateOptions({
android: {
// 音频焦点模式
audioFocusMode: TrackPlayer.AUDIO_FOCUS_MODE_GAIN,
// 音频流类型
audioAttributes: {
contentType: TrackPlayer.AUDIO_CONTENT_TYPE_MUSIC,
flags: TrackPlayer.AUDIO_FLAG_AUDIBILITY_ENFORCED,
usage: TrackPlayer.AUDIO_USAGE_MEDIA
}
},
// 其他配置...
});

6.4.2 iOS 音频中断处理#

在 iOS 上,当系统中断音频播放(如来电、Siri)时,你需要处理中断事件:

// 监听音频中断事件
import { Audio } from 'expo-av';
Audio.setAudioModeAsync({
allowsRecordingIOS: false,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
staysActiveInBackground: true,
playThroughEarpieceAndroid: false
});
const handleAudioInterruption = (interruption) => {
if (interruption.isPlaying) {
// 中断结束,恢复播放
TrackPlayer.play();
} else {
// 中断开始,暂停播放
TrackPlayer.pause();
}
};
// 注册中断监听器
Audio.addAudioInterruptionListener(handleAudioInterruption);

7. 常见问题#

7.1 后台播放停止#

如果应用在后台时播放停止,可能的原因:

  • Android: 应用被系统终止以释放内存
  • iOS: 未正确配置后台模式或被系统限制
  • Web: 浏览器策略限制或用户长时间无交互
  • 跨平台: 播放服务未正确注册或运行

7.2 通知不显示#

如果通知不显示,可能的原因:

  • 应用没有通知权限
  • 选择了 StopPlaybackAndRemoveNotification 行为
  • 播放服务已被终止
  • Android 8.0+ 未正确配置通知频道
  • 通知图标资源不存在或格式不正确

7.5 音频路由变化#

当用户插入耳机、连接蓝牙设备或切换音频输出时,你可能需要处理音频路由变化:

// Android 音频路由变化监听
import { AudioManager } from 'react-native-audio-manager';
AudioManager.setListener((result) => {
if (result.event === 'headsetPlug') {
if (result.isPlugged) {
console.log('耳机已插入');
} else {
console.log('耳机已拔出');
}
} else if (result.event === 'audiobecomingnoisy') {
console.log('音频变得嘈杂,暂停播放');
TrackPlayer.pause();
}
});
// 注册监听
AudioManager.registerListener();
### 7.3 远程控制不工作
如果远程控制(如锁屏控制)不工作:
- **Android**: 确保通知正在显示且已配置正确的通知频道
- **iOS**: 在真实设备上测试,而非模拟器
- **Web**: 浏览器不支持媒体会话 API 或需要 HTTPS
- **跨平台**: 确保已正确配置 `capabilities``notificationCapabilities`
### 7.4 iOS 审核注意事项
在提交 iOS 应用到 App Store 时,需要注意:
- 必须明确说明应用需要后台音频功能
- 应用必须在后台播放时有明确的用户价值
- 避免在后台播放无意义的音频
## 8. 最佳实践
1. **始终注册播放服务**: 确保在应用启动时注册播放服务
2. **正确配置后台模式**: 特别是在 iOS 平台上
3. **处理应用生命周期**: 监听应用进入前台/后台的事件
4. **优化资源使用**: 在后台时减少不必要的网络请求和计算
5. **测试真实设备**: 始终在真实设备上测试后台音频功能
6. **请求必要权限**: 在使用前请求通知和音频权限
7. **提供清晰的用户控制**: 让用户可以轻松开启/关闭后台播放
8. **遵循平台指南**: 遵守各平台的后台处理最佳实践
9. **处理边缘情况**: 如网络中断、音频文件错误等
10. **考虑电池寿命**: 避免在后台过度使用资源
后台模式是音乐播放器应用的核心功能之一。通过正确配置和使用 React Native Track Player 的后台音频功能,你可以为用户提供流畅的音乐播放体验,即使应用在后台运行或设备屏幕关闭。
## 9. 性能优化
### 9.1 内存优化
在后台播放音频时,内存管理非常重要:
1. **及时释放资源**: 当不再需要播放服务时,调用 `TrackPlayer.destroy()` 释放资源
2. **限制后台活动**: 减少后台任务的频率和复杂度
3. **优化网络请求**: 使用缓存和批量请求减少网络开销
4. **避免内存泄漏**: 正确管理事件监听器和定时器
```javascript
// 组件卸载时清理资源
useEffect(() => {
return () => {
// 移除事件监听器
AppState.removeEventListener('change', handleAppStateChange);
// 如果不再需要播放服务,销毁它
if (shouldDestroy) {
TrackPlayer.destroy();
}
};
}, []);

9.2 电池优化#

后台音频播放会消耗电池,以下是一些优化建议:

  1. 减少唤醒次数: 避免频繁的后台任务
  2. 使用低功耗模式: 当设备电量低时,减少后台活动
  3. 优化网络使用: 减少网络请求频率
  4. 使用合适的音频编码: 选择高效的音频编码格式

10. 调试技巧#

10.1 后台播放调试#

  1. Android 调试:

    • 使用 adb logcat 查看播放服务日志
    • 使用 Android Studio 监控播放服务状态
    • 测试不同的 AppKilledPlaybackBehavior 选项
  2. iOS 调试:

    • 使用 Xcode 控制台查看日志
    • 在真实设备上测试后台行为
    • 检查音频会话配置
  3. Web 调试:

    • 使用浏览器开发者工具的 Media 面板
    • 检查媒体会话 API 的支持情况
    • 测试不同浏览器的行为

10.2 常见问题排查#

  1. 后台播放停止:

    • 检查应用是否被系统杀死
    • 检查内存使用情况
    • 检查音频焦点设置
  2. 通知不显示:

    • 检查通知权限
    • 检查通知频道配置
    • 检查播放服务状态
  3. 远程控制不工作:

    • 检查 capabilities 配置
    • 检查通知是否正在显示
    • 在真实设备上测试

11. 总结#

  • Android: 默认支持后台播放,可通过 AppKilledPlaybackBehavior 控制应用关闭后的行为
  • iOS: 需要在 Xcode 中启用后台模式,支持锁屏控制
  • Web: 依赖浏览器 API,需要用户交互才能开始播放
  • 所有平台都支持自定义通知和远程控制
  • 音频焦点管理和中断处理对于良好的用户体验至关重要
  • 性能优化和电池管理是后台播放应用的关键考虑因素
  • 遵循最佳实践可以提供更好的用户体验并避免常见问题
后台模式
https://fuwari.vercel.app/posts/react-native-track-player/背景模式/
作者
IceZheng
发布于
2025-12-08
许可协议
CC BY-NC-SA 4.0