前言
录音功能是手机常见的功能,在HarmonyOS中应该如何实现这一功能呢?
获取权限
向系统权限
由于鸿蒙操作系统的安全性的问题首先需要在module.json5
中配置允许使用麦克风功能。
没啥好说的直接上代码
js
"requestPermissions": [
{
"name":"ohos.permission.MICROPHONE",
"usedScene": {},
"reason":"$string:EntryAbility_desc"
}
],
向用户请求
首次请求
由于上一步操作只是向系统请求麦克风权限,下一步还需要向用户也就是手机哦持有者申请权限。
核心API 使用到了abilityAccessCtrl
js
import { abilityAccessCtrl } from '@kit.AbilityKit'
@Entry
@Component
struct myTest {
async aboutToAppear() {
// 向用户发起麦克风的授权提示
let mgr = abilityAccessCtrl.createAtManager()
// 利用mgr对象向用户发起麦克风的授权
let result = await mgr.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])
}
build() {
Column() {
}
.height('100%')
.width('100%')
.backgroundColor(Color.Pink)
}
}
将res
打印能发现当选择了允许和不允许时authResults
分别对应0和-1,dialogShownResults
分别对应true和false
二次请求
当用户选择不允许时,可以通过直接跳转want
来管理开启麦克风的权限
主要使用Want
API 来完成,Want
是对象间信息传递的载体, 可以用于应用组件间的信息传递。
首先配置Want
的参数
js
const want: Want = {
bundleName: 'com.huawei.hmos.settings',
abilityName: 'com.huawei.hmos.settings.MainAbility',
uri: 'application_info_entry',
parameters: {
// 可以在AppScope下的app.json5中对应的bundleName查看
pushParams: '改成自己的包名'
}
}
利用Want
配合第一次请求的参数判断完成直接跳转到系统权限的设置界面
js
let ctx = getContext() as common.UIAbilityContext
ctx.startAbility(want)
获取录音文件
准备文件
我们需要提前准备好一个文件用来存放录音的信息
使用了fs.openSync
来创建和打开文件, getContext().filesDir
用来获取当前上下文的路径,使用时间戳获得唯一标识符作为文件名字。fd
代表着文件的操作符,后续对文件的操作只需调用fd
即可。
js
const filePath = getContext().filesDir + '/' + Date.now() + '.m4a'
const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
const fd = file.fd
配置录音对象
配置一些录音的基本信息,从官方文档参考即可
js
const config: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, //音频采集源为麦克风
profile: {
audioBitrate: 100000, // 音频比特率
audioChannels: 1, // 音频声道数
audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
audioSampleRate: 48000, // 音频采样率
fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前只支持m4a
},
url: `fd://${file.fd}` //第一步中的文件地址
}
开始录音与结束录音
首先实例化AVRecorder
,调用AVRecorder
上自带的方法即可。使用完毕记得销毁对象。
js
// 创建录音对象
const avRecorder = await media.createAVRecorder()
// 设置录制参数
await avRecorder.prepare(config)
// 开启录音
await avRecorder.start()
// 停止录制
await avRecorder.stop()
// 销毁实例,退出录制。
await avRecorder.release()
播放录音
使用了avPlayer
创建的实力,调用方法对stateChange
进行监听,当其处于prepare
状态时,使用.play
进行播放。打开之前存好的录音的文件地址,进行播放即可。
js
const file = fs.openSync(this.filePath, fs.OpenMode.READ_ONLY) //以只读方式打开录音文件
// 创建播放对象 AVPlayer
const avPlayer = await media.createAVPlayer()
// 注册stateChange监听
avPlayer.on('stateChange', (state) => {
if (state == 'initialized') {
avPlayer.prepare()
}
if (state == 'prepared') {
avPlayer.play()
}
})
// 赋值播放源
avPlayer.url = `fd://${file.fd}`
完整代码参考
js
import { abilityAccessCtrl, common, Want } from '@kit.AbilityKit'
import fs from '@ohos.file.fs';
import { media } from '@kit.MediaKit';
@Entry
@Component
struct myTest {
@StorageProp('topHeight') topHeight: number = 0
avRecorder: media.AVRecorder = Object() // 初始化空对象
async aboutToAppear() {
let mgr = abilityAccessCtrl.createAtManager()
let result = await mgr.requestPermissionsFromUser(getContext(), ['ohos.permission.MICROPHONE'])
if (result.authResults[0] == -1) {
const want: Want = {
bundleName: 'com.huawei.hmos.settings',
abilityName: 'com.huawei.hmos.settings.MainAbility',
uri: 'application_info_entry',
parameters: {
pushParams: 'com.itcast.interview_bjhm4App'
}
}
let ctx = getContext() as common.UIAbilityContext
ctx.startAbility(want)
}
}
build() {
Column() {
Button('开始录制').onClick(async () => {
let filePath = getContext().filesDir + '/' + Date.now() + '.m4a'
let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
const config: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, //音频采集源为麦克风
profile: {
audioBitrate: 100000, // 音频比特率
audioChannels: 1, // 音频声道数
audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前只支持aac
audioSampleRate: 48000, // 音频采样率
fileFormat: media.ContainerFormatType.CFT_MPEG_4A,
},
url: `fd://${file.fd}`
}
const avRecorder = await media.createAVRecorder()
this.avRecorder = avRecorder
await avRecorder.prepare(config)
await avRecorder.start()
AlertDialog.show({ message: JSON.stringify('录音开始') })
})
Button('停止录制').onClick(async () => {
await this.avRecorder.stop() //停止录音
await this.avRecorder.release() //销毁和释放录音对象
})
Button('播放').onClick(async () => {
const avPlayer = await media.createAVPlayer()
avPlayer.on('stateChange', (state) => {
if (state == 'initialized') {
avPlayer.prepare()
}
if (state == 'prepared') {
avPlayer.play()
}
})
// 3. 设置播放源 fd://句柄
const file = fs.openSync(item, fs.OpenMode.READ_ONLY)
avPlayer.url = `fd://${file.fd}`
})
}
.height('100%')
.width('100%')
.padding({ top: this.topHeight })
}
}