uni.getBackgroundAudioManager() 是唯一支持系统控制中心的音频API,仅App端有效;其不支持loop属性,需手动监听onEnded事件实现循环,并严格配置manifest.json才能保证锁屏播放。

uni.getBackgroundAudioManager() 是唯一能进系统控制中心的 API
小程序和 H5 端根本没控制中心概念,只有 App 端(iOS/Android)才能把播放信息同步到锁屏界面和系统媒体中心。而这个能力只绑定在 uni.getBackgroundAudioManager() 上——uni.createInnerAudioContext() 即使播得再稳,也不会出现在控制中心,更别提循环模式了。
它返回的实例自带 play()、pause()、stop(),但**没有 loop 属性或 setLoop 方法**。所谓“循环模式”,其实是靠你手动监听播放结束、触发重播来模拟的,系统控制中心只会显示当前播放状态(播放/暂停),不会显示“循环中”图标。
- iOS 控制中心右滑可看到封面、标题、进度条,但不区分单曲循环/列表循环
- Android 媒体通知栏同理,只反映是否在播放,不暴露循环逻辑
- 用户点控制中心的“下一首”按钮,会触发
onNext事件(需手动实现跳转),不是自动循环
@ended 中手动重播是唯一可行的循环路径
App 端用 uni.getBackgroundAudioManager() 播放音频后,loop="true" 完全无效。必须监听 onEnded 事件,在里面主动调用 seek(0) + play() 来实现单曲循环。
但要注意:iOS 和部分 Android 机型上 seek(0) 可能失败(尤其 MP3 编码不标准时),直接静音且无报错。
- 务必用
try/catch包裹seek(0),失败时 fallback 为重新赋值src(加时间戳参数强制刷新) - 不要在
onEnded里连续调用多次play(),可能触发系统静音策略 -
src必须是 HTTPS 或本地/static/xxx.mp3路径,相对路径或未打包资源会加载失败
const bgAudio = uni.getBackgroundAudioManager();
bgAudio.src = '/static/book.mp3';
bgAudio.onEnded(() => {
try {
bgAudio.seek(0);
} catch (e) {
bgAudio.src = '/static/book.mp3?t=' + Date.now();
}
bgAudio.play();
});
列表循环要自己管索引,别指望系统代劳
控制中心不支持“列表循环”这种概念,它只认当前一个音频。所谓“播完一首自动切下一首”,是你自己维护播放队列、更新 bgAudio.src 并重置元数据(title、coverImgUrl 等)的过程。
关键点不在控制中心,而在你如何衔接两首歌:避免黑屏、卡顿、元数据残留。
- 在
onEnded里计算下一个 index:nextIndex = (currentIndex + 1) % list.length - 更新前先调用
bgAudio.stop(),防止旧音频残留缓冲 - 必须重新设置
bgAudio.title、bgAudio.singer、bgAudio.coverImgUrl,否则控制中心还显示上一首的信息 - 真机调试时 iOS 对
coverImgUrl要求 HTTPS,本地图片要用uni.getFileSystemManager().readFile转 base64
manifest.json 配置漏一项,锁屏就静音
哪怕代码写得再完美,manifest.json 少配一项,iOS 就拒绝后台播放,Android 锁屏几秒后自动中断——而且大概率不报错,只默默静音。
三项必须同时满足:
- iOS:
app-plus.distribute.ios.UIBackgroundModes设为["audio"](不是["playback"]) - Android:
app-plus.background.mode设为"audio" - 确保
app-plus.modules.Audio存在且为{}(启用音频模块)
改完必须重新云打包,热更新无效。H5 端完全不支持该 API,记得用条件编译隔离:#ifdef APP-PLUS。
真正容易被忽略的是:iOS 上如果 manifest 里没勾选对应屏幕方向(比如你锁横屏但 manifest 没开 landscape),连音频初始化都可能失败;Android 上某些厂商 ROM(华为、小米)若没声明 WAKE_LOCK 权限,也会在锁屏后快速中断播放。


















