uni-app 背景音频播放必须用 uni.createinneraudiocontext(),因 标签在 ios 微信和 app 端后台会静音或中断;该 api 可绕过部分限制但需用户手势触发、https 源、配置后台权限,且不支持自动无缝循环,旧版 createaudiocontext 已废弃。

uni-app 背景音频播放必须用 uni.createInnerAudioContext()
uni-app 官方不支持 <audio></audio> 标签在 iOS 微信、App 端后台持续播放,真机上切到后台就静音或中断。唯一可靠方案是使用 uni.createInnerAudioContext() —— 它是 uni-app 封装的原生音频上下文,能绕过部分平台限制(尤其 iOS 微信),但仍有硬性约束。
- iOS 微信:需用户首次点击触发播放(不能自动播),且必须在
onShow或用户手势回调中调用.play() - Android App:后台播放需在 manifest 中开启音频服务权限(
android.permission.FOREGROUND_SERVICE),并配置backgroundMode: audio - H5 端无后台概念,切页即停;不要指望它“后台”运行
-
uni.createInnerAudioContext()不支持设置loop为true后自动无缝循环(iOS 有 100–300ms 间隙),需监听ended事件手动.seek(0)+.play()
为什么 uni.createAudioContext() 已废弃且不可用
旧版 uni.createAudioContext('audioId') 基于 <audio></audio> 标签,依赖 DOM,仅在 H5 有效;在小程序和 App 端实际调用的是空对象或报错 createAudioContext is not a function。uni-app 2.7+ 已明确标记为废弃,文档也不再收录。继续用它,等于在真机上写“假代码”。
- 小程序端:直接返回空对象,
.play()无反应,控制台无报错,极难排查 - App 端(尤其是 iOS):可能触发白屏或音频初始化失败,但错误不抛出
- 替代方案只有
uni.createInnerAudioContext(),它不依赖节点 ID,也不需要提前写 DOM
后台播放失败的三个高频原因
即使用了 uni.createInnerAudioContext(),90% 的“后台无声”问题都出在这三处,按顺序检查:
- 没在用户手势后首次调用
.play()(如放在onLoad里自动播 → iOS 微信直接拒绝) - 音频源是 HTTP 链接(非 HTTPS)→ iOS 强制拦截,控制台报
net::ERR_INSECURE_RESPONSE - App 端未在
manifest.json的 “模块配置” 中勾选 “Background Mode” 并填入audio→ 后台进程被系统杀死,音频中断无提示
示例正确初始化方式:
const audioCtx = uni.createInnerAudioContext();
audioCtx.src = 'https://example.com/music.mp3'; // 必须 HTTPS
audioCtx.autoplay = false;
// 在按钮 click 回调中:
buttonClick() {
audioCtx.play().catch(e => console.error('play failed:', e));
}
跨平台音频状态同步很脆弱
innerAudioContext 的 play/pause/stop 在不同平台行为不一致:iOS 微信暂停后 paused 为 true,但 Android App 可能仍返回 false;seek() 在某些安卓机型上会重置 duration 为 NaN。别依赖 audioCtx.paused 做状态判断,自己维护一个 isPlaying 变量更稳妥。
- 监听
play、pause、stop、ended四个事件,手动同步状态 - 不要在
onHide里调用.pause()→ 某些安卓版本会卡死音频上下文,下次.play()失败 - 切换音频源时,先
.destroy()再新建上下文,避免内存泄漏和状态污染
背景播放不是“打开开关就完事”,而是每个平台都在设障。最麻烦的从来不是怎么播,而是播了之后——它还在不在、有没有声、会不会突然断。










