鸿蒙开发封装音频播放 AVPlayer 和 申请长时任务
使用AVPlayer可以实现端到端播放原始媒体资源,本开发指导将以完整地播放一首音乐作为示例,向开发者讲解AVPlayer音频播放相关功能。如需播放PCM音频数据,请使用AudioRenderer。
播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。
在进行应用开发的过程中,开发者可以通过AVPlayer的state属性主动获取当前状态或使用on('stateChange')方法监听状态变化。如果应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。
1. 封装一个本地音频播放:
import { media } from '@kit.MediaKit';
// 封装 播放本地音频
class AVPlayerManager {
private avPlayer: media.AVPlayer | null = null
private loop: boolean = false
private rawFdPath: string = ''
async getAVPlayerInstance() {
// 如果已存在,直接返回
if (this.avPlayer !== null) {
return this.avPlayer
}
// 初始化播放器
const player = await media.createAVPlayer()
player.on('stateChange', (state) => {
switch (state) {
case 'initialized':
player.prepare()
break;
case 'prepared':
player.play()
break;
case 'playing':
player.play()
break;
case 'paused':
player.pause()
break;
case 'completed':
if (this.loop) {
player.play() // 播放结束继续播放:循环播放
} else {
player.stop() // 播放结束
}
break;
case 'stopped':
player.reset() // stop 时 reset -> 释放音频资源
break;
default:
break;
}
})
this.avPlayer = player
return this.avPlayer
}
// 加载 src/main/resources/rawfile 的文件
async playByRawSrc(rawFdPath: string) {
const player = await this.getAVPlayerInstance()
// 先释放原来的资源
await player.reset()
// 获取文件信息
const context = getContext()
// 加载 src/main/resources/rawfile 文件夹中的文件
const fileDescriptor = await context.resourceManager.getRawFd(rawFdPath)
// 设置播放路径
player.fdSrc = fileDescriptor
// 播放
player.play()
}
// 停止播放
async stop() {
const player = await this.getAVPlayerInstance()
this.loop = false
player.stop()
}
// 是否循环播放
async setLoop(isLoop: boolean) {
this.loop = isLoop
}
}
export const avPlayerManager = new AVPlayerManager()
2. 添加本地 音频文件:
目录地址:下载声音素材文件,解压到 src/main/resources/rawfile 文件夹中。如果没有 rawfile 文件夹,请新建 rawfile 文件夹。
音频文件下载:室内守护 (yuque.com)
3. 调用播放音频:
Button('播放本地声音')
.onClick(() => {
// 播放本地 rawfile 目录下的资源
avPlayerManager.playByRawSrc('lab_alarm.wav')
// 设置为循环播放
avPlayerManager.setLoop(true)
})
4. 申请长时任务(后台任务):
4.1 添加长时任务权限(module.json5):
{ // 申请长时任务(后台播放、后台下载、后台录音、后台定位)
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
},
4.2 封装长时任务API:
import { bundleManager, wantAgent } from '@kit.AbilityKit'
import { avSession } from '@kit.AVSessionKit'
import { backgroundTaskManager } from '@kit.BackgroundTasksKit'
class BackgroundRunningManager {
// 申请长时任务
async startBackgroundRunning() {
const context = getContext()
// 重点1: 提供音频后台约束能力,音频接入AVSession后,可以进行后台音频播放
const session = await avSession.createAVSession(context, 'guardianSession', 'audio')
await session.activate()
// 获取 bundle 应用信息
const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)
// 通过wantAgent模块下getWantAgent方法获取WantAgent对象
const wantAgentObj = await wantAgent.getWantAgent({
// 添加需要被拉起应用的bundleName和abilityName
wants: [{ bundleName: bundleInfo.name, abilityName: "EntryAbility" }],
// 使用者自定义的一个私有值
requestCode: 0,
})
// 重点2: 创建后台任务
await backgroundTaskManager.startBackgroundRunning(context,
backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj)
}
// 停止后台任务
async stopBackgroundRunning() {
backgroundTaskManager.stopBackgroundRunning(getContext())
}
}
export const backgroundRunningManager = new BackgroundRunningManager()
4.3 使用创建后台任务:
aboutToAppear() {
// 播放本地 rawfile 目录下的资源
avPlayerManager.playByRawSrc('lab_alarm.wav')
// 设置为循环播放
avPlayerManager.setLoop(true)
// 申请后台人任务
backgroundRunningManager.startBackgroundRunning()
}
aboutToDisappear(): void {
avPlayerManager.stop() // 停止播放
// 关闭后台任务
backgroundRunningManager.stopBackgroundRunning()
}