|
|
@@ -161,6 +161,11 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
this.stateSync.broadcastSongChange(song);
|
|
|
// 歌曲变化时更新AVSession元数据
|
|
|
this.unifiedService.updateAvSessionMetadata(song);
|
|
|
+ // 立即强制更新AVSession播放状态
|
|
|
+ setTimeout(() => {
|
|
|
+ const currentState = this.unifiedService.getCurrentState();
|
|
|
+ this.unifiedService.updateSessionPlayState(currentState.isPlaying);
|
|
|
+ }, 500);
|
|
|
// 歌曲变化时更新卡片
|
|
|
this.unifiedService.updateWidgetsForSongChange(song);
|
|
|
}
|
|
|
@@ -357,7 +362,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
// 保存播放状态变化
|
|
|
this.saveCurrentState();
|
|
|
|
|
|
- // 更新AVSession播放状态
|
|
|
+ // 立即更新AVSession播放状态
|
|
|
this.updateSessionPlayState(false);
|
|
|
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback paused');
|
|
|
@@ -805,103 +810,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 更新AVSession播放状态
|
|
|
- * 按照官方文档要求设置完整的播放状态信息
|
|
|
- */
|
|
|
- private updateSessionPlayState(isPlaying: boolean): void {
|
|
|
- if (!this.avSessionController) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession controller is null');
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- // 检查AVSession状态
|
|
|
- this.avSessionController.checkAvSessionStatus();
|
|
|
-
|
|
|
- const currentSong = this.playlistModel.getCurrentSong();
|
|
|
- const currentPosition = this.getCurrentPosition();
|
|
|
- const duration = currentSong?.duration ? Number(currentSong.duration) : 0;
|
|
|
- const currentState = this.stateModel.getState();
|
|
|
-
|
|
|
- // 按照官方文档要求设置完整的播放状态
|
|
|
- const playbackState: avSession.AVPlaybackState = {
|
|
|
- // 播放状态
|
|
|
- state: isPlaying ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
|
|
|
-
|
|
|
- // 播放位置信息 - 用于进度条显示
|
|
|
- position: {
|
|
|
- elapsedTime: currentPosition, // 已播放时间(毫秒)
|
|
|
- updateTime: Date.now() // 更新时间戳
|
|
|
- },
|
|
|
-
|
|
|
- // 播放速度
|
|
|
- speed: currentState.speed || 1.0,
|
|
|
-
|
|
|
- // 缓冲时间
|
|
|
- bufferedTime: Math.max(currentPosition, 0),
|
|
|
-
|
|
|
- // 循环模式
|
|
|
- loopMode: this.convertPlayModeToLoopMode(currentState.playMode),
|
|
|
-
|
|
|
- // 收藏状态
|
|
|
- isFavorite: false // 可以根据实际收藏状态设置
|
|
|
- };
|
|
|
-
|
|
|
- this.avSessionController.setAvSessionPlayState(playbackState);
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession play state updated: ${isPlaying ? 'PLAYING' : 'PAUSED'}, position: ${currentPosition}ms/${duration}ms, speed: ${playbackState.speed}x, loopMode: ${playbackState.loopMode}`);
|
|
|
- } catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to update AVSession play state: ${error}`);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置当前播放模式到AVSession
|
|
|
- */
|
|
|
- private setCurrentPlayMode(): void {
|
|
|
- if (!this.avSessionController) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- const playMode = this.stateModel.getState().playMode;
|
|
|
- const isPlaying = this.stateModel.getState().isPlaying;
|
|
|
- const currentPosition = this.getCurrentPosition();
|
|
|
-
|
|
|
- const playbackState: avSession.AVPlaybackState = {
|
|
|
- state: isPlaying ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
|
|
|
- position: {
|
|
|
- elapsedTime: currentPosition,
|
|
|
- updateTime: Date.now()
|
|
|
- },
|
|
|
- bufferedTime: currentPosition,
|
|
|
- loopMode: this.convertPlayModeToLoopMode(playMode),
|
|
|
- isFavorite: false
|
|
|
- };
|
|
|
-
|
|
|
- this.avSessionController.setAvSessionPlayState(playbackState);
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession play mode updated: ${playMode}`);
|
|
|
- } catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to set AVSession play mode: ${error}`);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 转换播放模式为AVSession循环模式
|
|
|
- */
|
|
|
- private convertPlayModeToLoopMode(playMode: PlayMode): avSession.LoopMode {
|
|
|
- switch (playMode) {
|
|
|
- case PlayMode.SINGLE_REPEAT:
|
|
|
- return avSession.LoopMode.LOOP_MODE_SINGLE;
|
|
|
- case PlayMode.NORMAL:
|
|
|
- return avSession.LoopMode.LOOP_MODE_LIST;
|
|
|
- case PlayMode.RANDOM:
|
|
|
- return avSession.LoopMode.LOOP_MODE_SHUFFLE;
|
|
|
- case PlayMode.SEQUENCE:
|
|
|
- default:
|
|
|
- return avSession.LoopMode.LOOP_MODE_SEQUENCE;
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* 转换AVSession循环模式为播放模式
|
|
|
@@ -919,38 +828,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
return PlayMode.SEQUENCE;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 更新AVSession元数据
|
|
|
- * 按照官方文档要求:设置必要的元数据(标题、副标题/歌手、封面图)
|
|
|
- */
|
|
|
- private async updateAvSessionMetadata(song: VideoItem): Promise<void> {
|
|
|
- if (!this.avSessionController || !song) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- const duration = song.duration ? Number(song.duration) : 0;
|
|
|
- // 获取歌词内容(如果有的话)
|
|
|
- const lyricContent = ''; // 这里可以根据需要获取歌词内容
|
|
|
-
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Setting AVSession metadata for "${song.name}" by "${song.artist || '未知艺术家'}"`);
|
|
|
-
|
|
|
- // 调用AvSessionController设置元数据,它会处理激活逻辑
|
|
|
- await this.avSessionController.setAVMetadataMusic(song, duration, lyricContent);
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession metadata and activation completed for ${song.name}`);
|
|
|
-
|
|
|
- // 元数据设置完成后,同步当前播放状态
|
|
|
- setTimeout(() => {
|
|
|
- const currentState = this.stateModel.getState();
|
|
|
- this.updateSessionPlayState(currentState.isPlaying);
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession state synced - playing: ${currentState.isPlaying}`);
|
|
|
- }, 300); // 延迟300ms确保AVSession完全激活
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to update AVSession metadata: ${error}`);
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
|
|
|
// ==================== 错误处理和恢复方法 ====================
|
|
|
|
|
|
@@ -1205,11 +1083,15 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
this.stateModel.updateProgress(currentPosition, duration);
|
|
|
|
|
|
// 定期更新AVSession播放状态,确保系统媒体控制界面显示正确的进度
|
|
|
- // 但不要太频繁,避免性能问题
|
|
|
+ // 前30秒每3秒更新一次,之后每10秒更新一次
|
|
|
const now = Date.now();
|
|
|
- if (!this.lastAvSessionUpdate || now - this.lastAvSessionUpdate > 5000) { // 每5秒更新一次
|
|
|
+ const timeSinceStart = now - (this.lastAvSessionUpdate || now);
|
|
|
+ const updateInterval = timeSinceStart < 30000 ? 3000 : 10000; // 前30秒3秒一次,之后10秒一次
|
|
|
+
|
|
|
+ if (!this.lastAvSessionUpdate || now - this.lastAvSessionUpdate > updateInterval) {
|
|
|
this.lastAvSessionUpdate = now;
|
|
|
this.updateSessionPlayState(true);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession progress updated - Position: ${currentPosition}ms, Duration: ${duration}ms`);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
LogUtils.getInstance().LOGI(`UnifiedPlayerService updateProgress error: ${error}`);
|
|
|
@@ -1626,6 +1508,14 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
onPrepared(): void {
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: Player prepared');
|
|
|
this.stateModel.updateLoadingState(false);
|
|
|
+
|
|
|
+ // 播放器准备完成时立即更新AVSession状态
|
|
|
+ setTimeout(() => {
|
|
|
+ const currentState = this.stateModel.getState();
|
|
|
+ this.updateSessionPlayState(currentState.isPlaying);
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession state updated after player prepared');
|
|
|
+ }, 100);
|
|
|
+
|
|
|
// 播放器准备完成时更新卡片(移除加载状态)
|
|
|
this.updateWidgetsForStateChange(this.stateModel.getState());
|
|
|
}
|
|
|
@@ -1638,16 +1528,18 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
// 保存播放状态变化
|
|
|
this.saveCurrentState();
|
|
|
|
|
|
- // 立即更新AVSession播放状态
|
|
|
- this.updateSessionPlayState(true);
|
|
|
-
|
|
|
- // 设置当前播放模式
|
|
|
- this.setCurrentPlayMode();
|
|
|
+ // 延迟一点更新AVSession,确保播放器状态稳定
|
|
|
+ setTimeout(() => {
|
|
|
+ this.updateSessionPlayState(true);
|
|
|
+ // 设置当前播放模式
|
|
|
+ this.setCurrentPlayMode();
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession state updated to PLAYING with current position');
|
|
|
+ }, 200);
|
|
|
|
|
|
// 播放开始时更新卡片显示播放状态
|
|
|
this.updateWidgetsForPlayStateChange(true);
|
|
|
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback started - AVSession state updated to PLAYING');
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback started - AVSession update scheduled');
|
|
|
}
|
|
|
|
|
|
onPlaybackCompleted(): void {
|
|
|
@@ -1658,7 +1550,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
// 保存播放状态变化
|
|
|
this.saveCurrentState();
|
|
|
|
|
|
- // 更新AVSession播放状态
|
|
|
+ // 立即更新AVSession播放状态为完成
|
|
|
this.updateSessionPlayState(false);
|
|
|
|
|
|
// 更新卡片显示播放完成状态
|
|
|
@@ -1873,23 +1765,245 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
|
|
|
*/
|
|
|
private parseDuration(durationStr: string): number {
|
|
|
if (!durationStr || durationStr === '0') {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - empty or zero duration: '${durationStr}'`);
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
- // 如果已经是数字,直接返回
|
|
|
- const numValue = Number(durationStr);
|
|
|
- if (!isNaN(numValue)) {
|
|
|
- return numValue;
|
|
|
+
|
|
|
+ try {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - parsing: '${durationStr}'`);
|
|
|
+
|
|
|
+ // 如果是纯数字,假设是秒数
|
|
|
+ const numValue = parseFloat(durationStr);
|
|
|
+ if (!isNaN(numValue)) {
|
|
|
+ const result = Math.floor(numValue * 1000); // 转换为毫秒
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - parsed as number: ${numValue}s -> ${result}ms`);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果包含冒号,解析为 MM:SS 或 HH:MM:SS 格式
|
|
|
+ if (durationStr.includes(':')) {
|
|
|
+ const parts = durationStr.split(':').map(part => parseInt(part, 10));
|
|
|
+ let totalSeconds = 0;
|
|
|
+
|
|
|
+ if (parts.length === 2) {
|
|
|
+ // MM:SS 格式
|
|
|
+ totalSeconds = parts[0] * 60 + parts[1];
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - parsed MM:SS format: ${durationStr} -> ${totalSeconds}s`);
|
|
|
+ } else if (parts.length === 3) {
|
|
|
+ // HH:MM:SS 格式
|
|
|
+ totalSeconds = parts[0] * 3600 + parts[1] * 60 + parts[2];
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - parsed HH:MM:SS format: ${durationStr} -> ${totalSeconds}s`);
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = totalSeconds * 1000; // 转换为毫秒
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - final result: ${result}ms`);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: parseDuration - unknown format: '${durationStr}', returning 0`);
|
|
|
+ return 0;
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService parseDuration error for '${durationStr}': ${error}`);
|
|
|
+ return 0;
|
|
|
}
|
|
|
-
|
|
|
- // 解析 MM:SS 格式
|
|
|
- const parts = durationStr.split(':');
|
|
|
- if (parts.length === 2) {
|
|
|
- const minutes = parseInt(parts[0]) || 0;
|
|
|
- const seconds = parseInt(parts[1]) || 0;
|
|
|
- return (minutes * 60 + seconds) * 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== PlayerStateCallback 实现 ====================
|
|
|
+
|
|
|
+
|
|
|
+ // ==================== AVSession 相关方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换播放模式为AVSession循环模式
|
|
|
+ */
|
|
|
+ private convertPlayModeToLoopMode(playMode: number): avSession.LoopMode {
|
|
|
+ switch (playMode) {
|
|
|
+ case PlayMode.SINGLE_REPEAT:
|
|
|
+ return avSession.LoopMode.LOOP_MODE_SINGLE;
|
|
|
+ case PlayMode.NORMAL:
|
|
|
+ return avSession.LoopMode.LOOP_MODE_LIST;
|
|
|
+ case PlayMode.RANDOM:
|
|
|
+ return avSession.LoopMode.LOOP_MODE_SHUFFLE;
|
|
|
+ case PlayMode.SEQUENCE:
|
|
|
+ default:
|
|
|
+ return avSession.LoopMode.LOOP_MODE_SEQUENCE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新AVSession播放状态
|
|
|
+ */
|
|
|
+ private updateSessionPlayState(isPlaying: boolean): void {
|
|
|
+ try {
|
|
|
+ if (!this.avSessionController) {
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession controller not initialized');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentSong = this.playlistModel.getCurrentSong();
|
|
|
+ const currentPosition = this.getCurrentPosition();
|
|
|
+
|
|
|
+ // 优先从播放器获取实际duration
|
|
|
+ let duration = 0;
|
|
|
+ try {
|
|
|
+ const ijkPlayer = this.playerManager.getIjkPlayer();
|
|
|
+ if (ijkPlayer) {
|
|
|
+ duration = ijkPlayer.getDuration();
|
|
|
+ }
|
|
|
+ if (duration <= 0 && currentSong?.duration) {
|
|
|
+ duration = this.parseDuration(currentSong.duration);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ duration = currentSong?.duration ? this.parseDuration(currentSong.duration) : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentState = this.stateModel.getState();
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession update - Position: ${currentPosition}ms, Duration: ${duration}ms, Song: ${currentSong?.name}`);
|
|
|
+
|
|
|
+ // 按照官方文档要求设置完整的播放状态
|
|
|
+ const playbackState: avSession.AVPlaybackState = {
|
|
|
+ // 播放状态
|
|
|
+ state: isPlaying ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
|
|
|
+
|
|
|
+ // 播放速度
|
|
|
+ speed: currentState.speed || 1.0,
|
|
|
+
|
|
|
+ // 循环模式
|
|
|
+ loopMode: this.convertPlayModeToLoopMode(currentState.playMode),
|
|
|
+
|
|
|
+ // 收藏状态
|
|
|
+ isFavorite: false // 可以根据实际收藏状态设置
|
|
|
+ };
|
|
|
+
|
|
|
+ // 只有当duration > 0时才设置位置信息,避免进度条显示问题
|
|
|
+ if (duration > 0) {
|
|
|
+ playbackState.position = {
|
|
|
+ elapsedTime: Math.max(0, currentPosition), // 已播放时间(毫秒)
|
|
|
+ updateTime: Date.now() // 更新时间戳
|
|
|
+ };
|
|
|
+ playbackState.bufferedTime = Math.max(currentPosition, 0);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Setting position info - Position: ${currentPosition}ms, Duration: ${duration}ms`);
|
|
|
+ } else {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Skipping position info due to invalid duration: ${duration}ms`);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.avSessionController.setAvSessionPlayState(playbackState);
|
|
|
+
|
|
|
+ // 记录上次更新时间
|
|
|
+ this.lastAvSessionUpdate = Date.now();
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to update AVSession play state: ${error}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置当前播放模式到AVSession
|
|
|
+ */
|
|
|
+ private setCurrentPlayMode(): void {
|
|
|
+ try {
|
|
|
+ if (!this.avSessionController) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentSong = this.playlistModel.getCurrentSong();
|
|
|
+ if (!currentSong) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 修复duration转换问题 - 优先从播放器获取实际duration
|
|
|
+ let duration = 0;
|
|
|
+ try {
|
|
|
+ const ijkPlayer = this.playerManager.getIjkPlayer();
|
|
|
+ if (ijkPlayer) {
|
|
|
+ const playerDuration = ijkPlayer.getDuration();
|
|
|
+ if (playerDuration > 0) {
|
|
|
+ duration = playerDuration;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Using player duration: ${duration}ms`);
|
|
|
+ } else {
|
|
|
+ // 备用方案:解析VideoItem中的duration
|
|
|
+ duration = currentSong.duration ? this.parseDuration(currentSong.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Using parsed duration: ${duration}ms from '${currentSong.duration}'`);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ duration = currentSong.duration ? this.parseDuration(currentSong.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: No player available, using parsed duration: ${duration}ms`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ duration = currentSong.duration ? this.parseDuration(currentSong.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error getting player duration, using parsed: ${duration}ms, error: ${error}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取歌词内容(如果有的话)
|
|
|
+ const lyricContent = ''; // 这里可以根据需要获取歌词内容
|
|
|
+
|
|
|
+ this.avSessionController.setAVMetadataMusic(currentSong, duration, lyricContent);
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession metadata updated for ${currentSong.name} with duration ${duration}ms`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to set current play mode: ${error}`);
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新AVSession元数据
|
|
|
+ */
|
|
|
+ private async updateAvSessionMetadata(song: VideoItem): Promise<void> {
|
|
|
+ try {
|
|
|
+ if (!this.avSessionController) {
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession controller not initialized');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 调试:打印VideoItem的duration字段
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: VideoItem duration field - value: '${song.duration}', type: ${typeof song.duration}`);
|
|
|
+
|
|
|
+ // 优先从播放器获取实际duration
|
|
|
+ let duration = 0;
|
|
|
+ try {
|
|
|
+ const ijkPlayer = this.playerManager.getIjkPlayer();
|
|
|
+ if (ijkPlayer) {
|
|
|
+ const playerDuration = ijkPlayer.getDuration();
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Player getDuration() returned: ${playerDuration}ms`);
|
|
|
+ if (playerDuration > 0) {
|
|
|
+ duration = playerDuration;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Using player duration: ${duration}ms`);
|
|
|
+ } else {
|
|
|
+ // 备用方案:解析VideoItem中的duration
|
|
|
+ duration = song.duration ? this.parseDuration(song.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Player duration invalid, using parsed duration: ${duration}ms from '${song.duration}'`);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ duration = song.duration ? this.parseDuration(song.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: No player available, using parsed duration: ${duration}ms from '${song.duration}'`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ duration = song.duration ? this.parseDuration(song.duration) : 0;
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error getting player duration, using parsed: ${duration}ms from '${song.duration}', error: ${error}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 最终验证duration
|
|
|
+ if (isNaN(duration) || duration <= 0) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Final duration is invalid (${duration}), setting to 0`);
|
|
|
+ duration = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取歌词内容(如果有的话)
|
|
|
+ const lyricContent = song.lyricContent || '';
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: About to call setAVMetadataMusic with duration: ${duration}ms (type: ${typeof duration})`);
|
|
|
+ await this.avSessionController.setAVMetadataMusic(song, duration, lyricContent);
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession metadata updated for ${song.name} with duration ${duration}ms`);
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to update AVSession metadata: ${error}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 辅助方法 ====================
|
|
|
+
|
|
|
+
|
|
|
}
|