王学岗鸿蒙开发(北向)——————(十三)音乐播放器

在这里插入图片描述
AudioRenderer适合录音

AVPlayer:简单的本地单曲播放

MP3文件放置的地方
在这里插入图片描述

import media from '@ohos.multimedia.media'
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
  //第1步:
  avPlayer:media.AVPlayer = null
  async onPageShow(){
  //第2步:异步创建播放器对象
  this.avPlayer = await media.createAVPlayer()
    //第3步:设置回调函数,监听对象的状态变化,
    this.setAVPlayerCallback();
  }
  build() {
    Row() {
      Column() {
        Button('播放本地歌曲').onClick(()=>{
          this.playLocalMusic()
        })

      }
      .height('100%')
    }
  }
  async  playLocalMusic(){
     //第4步:获取上下文
     const context = getContext(this) as common.UIAbilityContext
     //第5步:获取文件描述符
     const rawFieldFd = await context.resourceManager.getRawFd("kn.mp3")
     //第6步:fdSrc是本地文件描述符,
     if(this.avPlayer) {
       this.avPlayer.fdSrc = rawFieldFd
     }
   }
  setAVPlayerCallback() {
    // seek操作结果回调函数
    this.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
    })
    // 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: string, reason: media.StateChangeReason) => {
      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();
          break;
        case 'prepared': // prepare调用成功后上报该状态机
          console.info('AVPlayer state prepared called.');
          this.avPlayer.play(); // 调用播放接口开始播放
          break;
        case 'playing': // play成功调用后触发该状态机上报
          console.info('AVPlayer state playing called.');
          break;
        case 'paused': // pause成功调用后触发该状态机上报
          console.info('AVPlayer state paused called.');
          this.avPlayer.play(); // 再次播放接口开始播放
          break;
        case 'completed': // 播放结束后触发该状态机上报
          console.info('AVPlayer state completed called.');
          this.avPlayer.stop(); //调用播放结束接口
          break;
        case 'stopped': // stop接口成功调用后触发该状态机上报
          console.info('AVPlayer state stopped called.');
          this.avPlayer.reset(); // 调用reset接口初始化avplayer状态
          break;
        case 'released':
          console.info('AVPlayer state released called.');
          break;
        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }
}

AVPlayer:播放网络歌曲

播放网络歌曲,需要增加网络访问权限
在这里插入图片描述

import media from '@ohos.multimedia.media'
import common from '@ohos.app.ability.common';
@Entry
@Component
struct Index {
  //第1步:
  avPlayer:media.AVPlayer = null
  async onPageShow(){
  //第2步:异步创建播放器对象
  this.avPlayer = await media.createAVPlayer()
    //第3步:设置回调函数,监听对象的状态变化,
    this.setAVPlayerCallback();
  }
  build() {
    Row() {
      Column() {
        Button('播放网络歌曲').onClick(()=>{
          this.playNetMusic()
        })

      }
      .height('100%')
    }
  }
  /**
   * 播放网络歌曲
   */
  playNetMusic(){
    const url =  'https://www.yyq.cn/audio/audiomp3/0/16/8f6/0168f69e0e3a0c5c2638c366d53908a5.mp3'
    this.avPlayer.url = url
  }
  setAVPlayerCallback() {
    // seek操作结果回调函数
    this.avPlayer.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
    })
    // 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: string, reason: media.StateChangeReason) => {
      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();
          break;
        case 'prepared': // prepare调用成功后上报该状态机
          console.info('AVPlayer state prepared called.');
          this.avPlayer.play(); // 调用播放接口开始播放
          break;
        case 'playing': // play成功调用后触发该状态机上报
          console.info('AVPlayer state playing called.');
          break;
        case 'paused': // pause成功调用后触发该状态机上报
          console.info('AVPlayer state paused called.');
          this.avPlayer.play(); // 再次播放接口开始播放
          break;
        case 'completed': // 播放结束后触发该状态机上报
          console.info('AVPlayer state completed called.');
          this.avPlayer.stop(); //调用播放结束接口
          break;
        case 'stopped': // stop接口成功调用后触发该状态机上报
          console.info('AVPlayer state stopped called.');
          this.avPlayer.reset(); // 调用reset接口初始化avplayer状态
          break;
        case 'released':
          console.info('AVPlayer state released called.');
          break;
        default:
          console.info('AVPlayer state unknown called.');
          break;
      }
    })
  }
}

鸿蒙网络访问 Axios的使用

在这里插入图片描述
首先安装ohpm,如何查找phpm库安装路径

在这里插入图片描述
ohpm安装指南
Axios是第三方库,需要安装。

 /**
   * 获取网络歌曲数据,封装到对应的bean对象中
   */
  async getMusicData(){

    //发送网络请求,获取数据
     const resp = await axios({
        method: 'get',
        url: 'https://www.yyq.cn/api/getPlayData?playid=4926%2C4925%2C4924%2C4923%2C4922%2C4921%2C4920%2C4919%2C4918%2C4917%2C4916%2C4915&typeid=3'
      })

    if(resp.status === 200){

      this.songs = resp.data
      this.songs.forEach((song) =>{
        song.img = song.img
        song.src = 'https://www.yyq.cn/' + song.src
        console.log('getData',song.img, song.src);
      })

    }
  }

鸿蒙第三方库
鸿蒙第三方库

import media from '@ohos.multimedia.media'
import emitter from '@ohos.events.emitter'
import { songItemType } from '../models/music'
import { PlayStateType } from '../models/playState'
import { EmitEventType } from '../constants/EventConstants'

/**
 * 播放工具类,我们需要把这个工具类同步到界面,这就需要线程通信。
 * 鸿蒙中的线程通信,叫Emitter(发布订阅)和worker(并行计算)。
 * 我们这里用Emitter,发布者是播放器,订阅者是使用信息的页面(可以有多个订阅者)
 */
export class AvPlayerUtils{

  static player: media.AVPlayer | null = null

  //记录播放的音乐的总时长,可以从播放器中获取,
  static duration: number = 0

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

  //当前歌曲的播放状态,
  static isPlay: boolean = false

  //播放模式:自动播放,单曲循环,随机播放,默认是自动播放
  static playMode: 'auto' | 'repeat' | 'random' = 'auto'

  //歌曲名称,作者,图片等等

  //定义播放歌曲列表
  static playList: songItemType[] = []

  //当前的播放索引
  static playIndex: number = -1

//在EntryAbility的onWindowStageCreate(){}中初始化,就不需要再所有的页面中初始化了
  // 注意:EntryAbility的后缀名要改成.ets
  // 初始化播放对象,可以在页面显示的时候初始化
  static async  init(){

    //创建播放对象
    this.player = await media.createAVPlayer()

    this.player.on('stateChange', (state)=>{

      switch(state){
        case 'initialized':
          this.player.prepare()
          break;

        case 'prepared':
          this.player.play()
          //更新播放状态
          this.isPlay = true
          break
      }
    })
     //监听音乐的总时长
    this.player.on('durationUpdate',(duration)=>{
      this.duration = duration
      console.log('logData', this.duration)
    })
    //监听播放时长
    this.player.on('timeUpdate',(time)=>{
      this.time = time
      console.log('logData', this.time, '发送数据')

      //定义一个数据,发送通知出去

      // 收集要通知的信息
      const playState:PlayStateType = {
        img:this.playList[this.playIndex].img,
        name:this.playList[this.playIndex].name,
        author:this.playList[this.playIndex].author,
        url: this.playList[this.playIndex].url,
        playIndex: this.playIndex,
        time: this.time,
        duration:this.duration,
        isPlay:this.isPlay,
        playMode:this.playMode,
        playList:this.playList
      }

      //发布通知
      this.updateState(playState)
    })

  }

  //单曲指定播放,
  //播放器播放状态无法更替URL,需要把播放器置为idle(可以调用reset())状态
  static playSingle(song: songItemType){

    // 判断是不是列表中的歌曲
    const isList = this.playList.some((item:songItemType)=>item.id === song.id)
    // 如果是歌曲列表中的歌曲
    if(isList){
      // 是不是正在播放的
      if(this.player.url === song.url){
        // 重新播放(切换当前播放索引的歌曲)
        this.changePlay()
      }else{
        // 切换歌曲(更新播放索引切换歌曲)
        this.playIndex = this.playList.findIndex((item:songItemType)=>item.id===song.id)
        this.changePlay()
      }
    }else{
      // 添加到播放列表中,再进行播放
      //为了防止playList是空,每播一首歌就加入清单
      this.playList.unshift(song)
      this.playIndex = 0
      this.changePlay()
    }

  }

  /**
   * 切换播放
   */
  static async  changePlay(){

    //重置播放器状态,才能重新设置url
    await this.player.reset()
    //需要重置播放器数据
    this.duration = 0
    this.time = 0
    //为了防止playList是空,每播一首歌就加入清单
    this.player.url = this.playList[this.playIndex].url

  }

  //发布通知,订阅者就可以得到数据
  // 更新歌曲信息至页面
  static updateState(playState: PlayStateType) {
    emitter.emit({
      eventId: EmitEventType.UPDATE_STATE
    }, {
      data: {
        playStateStr: JSON.stringify(playState)
      }
    })
  }

}

播放器的seek要与seeDone连用

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值