开发中使用——鸿蒙播放本地mp3文件

文章目录


背景

项目中有个功能需要播放本地的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.loop
          if (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 = true
        return
      }
    
      this.avPlayer!.play().then(() => {
        console.info('Play success')
      }).catch((err: BusinessError) => {
        console.info('Play failed : ' + JSON.stringify(err))
      })
    }
  • 暂停

    复制代码
    /**
     * 暂停
     */
    pause() {
      if (!this.avPlayer) {
        this.autoPlay = false
        return
      }
      this.avPlayer!.pause().then(() => {
        console.info('Pause success')
      }).catch((err: BusinessError) => {
        console.info('Pause failed : ' + JSON.stringify(err))
      })
    }
  • 释放资源

    复制代码
    /**
     * 释放资源
     */
    release() {
      if (!this.avPlayer) {
        this.autoPlay = false
        return
      }
      this.avPlayer!.release().then(() => {
        console.info('release success')
      }).catch((err: BusinessError) => {
        console.info('release failed : ' + JSON.stringify(err))
      })
    }

感谢

【Harmony Next】使用 AVPlayer 播放音频

吐槽

官方有时间,还是自己跑一遍文档中的代码,以及链接提供的Demo吧!请不要浪费我们开发者的时间,谢谢。
官方文档------使用AVPlayer播放音频(ArkTS)

相关推荐
anyup16 小时前
🔥2026最推荐的跨平台方案:H5/小程序/App/鸿蒙,一套代码搞定
前端·uni-app·harmonyos
Ranger092920 小时前
鸿蒙开发新范式:Gpui
rust·harmonyos
Huang兄21 小时前
鸿蒙-深色模式适配
harmonyos·arkts·arkui
SummerKaze3 天前
为鸿蒙开发者写一个 nvm:hmvm 的设计与实现
harmonyos
在人间耕耘4 天前
HarmonyOS Vision Kit 视觉AI实战:把官方 Demo 改造成一套能长期复用的组件库
人工智能·深度学习·harmonyos
王码码20355 天前
Flutter for OpenHarmony:socket_io_client 实时通信的事实标准(Node.js 后端的最佳拍档) 深度解析与鸿蒙适配指南
android·flutter·ui·华为·node.js·harmonyos
HarmonyOS_SDK5 天前
【FAQ】HarmonyOS SDK 闭源开放能力 — Ads Kit
harmonyos
Swift社区5 天前
如何利用 ArkUI 框架优化鸿蒙应用的渲染性能
华为·harmonyos
特立独行的猫a5 天前
uni-app x跨平台开发实战:开发鸿蒙HarmonyOS影视票房榜组件完整实现过程
华为·uni-app·harmonyos·轮播图·uniapp-x
盐焗西兰花5 天前
鸿蒙学习实战之路-STG系列(5/11)-守护策略管理-添加与修改策略
服务器·学习·harmonyos