开发中使用——鸿蒙播放本地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)

相关推荐
wszy18097 小时前
新文章标签:让用户一眼发现最新内容
java·python·harmonyos
wszy18098 小时前
顶部标题栏的设计与实现:让用户知道自己在哪
java·python·react native·harmonyos
Van_Moonlight8 小时前
RN for OpenHarmony 实战 TodoList 项目:空状态占位图
javascript·开源·harmonyos
anyup9 小时前
2026第一站:分享我在高德大赛现场学到的技术、产品与心得
前端·架构·harmonyos
anyup10 小时前
从赛场到产品:分享我在高德大赛现场学到的技术、产品与心得
前端·harmonyos·产品
Van_Moonlight11 小时前
RN for OpenHarmony 实战 TodoList 项目:顶部导航栏
javascript·开源·harmonyos
Swift社区11 小时前
H5 与 ArkTS 通信的完整设计模型
uni-app·harmonyos
程序猿追12 小时前
【鸿蒙PC桌面端实战】从零构建 ArkTS 高性能图像展示器:DevEco Studio 调试与 HDC 命令行验证全流程
华为·harmonyos
前端世界14 小时前
设备找不到、Ability 启不动?一次讲清 DevEco Studio 调试鸿蒙分布式应用
华为·harmonyos
行者9615 小时前
OpenHarmony上Flutter粒子效果组件的深度适配与实践
flutter·交互·harmonyos·鸿蒙