uni.getbackgroundaudiomanager()是app和小程序后台音频唯一可行方案,因其直接桥接系统音频会话;h5端不支持真正后台播放,需条件编译降级为new audio()并接受切页即停。

App 端和微信小程序必须用 uni.getBackgroundAudioManager(),H5 端不支持真正后台播放,别试 uni.createInnerAudioContext() 或 <audio></audio> 标签——锁屏后基本秒停,尤其 iOS。
为什么 uni.getBackgroundAudioManager() 是唯一可行入口
它不是“增强版 audio”,而是直接桥接 iOS 的 AVAudioSession 和 Android 的 MediaSession,让系统承认“这个 App 正在播音乐”,从而授予后台运行资格。其他 API 全部绑定页面生命周期:切后台后 JS 被挂起、监听器失效、实例可能被销毁,onPlay 之类回调根本不会触发。
常见错误现象:
-
uni.createInnerAudioContext()在真机锁屏后 1–3 秒静音,iOS 微信里甚至不报错也不提示 - 在
onLoad或onShow里直接调play(),iOS 直接拦截,无声无日志 - 用了
uni.getBackgroundAudioManager()却没配 manifest,打包日志里没有background audio enabled提示,等于白写
manifest.json 必须手动改,且不能错位置、错格式
勾选项无效,必须编辑源码视图,iOS 和 Android 配置严格分离:
- iOS:嵌套在
"app-plus" → "distribute" → "ios"下,写成"UIBackgroundModes": ["audio"](注意是数组,"audio"不能拼错、不能带空格) - Android:嵌套在
"app-plus" → "distribute" → "android"下,"permissions"是字符串数组,正确写法:["<uses-permission android:name='\"android.permission.WAKE_LOCK\"'></uses-permission>"](XML 标签必须转义、闭合) - 改完必须重新云打包——本地调试、热更新、模拟器全不生效
播放前必须填全三项元数据,且由用户手势触发
iOS 锁屏界面只认 title、singer、coverImgUrl,缺任意一个,控制条直接不显示;src 必须是 HTTPS 远程地址(/static/xxx.mp3 在 App 端大概率解析失败)。
- 不能在
onLoad或onShow自动调play(),必须等用户点击按钮等明确交互 -
coverImgUrl在 App 端必须是本地绝对路径(如/static/cover.jpg),网络地址无效;微信小程序则要求 HTTPS 且 ≥300×300 像素,否则通知栏“下一曲”按钮不渲染 - 监听状态变化别依赖
onHide/onShow,可靠方式只有manager.onPlay、manager.onPause、manager.onEnded
H5 端要单独降级,别指望它有后台
uni.getBackgroundAudioManager() 在 H5 调用后静默失败,无报错也无效果。必须用条件编译隔离,改用 new Audio() + 页面可见性监听(document.hidden),并接受“切页即停”的事实。
关键点:
- 首次播放仍需用户手势触发,否则浏览器抛
DOMException: play() failed - 不要试图在 H5 模拟锁屏控制——它根本没有系统级音频会话概念
- 封面图、专辑名、上一曲/下一曲这些功能,在 H5 端天然不存在,硬加逻辑只会增加维护成本
最容易被忽略的是:iOS 对元数据字段完整性极其敏感,title 和 singer 少填一个,锁屏界面就只显示“未知”;而 Android 部分机型对 WAKE_LOCK 权限缺失的容忍度极低,锁屏几秒就自动暂停——这些都不是代码 bug,是配置和平台规则没吃透。











