鸿蒙音乐播放封装

import { media } from '@kit.MediaKit'
import { MusicInfo } from '../bean/MusicInfo'
import { AvSessionManager } from './AvSessionManager'
import { backgroundTaskManager } from '@kit.BackgroundTasksKit'
import { wantAgent } from '@kit.AbilityKit'
import { LogUtils } from './LogUtils'
import hilog from '@ohos.hilog'
import { MusicUtils } from './MusicUtils'
import { Event_Hub_Duration_Updata, Event_Hub_Video_Time_Updata } from './Constants'
import { emitter } from '@kit.BasicServicesKit'

export class AvPlayerManager{

  public static player:media.AVPlayer|null=null
  static currentMusic:MusicInfo=new MusicInfo()
  static musics:MusicInfo[]=MusicUtils.getMusics()
  static id:string='-1'
  static isPlaying:boolean=false

  static async init(){
    if (!AvPlayerManager.player) {
      AvPlayerManager.player=await media.createAVPlayer()
    }
    AvPlayerManager.player.on('stateChange',(state)=>{
      switch (state){
        case 'initialized':
          AvPlayerManager.player?.prepare()
          break
        case 'prepared':
          AvPlayerManager.player?.play()
          AvPlayerManager.isPlaying=true
          break
        case 'completed':
          AvPlayerManager.nextMusic()
          LogUtils.e('completed')
          break
      }
    })

    AvPlayerManager.player.on('durationUpdate',(duration)=>{
      AvPlayerManager.currentMusic.duration=duration
      AvSessionManager.sendAvMetaData(AvPlayerManager.currentMusic)
      emitter.emit(Event_Hub_Duration_Updata,{data:duration})
    })
    AvPlayerManager.player.on('timeUpdate',(time)=>{
      AvPlayerManager.currentMusic.time=time
      emitter.emit(Event_Hub_Video_Time_Updata,{data:time})
    })
    AvPlayerManager.player.on('error',(time)=>{

    })
  }

  static play(song:MusicInfo){

    AvPlayerManager.startBackgroundTask()
    AvPlayerManager.player!.url=song.url
  }

  /**
   * 样式调试
   * */
  static playRaw(){
    // AvPlayerManager.startBackgroundTask()
    // let mp3=getContext().createModuleContext('entry').resourceManager.getRawFdSync('like.MP3')
    let mp3=getContext().createModuleContext('basic').resourceManager.getRawFdSync('like.mp3')
    let avFileDescriptor: media.AVFileDescriptor =
      { fd: mp3.fd, offset: mp3.offset, length: mp3.length };
    AvPlayerManager.player!.fdSrc=avFileDescriptor
  }

  /**
   * 可用
   * */
  static async playRawWithName(name:string,id:string){
    // AvPlayerManager.startBackgroundTask()


    if (AvPlayerManager.id!='-1'){
      if (id===AvPlayerManager.id) {
        return
      }
      await AvPlayerManager.player?.reset()
    }

    let mp3=await getContext().createModuleContext('basic').resourceManager.getRawFd(name+'.mp3')

    AvPlayerManager.id=id
    AvPlayerManager.currentMusic.name=name
    let avFileDescriptor: media.AVFileDescriptor =
      { fd: mp3.fd, offset: mp3.offset, length: mp3.length };

    AvPlayerManager.player!.fdSrc=avFileDescriptor
  }

  static playUrl(song:string){
    // AvPlayerManager.startBackgroundTask()

    AvPlayerManager.player!.url=song
  }

  static pause(){
    AvPlayerManager.player?.pause()
  }
  static continue(){
    AvPlayerManager.player?.play()
  }

  static seekProgress(time:number){
    AvPlayerManager.player?.seek(time)
  }

  static async upMusic(){
    let position=AvPlayerManager.getCurrentPosition(AvPlayerManager.id)
    if (position>0) {
      position--
    }else {
      position=AvPlayerManager.musics.length-1
    }

    let music=AvPlayerManager.musics[position]
    await AvPlayerManager.playRawWithName(music.name,music.id)
  }

  /**
   * 自动下一个
   * */
  static async nextMusic(){
    let position=AvPlayerManager.getCurrentPosition(AvPlayerManager.id)

    if (position + 1 < AvPlayerManager.musics.length) {
      position=position+1
    }else {
      position=0
    }
    let music=AvPlayerManager.musics[position]
    await AvPlayerManager.playRawWithName(music.name,music.id)
  }

  static getCurrentMusic(){
    for (let i = 0; i < AvPlayerManager.musics.length; i++) {
      if (AvPlayerManager.musics[i].id===AvPlayerManager.id) {
        return AvPlayerManager.musics[i]
      }
    }
    return AvPlayerManager.musics[0]

  }

  static getMusicWithId(id:string){

    for (let i = 0; i < AvPlayerManager.musics.length; i++) {
      if (AvPlayerManager.musics[i].id===id) {
        return AvPlayerManager.musics[i]
      }
    }
    return null
  }

  static getCurrentPosition(id:string){

    for (let i = 0; i < AvPlayerManager.musics.length; i++) {
      if (AvPlayerManager.musics[i].id===id) {
        return i
      }
    }
    return 0
  }

//   开启后台长时间任务,,播放的时候调用
  static async startBackgroundTask(){

    // 如果已经存在,就表示开启了后台任务
    if (AvSessionManager.session.sessionId){
      return
    }

    // want的信息,作用:当点击播控中心的时候,会跳转到app中来
    let wantAgentInfo: wantAgent.WantAgentInfo = {
      wants: [
        {
          bundleName: 'com.zhangjian.myapplication',//包名
          abilityName: 'EntryAbility' }
      ],
      operationType: wantAgent.OperationType.START_ABILITIES,
      requestCode: 0,
      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
    }

    let want=await wantAgent.getWantAgent(wantAgentInfo)

    // 申请长时间任务
    await backgroundTaskManager.startBackgroundRunning(getContext(),
    backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
      want
    )
  }
}

音乐播放主界面:

import {
    AvPlayerManager,
    Event_Hub_Duration_Updata,
    Event_Hub_Video_Time_Updata,
    MusicInfo
} from '@zjian/basic'
import { Animator, AnimatorResult, router } from '@kit.ArkUI'
import { LogUtils } from '@zjian/basic/src/main/ets/utils/LogUtils'
import { emitter } from '@kit.BasicServicesKit'

@Component
export struct MusicDetailPage {
  @State item: MusicInfo = new MusicInfo()
  @State imgWidth: number = 2000
  @State isPlay: boolean = true
  @State angle: number = 0
  @State duration: string = '00:00'
  @State currentTime: string = '00:00'
  @State durationProgress: number = 0
  @State currentProgress: number = 0
  @State isNext: boolean = false
  animatorResult: AnimatorResult = Animator.create({
    duration: 1000 * 30,
    easing: "linear",
    delay: 0,
    fill: "none",
    direction: "normal",
    iterations: -1,
    begin: 0,
    end: 360
  })

  managerDuration(dur:number){
    this.durationProgress = dur
    if (dur > 0) {
      if (this.isNext) {
        this.animatorResult.finish()
        this.animatorResult.play()
        let music = AvPlayerManager.getCurrentMusic()
        this.item = music
        this.isNext = false
      }
      dur = dur / 1000

      let second = Math.floor(dur / 60).toString().padStart(2, '0')
      let min = Math.floor(dur % 60).toString().padStart(2, '0')
      this.duration = second + ':' + min
    }
  }

  aboutToAppear(): void {
    this.managerDuration(this.item.duration)

    this.animatorResult.play()
    this.animatorResult.onFrame = (val) => {
      this.angle = val
    }
    // 继续播放进入以后,就不会读到duration的信息
    emitter.on(Event_Hub_Duration_Updata, (duration)=>{
      let dur:number=Number(duration.data)
      this.managerDuration(dur)
    })
    emitter.on(Event_Hub_Video_Time_Updata, (data)=>{
      let time=Number(data.data)
      if (time === this.durationProgress) {
        this.isNext = true
      }

      this.currentProgress = time
      if (time > 0) {
        time = time / 1000
        let second = Math.floor(time / 60).toString().padStart(2, '0')
        let min = Math.floor(time % 60).toString().padStart(2, '0')
        this.currentTime = second + ':' + min
      }
    })
  }

  aboutToDisappear(): void {
    emitter.off(Event_Hub_Duration_Updata)
    emitter.off(Event_Hub_Video_Time_Updata)
  }

  build() {

    Column() {

      Row() {
        Row() {
          Image($rawfile('ic_back.png'))
            .height(25).aspectRatio(1)
        }.height(35).aspectRatio(1)
        .justifyContent(FlexAlign.Start)
        .onClick(() => {
          router.back()
        })

        Text().layoutWeight(1)
        Row({ space: 10 }) {
          Text('推荐').fontColor($r('app.color.grey')).fontSize(18)
          Image('').backgroundColor(Color.Grey).height(8).width(2).borderRadius(2)
          Text('歌曲').fontColor(Color.White).fontSize(18)
          Image('').backgroundColor(Color.Grey).height(8).width(2).borderRadius(2)
          Text('歌词').fontColor($r('app.color.grey')).fontSize(18)
        }

        Text().layoutWeight(1)
        Image($rawfile('ic_share_white.png')).height(30).aspectRatio(1)
      }
      .margin({
        top: 10
      })
      .width('100%')

      Row() {
        Image(this.item.image)
          .width('100%')
          .aspectRatio(1)
          .borderRadius((this.imgWidth))
          .backgroundImageSize(ImageSize.Cover)
          .shadow({
            radius: 30,
            color: Color.Black
          })
          .rotate({
            angle: this.angle
          })

      }
      .width('100%')
      .aspectRatio(1)
      .alignItems(VerticalAlign.Center)
      .justifyContent(FlexAlign.Center)
      // .padding(10)
      .margin({
        top: 20
      })

      Text(this.item.name)
        .fontColor(Color.White)
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .margin({
          top: 20
        })

      Row() {
        Text('林俊杰  专辑:' + this.item.artisc)
          .fontColor($r('app.color.grey'))
          .fontSize(17)

        Text('VIP')
          .fontSize(11)
          .fontColor($r('app.color.grey'))
          .border({
            width: 1,
            color: Color.Grey,
          })
          .borderRadius(2)
          .padding({
            left: 2,
            right: 2
          })
          .margin({
            left: 10
          })
      }
      .alignItems(VerticalAlign.Center)
      .justifyContent(FlexAlign.Center)
      .margin({
        top: 20
      })

      Slider({
        min: 0,
        max: this.durationProgress,
        value: this.currentProgress,
        step: 1,
        style: SliderStyle.OutSet
      })
        .blockColor(Color.White)//进度条的控制色值
        .selectedColor(Color.White)//进度条的左边色值
        .trackColor($r('app.color.grey'))//进度条的右边色值
        .trackThickness(2)//进度条控制按钮的长度
        .onChange((value, model) => {
          LogUtils.e('onChange value:'+model.toString())
          if (model === SliderChangeMode.End) {
            // AvPlayerManager.seekProgress(value)
          }
        })
        .margin({
          top: 125
        })

      Row() {
        Text(this.currentTime)
          .fontColor($r('app.color.grey'))
          .fontSize(12)
          .fontWeight(FontWeight.Bold)
        Text(this.duration + '')
          .fontColor($r('app.color.grey'))
          .fontSize(12)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%').justifyContent(FlexAlign.SpaceBetween)

      Column() {
        Row() {
          Image($rawfile('ic_loop.png'))
            .width(30).aspectRatio(1)

          Image($rawfile('ic_up.png'))
            .width(30).aspectRatio(1)
            .onClick(() => {
              this.isNext = true
              AvPlayerManager.upMusic()
            })

          Image(this.isPlay ? $rawfile('ic_play.png') : $rawfile('ic_pause.png'))
            .width(60).aspectRatio(1)
            .onClick(() => {
              if (this.isPlay) {
                this.animatorResult.pause()
                AvPlayerManager.pause()
              } else {
                this.animatorResult.play()
                AvPlayerManager.continue()
              }
              this.isPlay = !this.isPlay
            })
          Image($rawfile('ic_up.png')).rotate({
            angle: 180
          })
            .width(30).aspectRatio(1)
            .onClick(() => {
              this.isNext = true
              AvPlayerManager.nextMusic()
            })
          Image($rawfile('ic_music.png'))
            .width(30).aspectRatio(1)
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
      }.margin({
        top: 10
      })
      .width('100%')
      .justifyContent(FlexAlign.Center)

    }
    .alignItems(HorizontalAlign.Start)
    .backgroundColor($r('app.color.black01'))
    .width('100%')
    .height('100%')
    .padding({
      right: 30,
      left: 30
    })
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
鸿蒙华为公司自主研发的操作系统,而“鸿蒙 JS 网络封装”指的是在鸿蒙操作系统中使用 JavaScript 进行网络封装鸿蒙 JS 网络封装是为了方便开发者使用 JavaScript 语言来进行网络相关的操作,比如发送网络请求、处理网络响应等。通过封装网络功能,开发者可以更加便捷地在鸿蒙操作系统上开发网络相关的应用。 鸿蒙 JS 网络封装提供了一系列 API 和函数,开发者可以使用这些接口进行网络请求。它包括了网络请求的发起、参数的设置、请求头的添加、响应结果的处理等功能。开发者可以根据自己的需求,使用这些函数进行网络操作。 使用鸿蒙 JS 网络封装可以帮助开发者实现以下功能: 1. 发送网络请求:开发者可以使用封装的函数发送 GET 或 POST 请求到指定的服务器地址,并获得服务器返回的结果。 2. 设置请求参数:通过网络封装,开发者可以设置请求的参数,比如请求的地址、请求的数据、请求超时时间等。 3. 处理响应结果:开发者可以通过网络封装获取服务器返回的响应结果,并对结果进行处理,比如解析 JSON 数据、处理错误信息等。 总之,鸿蒙 JS 网络封装提供了一种方便快捷的方式,让开发者可以使用 JavaScript 语言在鸿蒙操作系统上进行网络相关的操作。这对于开发鸿蒙应用的开发者来说,是一个有益的工具,能够提高开发效率,简化网络操作的流程,同时也为用户提供更好的使用体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jian11058

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值