更新记录
1.1.0(2026-11-12) 下载此版本
- 新增
onRecordState注册式监听:录音异常中断时触发,code = 1005,data 为已自动保存的文件路径 - Android:采集线程遇 read 错误 / 写文件异常(麦克风被抢占、存储写满等)时自动收尾(回写 wav 头、释放麦克风、关闭前台服务)并回调
- iOS:录音期间轮询
isRecording(0.5s),来电打断 / 编码错误 / 系统停止录音时自动收尾并回调 - 收尾逻辑抽为统一函数,
finishing标志防止 stopRecord 与异常收尾并发重复处理 - 注意:App 进程被系统杀死时无法回调(进程内代码已终止),前端可用 storage 记录路径 + 下次启动检查做补救
平台兼容性
uni-app(3.98)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | - | × | × | √ | - | 9.0 | 16 | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | - | - |
uni-app x(3.98)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | - | - | - | - |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| × | × | × | √ |
LordXuan-recorder
UTS 原生录音插件,支持 Android / iOS 后台录音,输出标准 wav 文件,Android 9+ 自动挂载麦克风类型前台服务 + 常驻通知,避免后台录音被系统静音。
- Android:
AudioRecord采集 16bit PCM,边采边写 wav(44 字节文件头 + PCM 数据) - iOS:
AVAudioRecorder+AVAudioSession(playAndRecord),配合UIBackgroundModes: audio支持后台录音 - HarmonyOS:占位实现,统一回调
code = -1 - 全部使用系统原生 API,不引入任何三方 aar / framework
目录结构
LordXuan-recorder/
├── utssdk/
│ ├── interface.uts # 统一接口与类型(三端共用)
│ ├── unierror.uts # 统一错误码
│ ├── app-android/
│ │ ├── index.uts # Android 实现(AudioRecord + 前台服务 + 通知)
│ │ ├── config.json # minSdkVersion
│ │ └── AndroidManifest.xml # 权限 + Service 声明(打包自动合并)
│ ├── app-ios/
│ │ ├── index.uts # iOS 实现(AVFoundation)
│ │ └── config.json # deploymentTarget
│ └── app-harmony/
│ ├── index.uts # 鸿蒙占位
│ └── config.json
├── package.json
├── changelog.md
└── readme.md
API
所有方法都是 callback 风格,回调参数统一为:
{
code: number, // 0 成功,非 0 失败
msg: string,
data: any | null
}
| 方法 | 参数 | data |
|---|---|---|
checkRecordPermission(callback) |
- | boolean 是否已授权 |
requestRecordPermission(callback) |
- | boolean 是否已授权 |
startRecord(options, callback) |
RecordOption |
string 录音文件绝对路径(此时文件已创建但只有 44 字节 wav 头,尚无音频数据) |
stopRecord(callback) |
- | string 录音文件绝对路径(文件已完整,可播放 / 上传) |
getSystemSdkVersion(callback) |
- | Android 返回 SDK_INT,iOS / 鸿蒙返回 -1 |
onRecordState(callback) |
- | 注册录音状态监听,异常中断时触发,见下方说明 |
RecordOption
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
filePath |
string |
自动生成 | 保存路径,见下方路径规则 |
sampleRate |
number |
44100 |
采样率 |
channel |
number |
1 |
1 单声道,2 立体声 |
路径规则:
- 不传:保存到应用私有目录
lordxuan_record_<时间戳>.wav _doc/rec.wav:保存到应用私有files目录/storage/.../rec.wav:按绝对路径保存(需自行保证目录可写)rec.wav:保存到应用私有目录根目录
错误码(unierror.uts)
| code | 说明 |
|---|---|
0 |
成功 |
1001 |
权限拒绝 |
1002 |
录音已经在进行中 |
1003 |
录音启动失败(含创建文件失败、麦克风占用、前台服务启动失败、App 不在前台) |
1004 |
未开始录音就调用停止 |
1005 |
录音异常中断,插件已自动收尾并保存文件,data 为文件路径(通过 onRecordState 回调) |
-1 |
鸿蒙暂未实现录音 |
异常中断监听 onRecordState
录音过程中可能被外部因素中断:来电、其他 App 抢占麦克风、存储写满、系统停止录音等。插件检测到异常中断后会自动完成收尾(回写 wav 头、释放麦克风、关闭前台服务与通知),并通过 onRecordState 通知前端:
import { onRecordState } from '@/uni_modules/LordXuan-recorder'
// 建议在 App 启动时就注册,重复调用以最后一次为准
onRecordState((res) => {
if (res.code === 1005) {
// res.data 为已自动保存的文件路径,可正常播放/上传
console.log('录音异常中断,文件已保存:', res.data)
}
})
注意:App 进程被系统杀死时无法回调(进程内代码已全部终止)。针对这种情况,前端可用 storage 做补救:
// startRecord 成功时记录
uni.setStorageSync('lastRecording', res.data)
// stopRecord 成功后清除
uni.removeStorageSync('lastRecording')
// App 下次启动时检查:key 仍存在说明上次录音被进程杀死中断,可清理坏文件
const last = uni.getStorageSync('lastRecording')
if (last) {
uni.removeStorageSync('lastRecording')
// 此文件只有 wav 头没有数据,可删除或提示用户
}
Vue 页面调用示例
UTS 插件仅 App(Android / iOS)端可用,import 与调用必须放在 #ifdef APP-PLUS 条件编译里,否则编译到小程序 / web 端会报"文件查找失败":
<template>
<view class="page">
<button @click="checkPermission">检查权限</button>
<button @click="requestPermission">申请权限</button>
<button type="primary" @click="start">开始录音</button>
<button type="warn" @click="stop">停止录音</button>
<text class="tip">{{ tip }}</text>
<text class="path" v-if="filePath">{{ filePath }}</text>
<button v-if="filePath" @click="play">播放录音</button>
</view>
</template>
<script>
// #ifdef APP-PLUS
import {
checkRecordPermission,
requestRecordPermission,
startRecord,
stopRecord,
getSystemSdkVersion
} from '@/uni_modules/LordXuan-recorder'
// #endif
export default {
data() {
return {
tip: '等待操作',
filePath: ''
}
},
mounted() {
// #ifdef APP-PLUS
getSystemSdkVersion((res) => {
console.log('系统版本:', res)
})
// #endif
},
methods: {
checkPermission() {
// #ifdef APP-PLUS
checkRecordPermission((res) => {
this.tip = `权限状态:code=${res.code}, granted=${res.data}`
})
// #endif
},
requestPermission() {
// #ifdef APP-PLUS
requestRecordPermission((res) => {
this.tip = `申请结果:${res.msg},granted=${res.data}`
})
// #endif
},
start() {
// #ifdef APP-PLUS
startRecord({
// 不传 filePath 时插件自动生成
filePath: '_doc/lordxuan_' + Date.now() + '.wav',
sampleRate: 44100,
channel: 1
}, (res) => {
console.log('startRecord:', res)
if (res.code === 0) {
this.filePath = res.data
this.tip = '录音中……可切到后台测试'
// Android 9+ 通知栏出现「正在录音中」常驻通知
} else {
this.tip = `启动失败:${res.msg}`
}
})
// #endif
},
stop() {
// #ifdef APP-PLUS
stopRecord((res) => {
console.log('stopRecord:', res)
if (res.code === 0) {
this.filePath = res.data
this.tip = '录音已保存'
} else {
this.tip = `停止失败:${res.msg}`
}
})
// #endif
},
play() {
const innerAudioContext = uni.createInnerAudioContext()
innerAudioContext.src = this.filePath
innerAudioContext.play()
}
}
}
</script>
<style>
.page {
padding: 40rpx;
}
button {
margin-bottom: 24rpx;
}
.tip {
display: block;
margin-top: 24rpx;
color: #666;
}
.path {
display: block;
margin-top: 16rpx;
font-size: 24rpx;
color: #999;
word-break: break-all;
}
</style>
项目根目录 manifest.json 需要补充的配置
Android 的权限与 Service 已由插件自带的 utssdk/app-android/AndroidManifest.xml 自动合并,正常无需再配置。若你的打包环境未合并,可在 app-plus.distribute.android.permissions 手动补:
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>",
"<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_MICROPHONE\"/>",
"<uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\"/>"
]
}
iOS 必须补麦克风用途描述与后台音频模式:
"ios": {
"privacyDescription": {
"NSMicrophoneUsageDescription": "用于录制语音并保存为本地音频文件"
},
"UIBackgroundModes": ["audio"]
}
说明:
NSMicrophoneUsageDescription缺失时,iOS 上申请麦克风权限会直接失败- 未开启
audio后台模式时,App 退到后台会挂起,录音中断 - HBuilderX 也可以在
manifest.json可视化界面 → App 模块配置 / iOS 后台运行能力 中勾选,效果一致
调试说明(必看)
- 必须使用自定义调试基座:
运行 → 运行到手机或模拟器 → 制作自定义调试基座,标准基座不包含 UTS 原生插件代码。 - 原生配置(AndroidManifest.xml / 权限 / config.json)必须重新打基座或云打包才生效,改完不要只热刷新。
- Android 建议真机测试,模拟器部分机型没有麦克风或前台服务行为不一致。
- 前台服务限制:App 已经进入后台时不允许再启动前台录音服务,插件在启动前会校验 App 是否在前台,不在前台直接回
1003;请务必在页面上点击「开始录音」后再切后台。 - Android 13+ 需要通知权限才能看到常驻通知,插件会在
requestRecordPermission时一并申请。 - 通知是
ongoing(不可滑动关闭),stopRecord后会自动移除并停止服务。
常见问题
Q:控制台报 Unable to instantiate service uts.sdk.modules.LordXuanRecorder.RecordService?
说明插件包名与清单里的 android:name 不匹配。UTS 插件默认包名规则为 uts.sdk.modules. + 插件 id 转驼峰(LordXuan-recorder → LordXuanRecorder)。若你的工程生成的包名不同(例如首字母被小写),请同时修改:
utssdk/app-android/AndroidManifest.xml中package与<service android:name>utssdk/app-android/index.uts中的SERVICE_CLASS_NAME常量
Q:Android 后台录音没有声音?
确认是否走的是前台服务(SDK>=28 必须),以及是否授予了通知权限;部分 ROM 还需要在系统设置里允许「后台运行 / 自启动」。
Q:录音文件在电脑上放不出声?
插件输出的是标准 PCM wav(44 字节头),若文件头未回写(例如 App 被强杀),时长信息会为 0,可用工具修复;正常 stopRecord 流程会自动回写。

收藏人数:
下载插件并导入HBuilder
下载示例项目ZIP
赞赏(0)
下载 4
赞赏 0
下载 12761557
赞赏 1959
赞赏
京公网安备:11010802035340号