开发中使用——鸿蒙播放本地mp3文件
文章目录
- 背景
- 现实
- 解决
- 一、创建AVPlayer实例对象
- 二、设置mp3的播放路径
- 三、设置AVPlayer回调,监听播放事件
- 四、其他操作
- 感谢
- 吐槽
背景
项目中有个功能需要播放本地的mp3音频,想着只是一个简单的功能,看一下官方文档,很容易就实现了,因为苹果和安卓都很容易实现。
现实
现实是打脸的,按照官方文档——使用AVPlayer播放音频(ArkTS)文档写一遍,你会发现无论是加载网上的.mp3文件,还是本地rawfile文件下的.mp3都报错。
解决
一、创建AVPlayer实例对象
/*** 创建Player实例*/async createAVPlayerInstance() {this.avPlayer = await media.createAVPlayer();}
二、设置mp3的播放路径
/*** 设置mp3的播放路径* @param context* @param path*/async setSourcePath(context:common.UIAbilityContext,path: string) {setTimeout(async () => {if (this.avPlayer) {try {let fileDescriptor = await context.resourceManager.getRawFd(path);let fileFd: number = JSON.parse(JSON.stringify(fileDescriptor))['fd']let fileOffset: number = JSON.parse(JSON.stringify(fileDescriptor))['offset']let avFileDescriptor: media.AVFileDescriptor = { fd: fileFd, offset: fileOffset, length: -1 };this.avPlayer!.fdSrc = avFileDescriptor;} catch (err) {console.info('Set Url failed : ' + JSON.stringify(err))}}}, 500)}
三、设置AVPlayer回调,监听播放事件
/*** 设置avplayer回调,监听播放事件*/private setAVPlayerCallback() {if (!this.avPlayer) {return}// seek操作结果回调this.avPlayer!.on('seekDone', (seekDoneTime) => {console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);})// 音量变化回调this.avPlayer!.on('volumeChange', (volume) => {console.info(`volumeChange called, and new volume is :${volume}`);})// 音频总时长this.avPlayer!.on('durationUpdate', (duration) => {console.info(`durationUpdate :${duration}`);this.duration = duration;})// 当前播放进度this.avPlayer!.on('timeUpdate', (time) => {let now = Math.floor(time/1000)if (this.process != now) {console.info(`timeUpdate :${now}`);}this.process = now})// error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程this.avPlayer!.on('error', (err) => {console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);this.avPlayer!.reset(); // 调用reset重置资源,触发idle状态})// 状态机变化回调函数this.avPlayer!.on('stateChange', async (state, reason) => {switch (state) {case 'idle': // 成功调用reset接口后触发该状态机上报console.info('AVPlayer state idle called.');this.avPlayer!.release(); // 调用release接口销毁实例对象break;case 'initialized': // avplayer 设置播放源后触发该状态上报console.info('AVPlayer state initialized called.');this.avPlayer!.prepare().then(() => {console.info('AVPlayer prepare succeeded.');}, () => {console.error(`Invoke prepare failed, code is`);});break;case 'prepared': // prepare调用成功后上报该状态机console.info('AVPlayer state prepared called.');this.avPlayer!.loop = this.loopif (this.autoPlay) {this.avPlayer!.play(); // 调用播放接口开始播放}break;case 'playing': // play成功调用后触发该状态机上报console.info('AVPlayer state playing called.');break;case 'paused': // pause成功调用后触发该状态机上报console.info('AVPlayer state paused called.');break;case 'completed': // 播放结束后触发该状态机上报console.info('AVPlayer state completed called.');if (this.loop == true) {this.avPlayer!.seek(0)this.avPlayer!.play()}break;case 'stopped': // stop接口成功调用后触发该状态机上报console.info('AVPlayer state stopped called.');break;case 'released':console.info('AVPlayer state released called.');break;default:console.info('AVPlayer state unknown called.');break;}})}
四、其他操作
- 播放
/*** 播放*/play() {if (!this.avPlayer) {this.autoPlay = truereturn}this.avPlayer!.play().then(() => {console.info('Play success')}).catch((err: BusinessError) => {console.info('Play failed : ' + JSON.stringify(err))})}
- 暂停
/*** 暂停*/pause() {if (!this.avPlayer) {this.autoPlay = falsereturn}this.avPlayer!.pause().then(() => {console.info('Pause success')}).catch((err: BusinessError) => {console.info('Pause failed : ' + JSON.stringify(err))})}
- 释放资源
/*** 释放资源*/release() {if (!this.avPlayer) {this.autoPlay = falsereturn}this.avPlayer!.release().then(() => {console.info('release success')}).catch((err: BusinessError) => {console.info('release failed : ' + JSON.stringify(err))})}
感谢
【Harmony Next】使用 AVPlayer 播放音频
吐槽
官方有时间,还是自己跑一遍文档中的代码,以及链接提供的Demo吧!请不要浪费我们开发者的时间,谢谢。
官方文档——使用AVPlayer播放音频(ArkTS)
