uni.createInnerAudioContext()不能用于后台播放,因其是页面级音频上下文,切后台时系统强制暂停;后台播放必须用uni.getBackgroundAudioManager(),且需用户交互后初始化、HTTPS源、平台原生配置。

uni-app 里做音频进度条,必须用 uni.createInnerAudioContext();想让音频在 App 切后台后继续播,得用 uni.getBackgroundAudioManager()——两者不能混用,用途完全不同。
为什么不能用 uni.createInnerAudioContext() 做后台播放
它本质是“页面级音频上下文”,生命周期绑定在当前页面。App 切后台时,iOS 和 Android 都会主动 suspend 其音频线程,即使你没调 pause(),也会无声或中断。这不是 bug,是系统强制行为。
常见错误现象:
- 真机测试时,App 切后台几秒后音乐突然停了,控制台无报错
- 在 iOS 微信里反复触发
play()失败,报错DOMException: The request is not allowed by the user agent - Android 上后台播放一会儿就卡住,再切回来发现
currentTime停滞不动
根本原因:它不持有系统级音频会话(audio session),无法声明“我要持续播放”。所以别指望靠它实现真正的后台音乐。
uni.getBackgroundAudioManager() 的正确初始化时机与限制
这个 API 返回的是全局单例,和页面无关,但初始化有强约束:
- 必须在用户首次交互(如按钮点击)后调用
play(),否则 iOS/Android 都会静音 -
src必须是 HTTPS 地址,HTTP 会被 iOS 直接拦截,控制台显示net::ERR_INSECURE_RESPONSE - 微信小程序端需在
manifest.json中配置"mp-weixin"下的"backgroundMode": ["audio"] - App 端(尤其 iOS)必须在 Xcode 的
Info.plist中手动添加UIBackgroundModes→audio,仅改 manifest 不生效
示例初始化(放在按钮 click 回调中):
const bgm = uni.getBackgroundAudioManager();
bgm.title = '背景音乐';
bgm.src = 'https://example.com/bgm.mp3'; // 必须 HTTPS
bgm.play().catch(e => console.error('后台播放失败:', e));
进度条怎么同步且支持拖动
uni.getBackgroundAudioManager() 提供 onTimeUpdate,但它的触发频率不稳定(尤其在后台),直接绑进度条会跳变。更可靠的做法是:用定时器 + currentTime 主动读取。
- 开始播放后启动
setInterval,每 200–300ms 读一次bgm.currentTime - 拖动时先
bgm.pause(),再bgm.seek(x),最后bgm.play() - 注意
seek()在某些安卓机型上可能不准,建议加setTimeout(() => bgm.play(), 50)避免被系统拦截 - 不要依赖
duration初始化时就存在——它可能为 0,需监听onCanplay后再赋值
关键片段:
bgm.onCanplay(() => {
this.duration = bgm.duration || 0;
});
// 拖动逻辑
handleSeek(value) {
const time = (value / 100) * this.duration;
bgm.pause();
bgm.seek(time);
setTimeout(() => bgm.play(), 50);
}
循环播放与状态同步的坑
uni.getBackgroundAudioManager() 不支持 loop = true,onEnded 事件也只在前台触发一次。后台时播放结束不会触发任何回调。
- 若需循环,必须在前台监听
onEnded,然后手动bgm.seek(0)+bgm.play() - 但用户切后台后,
onEnded就失效了——这意味着后台循环无法自动完成,只能靠前台逻辑兜底 - 跨页面状态不同步:A 页面调用
play(),B 页面拿不到当前播放状态,需用全局变量或 vuex 缓存bgm.playing、bgm.currentTime - 多个页面同时操作同一个
bgm实例,容易互相覆盖title/coverImgUrl,建议统一在 App.vue 初始化并暴露方法
最易被忽略的一点:App 切后台后,onTimeUpdate 和 onEnded 基本不可靠,所有依赖这些事件的 UI 更新(比如进度条、暂停按钮状态)都会失效。你看到的“还在动”,大概率是前端定时器在空跑,实际音频早已停止。


















