


云音乐项目就剩最后一部分了,就是播控中心部分,今天上午看了下,感觉有点难,特别是对于不会看文档的小白来说确实有点难上手了,我在这里尽量讲解的通俗易懂,希望大家还是要学会读文档,会根据文档提示来学习,话不多说开始今天的学习
先把开发文档给到大家:开发文档


AVSession在构造方法中支持不同的类型参数,由 AVSessionType 定义,不同的类型代表了不同场景的控制能力,对于播控中心来说,会展示不同的控制模版。 audio类型,播控中心的控制样式为:收藏,上一首,播放/暂停,下一首,循环模式。 video类型,播控中心的控制样式为:快退,上一首,播放/暂停,下一首,快进。 voice_call类型,通话类型。
创建一个用于播控中心的工具类

初始化的时候就开始加载

应用退至后台后,在后台需要长时间运行用户可感知的任务,如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。在长时任务中,支持同时申请多种类型的任务,也可以对任务类型进行更新。应用退至后台执行业务时,系统会做一致性校验,确保应用在执行相应的长时任务。应用在申请长时任务成功后,通知栏会显示与长时任务相关联的消息,用户删除通知栏消息时,系统会自动停止长时任务。
先申请权限

声明后台模式类型

申请长时任务逻辑

在播放歌曲的时候使用

实现了歌曲可以在后台进行播放的功能

应用可以通过setAVMetadata把会话的一些元数据信息设置给系统,从而在播控中心界面进行展示,包括不限制:当前媒体的ID(assetId),上一首媒体的ID(previousAssetId),下一首媒体的ID(nextAssetId),标题(title),专辑作者(author),专辑名称(album),词作者(writer),媒体时长(duration)等。
就是设置一下所用到的数据

在时间变化这里添加以下即可

应用可以通过setAVPlaybackState。把当前的播放状态设置给系统,以在播控中心界面进行展示。 播放状态一般是在资源播放后会进行变化的内容,包括:当前媒体的播放状态(state)、播放位置(position)、播放倍速(speed)、缓冲时间(bufferedTime)、循环模式(loopMode)、是否收藏(isFavorite)、正在播放的媒体Id(activeItemId)、自定义媒体数据(extras)等。
核心逻辑如下,这里有三个地方需要设置播放状态




应用接入AVSession,可以通过注册不同的控制命令来实现播控中心界面上的控制操作,即通过on接口注册不同的控制命令参数,即可实现对应的功能。

一定要注销会话释放资源




这部分内容确实有点难以理解,课下还是要去再慢慢琢磨琢磨,感觉还是思路有点乱,感兴趣的可以仔细看一下这两个工具类中的代码,我这里就不意义解释了
AvSessionManager代码
import { avSession } from '@kit.AVSessionKit'
import { wantAgent } from '@kit.AbilityKit';
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import { GlobalMusic } from '../models/globalMusic';
import { AppStorageV2 } from '@kit.ArkUI';
import { SongItemType } from '../models/music';
import { playerManager } from './AvPlayerManager';
class AvSessionManager{
session : avSession.AVSession | null = null
playState:GlobalMusic = AppStorageV2.connect(GlobalMusic,'SONG_KEY',()=>new GlobalMusic())!
async init(content:Context){
this.session = await avSession.createAVSession(content,'bgPlay','audio')
this.registerEvent()
}
// 申请长时任务
async startBackGroundTask(){
let wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: "com.example.von_music",
abilityName: "EntryAbility"
}
],
actionType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
};
const want = await wantAgent.getWantAgent(wantAgentInfo)
await backgroundTaskManager.startBackgroundRunning(getContext(),backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,want)
}
// 设置元数据
setAVMetadata(song:SongItemType){
this.session?.setAVMetadata({
assetId:song.id,
title:song.name,
mediaImage:song.img,
artist:song.author,
duration:this.playState.duration
})
}
// 设置播放状态
setAVPlayBackState(){
this.session?.setAVPlaybackState({
state:this.playState.isPlay ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
speed:1,
position:{
elapsedTime:this.playState.time,//歌曲播放时间
updateTime:new Date().getTime()//系统时间
},
duration:this.playState.duration
})
}
// 注册事件
registerEvent(){
this.session?.on('play',()=>{
playerManager.singPlay(this.playState.playList[this.playState.playIndex])
})
this.session?.on('pause',()=>{
playerManager.paused()
})
this.session?.on('playPrevious',()=>{
playerManager.prevPlay()
})
this.session?.on('playNext',()=>{
playerManager.nextPlay()
})
this.session?.on('seek',(value:number)=>{
playerManager.seekPlay(value)
})
this.session?.activate()
}
// 注销会话
async destroy(){
await this.session?.destroy()
}
}
export const sessionManager : AvSessionManager = new AvSessionManager()AvPlayerManager代码
import { media } from '@kit.MediaKit'
import { GlobalMusic } from '../models/globalMusic'
import { SongItemType } from '../models/music'
import { AppStorageV2 } from '@kit.ArkUI'
import { sessionManager } from './AvSessionManager'
class AvPlayerManager{
// 播放器
player : media.AVPlayer | null = null
currentSong : GlobalMusic = AppStorageV2.connect(GlobalMusic,'SONG_KEY',()=>new GlobalMusic())!
// 定义方法
async init () {
if(!this.player){
this.player = await media.createAVPlayer()
}
// 监听状态变化
this.player.on('stateChange',(state) => {
if(state === 'initialized'){
this.player?.prepare()
}else if(state === 'prepared'){
this.player?.play()
this.currentSong.isPlay = true
} else if(state === 'completed'){
this.nextPlay(true)
} else if(state === 'released'){
this.currentSong.reset()
}
})
// 监听时间变化
this.player.on('durationUpdate',(duration)=>{
this.currentSong.duration = duration
sessionManager.setAVMetadata((this.currentSong.playList[this.currentSong.playIndex]))
})
this.player.on('timeUpdate',(time)=>{
this.currentSong.time = time
sessionManager.setAVPlayBackState()
})
}
// 播放歌曲
singPlay(song:SongItemType){
// 申请长时任务
sessionManager.startBackGroundTask()
sessionManager.setAVPlayBackState()
const inList = this.currentSong.playList.some(item => item.id === song.id)
// 歌曲在列表里
if(inList){
// 正在播放
if(this.currentSong.url === song.url){
this.player?.play()
this.currentSong.isPlay = true
}else {
// 如果没有播放根据索引找到歌曲进行播放
this.currentSong.playIndex = this.currentSong.playList.findIndex(item => item.id === song.id)
// 切歌
this.changeSong()
}
} else { // 歌曲不在列表
this.currentSong.playList.unshift(song) // 将歌曲添加到列表并且设置为索引为0
this.currentSong.playIndex = 0
// 切歌
this.changeSong()
}
}
// 切歌
async changeSong() {
await this.player?.reset()
this.currentSong.duration = 0
this.currentSong.time = 0
this.currentSong.img = this.currentSong.playList[this.currentSong.playIndex].img
this.currentSong.name = this.currentSong.playList[this.currentSong.playIndex].name
this.currentSong.author = this.currentSong.playList[this.currentSong.playIndex].author
this.currentSong.url = this.currentSong.playList[this.currentSong.playIndex].url
this.player!.url = this.currentSong.url
}
// 跳转进度 seek
seekPlay(value:number){
this.player?.seek(value)
}
// 暂停
paused() {
this.player?.pause()
this.currentSong.isPlay = false
sessionManager.setAVPlayBackState()
}
// 上一首
prevPlay(){
if(this.currentSong.playMode === 'random'){
// 随机播放
// Math.random : [0,1)
this.currentSong.playIndex = Math.floor(Math.random() * this.currentSong.playList.length)
}else {
this.currentSong.playIndex--
if(this.currentSong.playIndex < 0){
this.currentSong.playIndex = this.currentSong.playList.length - 1
}
}
this.singPlay(this.currentSong.playList[this.currentSong.playIndex])
}
// 下一首
nextPlay(autoNextPlay ?: boolean){
if(this.currentSong.playMode === 'repeat' && autoNextPlay){// 重复播放:当前模式为repeat并且autoNextPlay为true
this.currentSong.playIndex = this.currentSong.playIndex
}else if(this.currentSong.playMode === 'random'){
// 随机播放
// Math.random : [0,1)
this.currentSong.playIndex = Math.floor(Math.random() * this.currentSong.playList.length)
} else {
this.currentSong.playIndex++
if(this.currentSong.playIndex >= this.currentSong.playList.length){
this.currentSong.playIndex = 0
}
}
this.singPlay(this.currentSong.playList[this.currentSong.playIndex])
}
// 列表移除歌曲
removeSong(index:number){
if(index === this.currentSong.playIndex){
// 删除的是正在播放的歌曲
if(this.currentSong.playList.length > 1){
// 列表有多首歌
this.currentSong.playList.splice(index,1)
// 目前播放的歌曲的最后一首
if(this.currentSong.playIndex >= this.currentSong.playList.length){
this.currentSong.playIndex = 0
}
this.singPlay(this.currentSong.playList[this.currentSong.playIndex])
}else{
// 列表只有一首歌
this.player?.reset()
this.currentSong.reset()
}
} else {
if(index < this.currentSong.playIndex){
// 要删除歌曲在播放的前面
this.currentSong.playIndex--
}
this.currentSong.playList.splice(index,1)
}
}
// 释放播放器
async release() {
await this.player?.release()
}
}
export const playerManager : AvPlayerManager = new AvPlayerManager()