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

相关推荐
不是三毛没有半7 小时前
华为USG6000v2 NAT模式下IPSEC IKE V1 实验
网络·网络安全·华为
前端世界8 小时前
HarmonyOS 数据处理性能优化:算法 + 异步 + 分布式实战
算法·性能优化·harmonyos
HarmonyOS小助手9 小时前
【案例+1】HarmonyOS官方模板优秀案例 第7期:金融理财 · 记账应用
harmonyos·鸿蒙·鸿蒙生态
爱笑的眼睛1110 小时前
HarmonyOS 应用开发深入浅出:基于 Stage 模型与声明式 UI 的现代化状态管理实践
华为·harmonyos
爱笑的眼睛1111 小时前
HarmonyOS 应用开发深度解析:掌握 ArkTS 声明式 UI 与现代化状态管理
华为·harmonyos
爱笑的眼睛1111 小时前
HarmonyOS 应用开发深度解析:基于 ArkTS 的跨组件状态管理最佳实践
华为·harmonyos
前端世界11 小时前
鸿蒙系统下的智能设备故障检测实战:从监控到自愈的全流程实现
华为·harmonyos
2501_9197490311 小时前
flutter鸿蒙:使用flutter_local_notifications实现本地通知
flutter·华为·harmonyos
Georgewu21 小时前
【HarmonyOS 6】 The target can not be empty. check the build.profile,json5 file of
harmonyos