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

相关推荐
2601_949593653 分钟前
基础入门 React Native 鸿蒙跨平台开发:Animated 动画按钮组件 鸿蒙实战
react native·react.js·harmonyos
菜鸟小芯11 分钟前
【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&推荐功能实现
flutter·harmonyos
星辰徐哥12 分钟前
鸿蒙APP开发从入门到精通:页面路由与组件跳转
华为·harmonyos
爱吃大芒果21 分钟前
Flutter for OpenHarmony 实战: mango_shop 资源文件管理与鸿蒙适配
javascript·flutter·harmonyos
大雷神2 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地--第20篇:天气服务与气象数据
harmonyos
爱吃大芒果2 小时前
Flutter for OpenHarmony 适配:mango_shop 页面布局的鸿蒙多设备屏幕适配方案
flutter·华为·harmonyos
前端不太难2 小时前
没有文档模型,HarmonyOS PC 应用会发生什么?
华为·状态模式·harmonyos
2601_949593652 小时前
高级进阶 React Native 鸿蒙跨平台开发:LinearGradient 玻璃拟态卡片
react native·react.js·harmonyos
摘星编程2 小时前
在OpenHarmony上用React Native:TopTab顶部标签页
react native·react.js·harmonyos
大雷神2 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地--第25篇:学习中心 - 课程详情与学习
学习·华为·harmonyos