项目背景:项目是用 vue 写的,最终打包为 apk ,其中涉及到录音的功能,利用 h5+ 实现的。
(在vue中集成 html5 plus, 参考 https://www.cnblogs.com/luobiao/p/10552030.html)
需求:长按录音,录音之前判断是否已经获取录音权限,如果没有权限,则需要获取权限;如果有权限,则开始录音。
录音功能,使用了触摸事件,触摸开始,则录音开始,触摸结束,则录音结束。并且限制录音时长最长为一分钟
因为要使用录音,所以在 mounted 钩子函数中需要先获取设备的录音对象
使用 plus.audio.getRecorder() 可以获取设备的录音对象。
mounted () {
let vm = this
this.onPlusReady(() => {
console.log('plus ready')
// eslint-disable-next-line
vm.recorderPlus = plus.audio.getRecorder()
})
},
录音时,首先要先判断是否已经获取录音的权限。 plus.navigator.checkPermission() 方法可以检查运行环境的权限。
plus.navigator.checkPermission(permission)
向系统检查当前程序的权限状态,不触发权限相对应的功能API的调用。
permission : 要检查的权限名称。
返回值:"authorized"表示程序已被用户授权使用此权限; "denied"表示程序已被用户拒绝使用此权限; "undetermined"表示程序未确定是否可使用此权限,此时调用对应的API时系统会弹出提示框让用户确认; "notdeny"表示程序未被用户拒绝使用此权限(与denied相反,可能是"authorized"或者"undetermined"); "unknown"表示程序未知此权限状态(系统存在权限管理但无法查询); "unsupported"表示程序不支持此权限。
startRecord () {
if (this.recorderPlus === null) {
this.$toast('Device not ready!')
return
}
// 判断权限
// eslint-disable-next-line
let permission = plus.navigator.checkPermission('RECORD')
console.log(permission)
switch (permission) {
case 'authorized': // 允许
this.record()
break
case 'denied': // 拒绝
this.requestPermission()
break
case 'undetermined': // 询问
this.requestPermission()
break
case 'unknown': // 未知
this.record()
break
default:
this.$toast('设备不支持录音')
break
}
},
获取权限时,安卓 和 ios 的处理方式不同。
对于安卓手机,plus.android 提供了获取权限的方法。
plus.android.requestPermissions(permissions, successCb, errorCb)
permissions: Array[String] 申请的权限列表(要申请的权限需在应用manifest.json的“模块权限配置”中勾选)
succesCb: 申请权限成功回调函数
返回申请权限的结果,可能被用户允许 回调函数的参数event包含以下属性:
errorCb: 申请权限失败回调函数
// eslint-disable-next-line
plus.android.requestPermissions(['android.permission.RECORD_AUDIO'], function (e) {
if (e.deniedAlways.length > 0) { // 权限被永久拒绝
vm.$dialog.alert({
message: '录音权限被永久拒绝,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。'
})
}
if (e.deniedPresent.length > 0) { // 权限被临时拒绝
vm.$dialog.confirm({
message: '拒绝开启录音权限,将不能使用此功能!确定拒绝开启吗?',
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {})
.catch(() => {
vm.requestPermission()
})
}
if (e.granted.length > 0) { // 权限被允许
}
}, function (e) {
vm.$dialog.alert({
message: '请求录音权限失败,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。'
})
})
但是对于 ios , 并没有直接的方法获取权限。最后采取的解决办法是,在没有录音权限的时候,先主动调用一次录音的api,此时 ios 回去请求一次录音的权限。如果没有选择不允许使用权限,则触发录音失败的回调函数。
vm.recorderPlus.record({}, function () {
}, function (e) {
if (e.code === 2) {
vm.$dialog.alert({
message: '录音权限未允许,请到设置手动开启权限,否则将不能使用此功能。'
})
}
console.log(JSON.stringify(e))
})
vm.recorderPlus.stop()
因为两个平台需要区别对待,plus 提供了判断平台的方法,plus.os.name
获取录音权限的 requestPermission() 方法的完整代码为
requestPermission () {
let vm = this
// eslint-disable-next-line
let platform = plus.os.name
if (platform === 'Android') {
// 动态申请权限
// eslint-disable-next-line
plus.android.requestPermissions(['android.permission.RECORD_AUDIO'], function (e) {
if (e.deniedAlways.length > 0) { // 权限被永久拒绝
vm.$dialog.alert({
message: '录音权限被永久拒绝,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。'
})
}
if (e.deniedPresent.length > 0) { // 权限被临时拒绝
vm.$dialog.confirm({
message: '拒绝开启录音权限,将不能使用此功能!确定拒绝开启吗?',
confirmButtonText: '确定',
cancelButtonText: '取消'
}).then(() => {})
.catch(() => {
vm.requestPermission()
})
}
if (e.granted.length > 0) { // 权限被允许
}
}, function (e) {
vm.$dialog.alert({
message: '请求录音权限失败,请到设置权限里找到应用手动开启权限,否则将不能使用此功能。'
})
})
} else if (platform === 'iOS') {
vm.recorderPlus.record({}, function () {
}, function (e) {
if (e.code === 2) {
vm.$dialog.alert({
message: '录音权限未允许,请到设置手动开启权限,否则将不能使用此功能。'
})
}
console.log(JSON.stringify(e))
})
vm.recorderPlus.stop()
} else {
this.record()
}
},
录音 record()方法的完整代码
data () {
return {
recording: false, // 是否有录音在进行中
timeLimit: 60, // 时间限制(s)
remainTime: 60, // 剩余时间(s)
timeOut: 10, // 剩余时间提示(s)
}
},
record () {
let vm = this
if (vm.recording) {
return false
}
vm.recording = true
if (vm.timer) {
clearInterval(vm.timer)
}
vm.remainTime = vm.timeLimit
let duration = 0
vm.timer = setInterval(function () {
duration++
vm.remainTime = vm.timeLimit - duration
if (duration === vm.timeLimit) {
vm.stopRecord()
}
}, 1000)
let rates = vm.recorderPlus.supportedSamplerates
vm.recorderPlus.record({filename: '_doc/audio/', format: 'wav', samplerate: rates[0]}, function (path) {
console.log('录音文件的路径为:' + path)
}, function (e) {
let error = JSON.stringify(e)
vm.$toast('Audio record failed: ' + error)
if (vm.timer) {
clearInterval(vm.timer)
}
if (vm.recording) {
vm.recording = false
}
})
},
结束录音的方法
stopRecord () {
let vm = this
if (vm.timer) {
clearInterval(vm.timer)
}
if (vm.recording) {
vm.recording = false
vm.recorderPlus.stop()
}
},
写在最后:此解决方案,在开发时,我只用 iPhone X 和 OPPO R11 进行了测试,没有发现问题。公司资源有限,后来测试也没有测试到所有机型。现在 app 已经发布到应用市场,随着用户的增加,目前为止,还没有收到录音获取权限不起作用的反馈。如有问题,欢迎大家分享反馈。