xugenyuan

ref |> 处理播控中心进度条问题

... ... @@ -45,11 +45,10 @@ export class AudioSuspensionModel {
this.playerController.get().keepOnBackground = true
BackgroundAudioController.sharedController().avplayerController = this.playerController.get()
await BackgroundAudioController.sharedController().createSession()
BackgroundAudioController.sharedController().startContinuousTask()
let id = $r('app.media.newspaper_default').id
BackgroundAudioController.sharedController().setSessionMetaData(srcContentId ?? "", srcTitle, 'file://', srcSource ?? "")
BackgroundAudioController.sharedController().stopUseFeatures()
// BackgroundAudioController.sharedController().startContinuousTask()
BackgroundAudioController.sharedController().listenPlayEvents()
await BackgroundAudioController.sharedController().setSessionMetaData(srcContentId ?? "", srcTitle, $r("app.media.system_audio_icon_bk_center"), srcSource ?? "")
BackgroundAudioController.sharedController().stopUseFeatures()
if (this.url === url) {
this.isMinimize = AppStorage.link<boolean>('isMinimize')
... ...
... ... @@ -2,10 +2,11 @@ import { Context, WantAgent, wantAgent } from '@kit.AbilityKit'
import { avSession as AVSessionManager } from '@kit.AVSessionKit'
import { backgroundTaskManager } from '@kit.BackgroundTasksKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { Logger } from 'wdKit/Index'
import { PlayerConstants } from '../constants/PlayerConstants'
import { DateTimeUtils, EmitterEventId, EmitterUtils, Logger } from 'wdKit/Index'
import { Events, PlayerConstants } from '../constants/PlayerConstants'
import { WDPlayerController } from './WDPlayerController'
import { image } from '@kit.ImageKit'
import { JSON } from '@kit.ArkTS'
const TAG = "BackgroundAudioController"
... ... @@ -13,6 +14,9 @@ export class BackgroundAudioController {
private static bgAudioController: BackgroundAudioController
private constructor() {
EmitterUtils.receiveEvent(EmitterEventId.APP_ENTER_BACKGROUD, () => {
this.startContinuousTask()
})
}
public static sharedController() {
if (!BackgroundAudioController.bgAudioController) {
... ... @@ -24,9 +28,17 @@ export class BackgroundAudioController {
public gotContextFunc?: () => Context
public avplayerController?: WDPlayerController
private lastSession?: AVSessionManager.AVSession
private applyedLongTaskPlay: boolean = false
private lastProgress: number = 0.0
private hasSetupProgress: boolean = false
private playing: boolean = false
private lastItemAssetId?: string
private lastItemTitle?: string
private lastItemMediaImage?: Resource
private lastItemArtist?: string
private lastItemTotalDuration: number = 0
// 开始创建并激活媒体会话
// 创建session
... ... @@ -56,23 +68,53 @@ export class BackgroundAudioController {
}
//设置播放元数据
setSessionMetaData(assetId: string, title: string, mediaImage: image.PixelMap | string, artist: string) {
Logger.debug(TAG, `SetAVMetadata assetId: ${assetId}}, title: ${title}, mediaImage: ${mediaImage}, artist: ${artist}`);
async setSessionMetaData(assetId: string, title: string, mediaImage: Resource, artist: string) {
this.lastItemAssetId = assetId
this.lastItemTitle = title
this.lastItemMediaImage = mediaImage
this.lastItemArtist = artist
}
async setSessionMetaDataWithDuration(assetId: string, title: string, mediaImage: Resource, artist: string, duration: number) {
Logger.debug(TAG, `SetAVMetadata assetId: ${assetId}}, title: ${title}, mediaImage: ${mediaImage}, artist: ${artist}, duration: ${duration}`);
if (!this.gotContextFunc) { return }
let pixelMapImage:image.PixelMap | null = null
try {
const data:Uint8Array = await this.gotContextFunc().resourceManager.getMediaContent(mediaImage)
pixelMapImage = await image.createPixelMap(data.buffer as ArrayBuffer, {
editable: false,
alphaType: image.AlphaType.UNKNOWN,
srcPixelFormat: image.PixelMapFormat.RGB_888,
size: { width:300, height:300 }
})
} catch (e) {
Logger.error(TAG, `SetAVMetadata ` + JSON.stringify(e));
} finally {
// Logger.debug(TAG, `SetAVMetadata ` + JSON.stringify(pixelMapImage));
let metadata: AVSessionManager.AVMetadata = {
assetId: assetId.length > 0 ? assetId : "fake-asset-id",
title: title.length > 0 ? title : " ",
mediaImage: mediaImage,
mediaImage: pixelMapImage ?? ("file://" + mediaImage.id),
artist: artist.length > 0 ? artist : "人日日报",
duration: duration
};
this.lastSession?.setAVMetadata(metadata).then(() => {
try {
await this.lastSession?.setAVMetadata(metadata)
Logger.debug(TAG, `SetAVMetadata successfully`);
}).catch((err: BusinessError) => {
} catch (err) {
Logger.error(TAG, `Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`);
});
} finally {
pixelMapImage?.release()
}
}
}
//设置播放状态
setSessionPlayStatus(playStatus: number) {
let needUpdateProgress = false
let playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY
switch (playStatus){
case PlayerConstants.STATUS_PAUSE: {
... ... @@ -80,6 +122,7 @@ export class BackgroundAudioController {
} break
case PlayerConstants.STATUS_START: {
playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY
needUpdateProgress = true
} break
case PlayerConstants.STATUS_STOP: {
playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_STOP
... ... @@ -103,13 +146,15 @@ export class BackgroundAudioController {
Logger.error(TAG, `Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`);
} else {
Logger.debug(TAG, `SetAVPlaybackState 设置播放状态成功 ` + playStatus);
if (needUpdateProgress) {
this.hasSetupProgress = false
}
}
});
}
//设置进度,单位秒
setSessionPlayProgress(progressDuration: number, totalDuration: number) {
// Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
//设置进度,单位ms
async setSessionPlayProgress(progressDuration: number, totalDuration: number) {
if (totalDuration <= 0) {
return
}
... ... @@ -117,25 +162,38 @@ export class BackgroundAudioController {
if (Math.abs(newProgress - this.lastProgress) < 0.01) {
return
}
// Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
this.lastProgress = newProgress
if (this.lastItemAssetId) {
this.lastItemTotalDuration = totalDuration
await this.setSessionMetaDataWithDuration(
this.lastItemAssetId ?? "",
this.lastItemTitle ?? "",
this.lastItemMediaImage!,
this.lastItemArtist ?? "",
totalDuration
)
this.lastItemAssetId = undefined
}
if (this.hasSetupProgress) {
return
}
this.hasSetupProgress = true
Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
Logger.debug(TAG, `set progress: ` + DateTimeUtils.secondToTime(progressDuration / 1000)
+ " duration: " + DateTimeUtils.secondToTime(totalDuration / 1000));
// 设置状态: 播放状态,进度位置,播放倍速,缓存的时间
let playbackState: AVSessionManager.AVPlaybackState = {
state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态
position: {
elapsedTime: progressDuration * 1000, // 已经播放的位置,以ms为单位
elapsedTime: progressDuration, // 已经播放的位置,以ms为单位
updateTime: new Date().getTime(), // 应用更新当前位置时的时间戳,以ms为单位
},
duration: totalDuration * 1000,
speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
bufferedTime: totalDuration * 1000, // 可选,资源缓存的时间,以ms为单位
// duration: totalDuration,
// speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
// bufferedTime: totalDuration, // 可选,资源缓存的时间,以ms为单位
};
this.lastSession?.setAVPlaybackState(playbackState, (err) => {
if (err) {
... ... @@ -181,8 +239,12 @@ export class BackgroundAudioController {
// Logger.debug(TAG, `on playPrevious `);
// });
this.lastSession?.on('seek', (position: number) => {
Logger.debug(TAG, `on seek , the time is ${JSON.stringify(position)}`);
Logger.debug(TAG, `on seek , the time is ${position}`);
if (this.lastItemTotalDuration == 0) {
return
}
this.hasSetupProgress = true
// 由于应用内seek可能会触发较长的缓冲等待,可以先把状态设置为 Buffering
let playbackState: AVSessionManager.AVPlaybackState = {
state: AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING, // 缓冲状态
... ... @@ -193,11 +255,13 @@ export class BackgroundAudioController {
} else {
Logger.debug(TAG, `SetAVPlaybackState seek buffering`);
}
});
// 应用响应seek命令,使用应用内播放器完成seek实现
this.avplayerController?.setSeekTime(position * 0.001, SliderChangeMode.End)
this.avplayerController?.setSeekMicroSecondsTime(position)
setTimeout(() => {
this.hasSetupProgress = false
}, 1000)
});
});
}
... ... @@ -239,6 +303,7 @@ export class BackgroundAudioController {
// 通过wantAgent模块下getWantAgent方法获取WantAgent对象
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
if (!this.gotContextFunc) { return }
this.lastSession?.setLaunchAbility(wantAgentObj)
backgroundTaskManager.startBackgroundRunning(this.gotContextFunc(),
backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
wantAgentObj).then(() => {
... ...
... ... @@ -336,6 +336,13 @@ export class WDPlayerController {
this.avPlayer?.seek(this.seekTime);
}
}
async setSeekMicroSecondsTime(value: number) {
// 防止seek报错
if (this.avPlayer && PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer?.state) === -1) {
return;
}
this.avPlayer?.seek(value);
}
setBright() {
// globalThis.windowClass.setWindowBrightness(this.playerThis.bright)
... ...