鸿蒙实战开发:视频播放器实现(上)

鸿蒙实战开发:视频播放器实现(上) 

鸿蒙实战开发:视频播放器实现(中)

鸿蒙实战开发:视频播放器实现(下) 

ArkTS 提供了 @ohos.multimedia.media 模块来处理音视频相关媒体业务,它提供了音视频播放和录制的功能,通过 AVPlayer 类,可以实现音视频的播放。下面我们使用AVPlayer实现一个简单的视频播放器。

AVPlayer的工作流程

在正式进入播放器开发前,我们先来认识一下AVPlayer的工作流程,下图是根据官方的状态变化示意图重新绘制的流程图:

  1. 我们要实现一个播放器,首先需要使用createAVPlayer()创建一个播放器实例,此时播放器会进入idle状态,也就是闲置状态。如果我们调用了reset()来重置播放器,此时播放器也会进入闲置状态
  2. 在闲置状态,给播放器设置播放源,即设置播放器的 url 或 的 fdSrc,播放器就会进入initialized状态,也就是初始化状态。在初始化状态,需要给播放器配置播放窗口,才能显示视频画面。
  3. 在初始化状态调用prepare()方法,播放器会进入prepared状态,也就是准备状态,此时播放器的资源已准备就绪。如果在播放器的停止状态调用了prepare()方法,播放器会重新进入prepared状态。
  4. 在准备状态调用play()方法,播放器就会进入playing状态,即正在播放状态。如果在播放器的停止、播放完成状态调用play()方法,播放器会重新进入播放状态。
  5. 在播放状态中调用了pause()方法,播放器就会进入paused状态,即暂停状态。如果此时调用了play()方法,播放器会进入playing状态,继续播放媒体资源。
  6. 当媒体资源播放至结尾时,如果用户没有设置循环播放(loop = 1),播放器就会进入completed状态,即完成状态。如果这个时候调用play()会进入playing状态重播媒体资源。
  7. 在prepared、playing、paused、completed状态是调用stop()方法,播放器就会进入stopped状态,即停止状态,此时的播放器会释放内存资源。在这个时候,可以调用prepare()方法让播放器进入准备状态,重新播放媒体资源。也可以调用reset()方法重置播放器,让其回到闲置状态,或者调用release()方法彻底销毁播放器。

了解完播放器的工作流程后,我们就正式开始播放器的开发。

视频播放器实现

实现播放器的核心,就是监听播放器状态,在对应的状态中执行下一步的动作。

1、创建播放器

首先我们建一个播放器工具类,在工具类中使用media.createAVPlayer() 方法创建一个AVPlayer播放器实例。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null
  
  // 创建播放器的方法
  static async  init() {

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()
    
  }
}

2、监听状态

因为播放器的实现核心,就是监听播放器状态,然后在对应的状态中执行下一步动作。同时,我们也需要根据播放器的状态来设置页面的展示,因此需要监听播放器的状态。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null
  
  // 创建播放器的方法
  static async  init() {

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
      console.info('AVPlayer state durationUpdate called. current time: ', duration);
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }
}

在当前的实现中,我们主要监听了播放器的durationUpdate、timeUpdate、seekDone、stateChange事件。

3、设置播放源

我们提供一个changePlay方法,在这个方法中完成播放源的设置,在设置播放源前,应该先将播放器的状态重置为闲置状态。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null
  
  // 创建播放器的方法
  static async  init() {

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
      console.info('AVPlayer state durationUpdate called. current time: ', duration);
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  
  static async changePlay() {
    // 将播放状态置为闲置
    await VideoAVPlayerClass.avPlayer.reset()

    VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].url
  }
}

4、设置播放窗口

用AVPlayer播放视频,需要设置播放窗口才能显示画面,从XComponent组件获取surfaceId后设置给播放器实例的surfaceId属性。

首先在播放器类中定义一个surfaceId变量来存储从XComponent组件获取的surfaceId,然后在init()方法中将surfaceId存储到播放器类上,在播放器的初始化状态设置播放器的播放窗口。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null

  // surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取
  static surfaceId: string = ''
  
  // 创建播放器的方法
  static async init(initParams: InitParams) {

    // 存储属性SurfaceID,用于设置播放窗口,显示画面
    VideoAVPlayerClass.surfaceId = initParams.surfaceId

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
      console.info('AVPlayer state durationUpdate called. current time: ', duration);
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          // 设置显示画面,当播放的资源为纯音频时无需设置
          VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceId
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  
  static async changePlay() {
    // 将播放状态置为闲置
    await VideoAVPlayerClass.avPlayer.reset()

    VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].url
  }
}

5、获取播放信息

在页面中,需要展示当前播放视频的视频时长、播放时长以及播放器状态,因此我们需要获取视频的播放信息。我们先获取视频时长、当前播放时长、视频是否播放这三个播放信息。

  • 获取视频时长

通过监听播放器的durationUpdate事件,可以获取视频资源的总时长。在播放器类中定义一个duration变量来存储视频时长,然后监听durationUpdate事件获取视频时长。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null

  // 当前播放器播放视频的总时长
  static duration: number = 0

  // surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取
  static surfaceId: string = ''
  
  // 创建播放器的方法
  static async init(initParams: InitParams) {

    // 存储属性SurfaceID,用于设置播放窗口,显示画面
    VideoAVPlayerClass.surfaceId = initParams.surfaceId

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
        console.info('AVPlayer state durationUpdate called. current time: ', duration);
        // 获取视频总时长
        VideoAVPlayerClass.duration = duration
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          // 设置显示画面,当播放的资源为纯音频时无需设置
          VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceId
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  
  static async changePlay() {
    // 将播放状态置为闲置
    await VideoAVPlayerClass.avPlayer.reset()

    VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].url
  }
}

  • 获取当前播放时长

通过监听播放器的timeUpdate事件,可以获取当前的播放时长。在播放器类中定义一个

timeUpdate变量来存储当前播放时长,然后监听timeUpdate事件获取视频当前播放时长。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null

  // 当前播放器播放视频的总时长
  static duration: number = 0

  // 当前播放器播放的时长
  static time: number = 0

  // surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取
  static surfaceId: string = ''
  
  // 创建播放器的方法
  static async init(initParams: InitParams) {

    // 存储属性SurfaceID,用于设置播放窗口,显示画面
    VideoAVPlayerClass.surfaceId = initParams.surfaceId

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
        console.info('AVPlayer state durationUpdate called. current time: ', duration);
        // 获取视频总时长
        VideoAVPlayerClass.duration = duration
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
      // 获取当前播放时长
      VideoAVPlayerClass.time = time
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          // 设置显示画面,当播放的资源为纯音频时无需设置
          VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceId
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  
  static async changePlay() {
    // 将播放状态置为闲置
    await VideoAVPlayerClass.avPlayer.reset()

    VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].url
  }
}

获取是否播放状态

页面需要根据是否播放状态来展示播放/暂停按钮,因此我们需要记录是否播放状态。在播放器类中定义isPlay变量来记录是否播放状态,默认是暂停状态。

import media from '@ohos.multimedia.media'

export class VideoAVPlayerClass {
  // 创建的播放器应该存在我们的工具类上,这样才能被导出使用
  static player: media.AVPlayer | null = null

  // 当前播放器播放视频的总时长
  static duration: number = 0

  // 当前播放器播放的时长
  static time: number = 0

  // 当前播放器是否播放
  static isPlay: boolean = false

  // surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取
  static surfaceId: string = ''
  
  // 创建播放器的方法
  static async init(initParams: InitParams) {

    // 存储属性SurfaceID,用于设置播放窗口,显示画面
    VideoAVPlayerClass.surfaceId = initParams.surfaceId

    // 创建播放器实例
    VideoAVPlayerClass.player = await media.createAVPlayer()

    // ----------------------- 事件监听 --------------------------------------------------------------

    // 用于进度条,监听进度条长度,刷新资源时长
    VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {
        console.info('AVPlayer state durationUpdate called. current time: ', duration);
        // 获取视频总时长
        VideoAVPlayerClass.duration = duration
    })

    // 用于进度条,监听进度条当前位置,刷新当前时间
    VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{
      console.info('AVPlayer state timeUpdate called. current time: ', time);
      // 获取当前播放时长
      VideoAVPlayerClass.time = time
    })

    // 监听seek生效的事件
    VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
      VideoAVPlayerClass.avPlayer.play()
      VideoAVPlayerClass.isPlay = true
    })

    // 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    VideoAVPlayerClass.avPlayer.on('error', (err) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      // 调用reset重置资源,触发idle状态
      VideoAVPlayerClass.avPlayer.reset()
    })

    // 监听播放状态机AVPlayerState切换的事件
    VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {
      switch (state) {
      // 成功调用reset接口后触发该状态机上报
        case 'idle':
          console.info('AVPlayer state idle called.');
          break

       // avplayer 设置播放源后触发该状态上报
        case 'initialized':
          console.info('AVPlayerstate initialized called.');
          // 设置显示画面,当播放的资源为纯音频时无需设置
          VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceId
          break

      // prepare调用成功后上报该状态机
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          break

      // play成功调用后触发该状态机上报
        case 'playing':
          console.info('AVPlayer state playing called.');
          break

      // pause成功调用后触发该状态机上报
        case 'paused':
          console.info('AVPlayer state paused called.');
          break

      // 播放结束后触发该状态机上报
        case 'completed':
          console.info('AVPlayer state completed called.');
          break

      // stop接口成功调用后触发该状态机上报
        case 'stopped':
          console.info('AVPlayer state stopped called.');
        // 调用reset接口初始化avplayer状态
          VideoAVPlayerClass.avPlayer.reset()
          break

        case 'released':
          console.info('AVPlayer state released called.');
          break;

        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }

  
  static async changePlay() {
    // 将播放状态置为闲置
    await VideoAVPlayerClass.avPlayer.reset()

    VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].url
  }
}

至此,我们实现了播放器的一些基本设置,还不能实现视频的播放,视频的播放功能实现将在下一篇分享


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

为了能够帮助大家快速掌握鸿蒙(HarmonyOS NEXT)应用开发技术知识。在此给大家分享一下我结合鸿蒙最新资料整理出来的鸿蒙南北向开发学习路线以及整理的最新版鸿蒙学习文档资料。

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料

 获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

 有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

鸿蒙HarmonyOS华为开发的一款分布式操作系统,旨在为各种智能设备提供统一的操作系统平台。在鸿蒙HarmonyOS实现微信app效果,可以通过以下步骤进行: ### 1. 环境搭建 首先,需要搭建鸿蒙HarmonyOS开发环境。可以通过华为开发者官网下载DevEco Studio,这是鸿蒙系统的集成开发环境(IDE)。 ### 2. 创建新项目 打开DevEco Studio,创建一个新的鸿蒙HarmonyOS项目。选择合适的模板,例如“Empty Ability”,然后填写项目名称和包名等信息。 ### 3. 设计界面 使用鸿蒙HarmonyOS提供的UI框架,设计微信app的界面。可以通过XML布局文件或者代码方式实现。微信的主要界面包括聊天列表、聊天窗口、联系人列表等。 ### 4. 实现功能 #### 4.1 聊天功能 实现聊天功能需要处理消息的发送和接收。可以使用鸿蒙HarmonyOS提供的WebSocket或者Socket接口进行实时通信。 ```java // 示例代码:发送消息 public void sendMessage(String message) { // 使用WebSocket发送消息 webSocket.send(message); } // 示例代码:接收消息 webSocket.onMessage((message) -> { // 处理接收到的消息 receiveMessage(message); }); ``` #### 4.2 联系人列表 实现联系人列表需要从服务器获取联系人数据,并显示在界面上。可以使用ListContainer组件来实现。 ```xml <!-- 示例代码:联系人列表布局 --> <ListContainer id="contactList" orientation="vertical"> </ListContainer> ``` ```java // 示例代码:加载联系人数据 public void loadContacts() { List<Contact> contacts = getContactsFromServer(); contactList.setItemProvider(new ContactItemProvider(contacts)); } ``` #### 4.3 聊天记录 实现聊天记录需要将消息保存到本地数据库中。可以使用鸿蒙HarmonyOS提供的数据库接口进行数据存储。 ```java // 示例代码:保存消息到数据库 public void saveMessage(String message) { // 使用数据库接口保存消息 database.insert("messages", message); } ``` ### 5. 测试与调试 在模拟器或者真机上测试app的各项功能,确保没有明显的bug和问题。 ### 6. 发布 完成开发和测试后,可以将app发布到华为的应用市场。 ### 总结 通过以上步骤,可以在鸿蒙HarmonyOS实现一个类似微信的app效果。当然,实际开发中还需要考虑更多的细节和优化,例如性能优化、安全性、用户体验等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值