HarmonyOS鸿蒙Next中AVPlayer的状态机具体该怎么处理

HarmonyOS鸿蒙Next中AVPlayer的状态机具体该怎么处理 AVPlayer的状态机具体该怎么处理?有没有一个简单的demo能参考一下?

3 回复
//avplayerManager.ets:
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = '[AvPlayer]  '

@ObservedV2
export class AudioPlayManager {
  private avPlayer: media.AVPlayer | null = null
  @Trace audioDuration: number = 0
  @Trace currAudioTime: number = 0
  @Trace isPlaying: boolean = false
  @Trace audioPlayState: media.AVPlayerState = 'idle';

  // 注册avplayer回调函数。
  setAVPlayerCallback(avPlayer: media.AVPlayer) {
    // seek操作结果回调函数。
    avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`${TAG} on seekDone, seek time is ${seekDoneTime}`);
    });
    // error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程。
    avPlayer.on('error', (err: BusinessError) => {
      console.error(`${TAG} on error, code is ${err.code}, message is ${err.message}`);
      avPlayer.reset(); // 调用reset重置资源,触发idle状态。
    });
    avPlayer.on('timeUpdate', (time: number) => {
      console.info(`${TAG} on timeUpdate :  ${time}`);
      this.currAudioTime = time
    });
    avPlayer.on('durationUpdate', (time: number) => {
      console.info(TAG + `on durationUpdate: ${time}`)
      this.audioDuration = time;
    })
    // 状态机变化回调函数。
    avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
      switch (state) {
        case 'idle': // 成功调用reset接口后触发该状态机上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          // avPlayer.release(); // 调用release接口销毁实例对象。
          break;
        case 'initialized': // avplayer 设置播放源后触发该状态上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          // avPlayer.audioRendererInfo = {
          //   usage: audio.StreamUsage.STREAM_USAGE_MUSIC, // 音频流使用类型:音乐。根据业务场景配置,参考StreamUsage。
          //   rendererFlags: 0 // 音频渲染器标志。
          // };
          avPlayer.prepare();
          break;
        case 'prepared': // prepare调用成功后上报该状态机。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          // this.audioDuration = avPlayer.duration
          break;
        case 'playing': // play成功调用后触发该状态机上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          break;
        case 'paused': // pause成功调用后触发该状态机上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          avPlayer.pause()
          break;
        case 'completed': // 播放结束后触发该状态机上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          this.resetCurrAudioPlayStatusInfo();
          break;
        case 'stopped': // stop接口成功调用后触发该状态机上报。
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          break;
        case 'released':
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          this.setAudioPlayState(avPlayer.state)
          break;
        default:
          console.info(`${TAG} 状态机 audioPlayState: ${avPlayer.state}`);
          break;
      }
    });
  }

  //设置当前音频播放状态
  setAudioPlayState(state: media.AVPlayerState) {
    this.audioPlayState = state;
    console.info(TAG + `setAudioPlayState audioPlayState: ${this.audioPlayState}`)
  }

  //音频播放
  async setAudioSrcToPrepared(audioSrc: string) {
    // 创建avPlayer实例对象。
    this.avPlayer = await media.createAVPlayer();
    //设置状态机
    this.setAVPlayerCallback(this.avPlayer!);
    //设置 音频url,状态自动跳至 initialized
    this.avPlayer!.url = audioSrc;
  }
  
  async startPlay() {
    this.isPlaying = true
    try {
      this.avPlayer?.play()
    }catch (err){
      let error:BusinessError = err as BusinessError
    }
  }

  async stopPlay() {
    this.avPlayer?.prepare()
    this.isPlaying = false
  }

  async release() {
    this.avPlayer?.release()
    this.isPlaying = false
  }

  async reset() {
    this.isPlaying = false
    this.currAudioTime = 0
    this.avPlayer?.prepare();
    // this.avPlayer?.release()
    this.avPlayer = null;
  }

  //重置当前音频播放状态信息
  resetCurrAudioPlayStatusInfo() {
    this.isPlaying = false
    this.currAudioTime = 0
    this.setAudioPlayState('stopped');
  }

  async seek(value: number) {
    this.avPlayer?.seek(value)
  }
}

//Index
import { AudioPlayManager } from './avplayerManager';

@Entry
@Component
struct Index {
  avplayerManager:AudioPlayManager = new AudioPlayManager()

  build() {
    Column({space:20}){
      Button('AVPlayer实例化')
        .onClick(()=>{
          this.avplayerManager.setAudioSrcToPrepared('')
          // 在该函数中传入音频文件url
        })
      Button('开始播放(确保实例化完成之后再点击播放)')
        .onClick(()=>{
          this.avplayerManager.startPlay()
        })
      Button('暂停播放')
        .onClick(()=>{
          this.avplayerManager.stopPlay()
        })
      Button('重置播放')
        .onClick(()=>{
          this.avplayerManager.reset()
        })
      Button('销毁资源')
        .onClick(()=>{
          this.avplayerManager.release()
        })
    }
    .width('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

更多关于HarmonyOS鸿蒙Next中AVPlayer的状态机具体该怎么处理的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


AVPlayer状态机处理基于状态监听和回调机制。通过on('stateChange')监听状态变化,事件包括idleinitializedpreparedplayingpausedcompletedstoppederror等。开发者需在回调中根据state参数执行相应操作,如播放器准备完成后自动播放。错误状态需通过on('error')单独处理。状态转换由系统管理,应用只需响应状态变更。

在HarmonyOS Next中,AVPlayer的状态机是其核心控制逻辑,主要通过监听状态回调进行有序处理。其生命周期主要包含以下关键状态:Idle、Initialized、Prepared、Playing、Paused、Completed、Stopped 以及 Error

核心处理流程如下:

  1. 状态监听:通过 on('stateChange') 方法注册监听器,在回调中根据 state 参数进行分支处理。
  2. 关键状态与操作
    • Idle -> Initialized:调用 avPlayer.prepare() 后进入。
    • Initialized -> Prepared:准备就绪,可获取媒体信息(如时长)。此时可调用 avPlayer.play() 开始播放。
    • Prepared -> Playing / Paused:进行播放控制。
    • Completed / Stopped / Error:需进行资源释放或错误处理。

一个简单的状态处理代码结构示例:

import media from '@ohos.multimedia.media';

// 1. 创建AVPlayer实例
let avPlayer: media.AVPlayer;
avPlayer = await media.createAVPlayer();

// 2. 设置状态监听
avPlayer.on('stateChange', async (state: string) => {
  switch (state) {
    case 'initialized':
      // 资源已设置,可进行prepare
      await avPlayer.prepare();
      break;
    case 'prepared':
      // 准备就绪,可开始播放
      await avPlayer.play();
      break;
    case 'playing':
      // 播放中,可更新UI控件(如进度条)
      break;
    case 'paused':
      // 已暂停
      break;
    case 'completed':
      // 播放完成,可重置或释放
      await avPlayer.reset();
      break;
    case 'stopped':
      // 已停止
      break;
    case 'error':
      // 发生错误,需查询错误码进行处理
      let errorMsg = avPlayer.getErrorMessage();
      // 处理错误逻辑...
      break;
    default:
      break;
  }
});

// 3. 设置资源并触发初始化(例如设置网络URL)
avPlayer.url = 'https://example.com/sample.mp4';
// 设置url后,状态会从idle变为initialized,触发上述监听回调

重要提醒

  • 确保在合适的生命周期(如页面退出时)调用 avPlayer.release() 释放资源。
  • 进行 play()pause()seek() 等操作前,建议检查当前状态是否允许该操作。
  • 错误状态必须处理,可调用 getErrorMessage() 获取详细信息。

以上代码框架清晰地展示了状态机的流转与处理要点,你可以基于此结构扩展具体的UI控制与业务逻辑。

回到顶部