Ver Fonte

修复时间进度显示异常

chendeben há 1 ano atrás
pai
commit
5197d1d9ce

+ 263 - 0
TTMusic播放流程分析.md

@@ -0,0 +1,263 @@
+# TTMusic APP 播放流程详细分析
+
+## 1. 架构概览
+
+TTMusic采用了分层架构设计,主要包含以下核心组件:
+
+- **UnifiedPlayerService**: 统一播放器服务,提供高级播放控制接口
+- **PlayerManager**: 播放器管理器,负责ijkPlayer实例的管理和音频会话
+- **PlayerStateModel**: 播放状态模型,管理播放状态并提供状态验证
+- **PlaylistModel**: 播放列表模型,管理播放列表和播放导航逻辑
+- **IjkMediaPlayer**: 基于ijkplayer的播放器核心实现
+- **AvSessionController**: 系统媒体会话控制,实现系统级媒体控制
+- **VideoItem**: 媒体数据模型,表示音频/视频文件
+
+## 2. 播放流程详细分析
+
+### 2.1 初始化流程
+
+1. **应用启动时**:
+   - [`UnifiedPlayerService.getInstance()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:146) 获取单例实例
+   - 调用 [`initialize(context)`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:152) 进行初始化
+   - 创建核心组件:PlayerManager、PlayerStateModel、PlaylistModel等
+   - 设置状态监听器和回调
+
+2. **播放器初始化**:
+   - [`PlayerManager.initialize()`](entry/src/main/ets/common/service/PlayerManager.ets:74) 初始化ijkplayer
+   - [`setupIjkPlayerOptions()`](entry/src/main/ets/common/service/PlayerManager.ets:84) 配置播放器选项
+   - [`setupPlayerCallbacks()`](entry/src/main/ets/common/service/PlayerManager.ets:142) 设置播放器回调
+
+3. **AVSession初始化**:
+   - [`AvSessionController.getInstance()`](entry/src/main/ets/controller/AvSessionController.ets:40) 获取系统媒体会话控制器
+   - [`initAvSession()`](entry/src/main/ets/controller/AvSessionController.ets:47) 初始化系统媒体会话
+   - [`registerControlCommands()`](entry/src/main/ets/controller/AvSessionController.ets:232) 注册系统控制命令
+
+### 2.2 播放控制流程
+
+#### 2.2.1 点击播放/恢复播放
+
+1. **用户触发播放**:
+   - UI调用 [`UnifiedPlayerService.startPlayOrResumePlay()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:262)
+
+2. **服务就绪检查**:
+   - [`isAllServicesReady()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:769) 检查所有服务是否就绪
+   - 如果未就绪,调用 [`waitForAllServicesReady()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:918) 等待服务初始化完成
+
+3. **获取当前歌曲**:
+   - [`playlistModel.getCurrentSong()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:278) 获取当前歌曲
+   - 如果没有歌曲,尝试从持久化存储恢复状态
+
+4. **播放器状态检查**:
+   - [`canResumeFromPause()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:319) 检查是否可以从暂停状态恢复
+   - 如果可以恢复,调用 [`resumeFromPause()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:365)
+
+5. **设置播放器**:
+   - [`setupPlayerForSong()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1436) 为当前歌曲配置播放器
+   - 调用 [`ijkPlayer.reset()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:186) 重置播放器状态
+   - [`ijkPlayer.setDataSource()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:110) 设置数据源
+   - [`ijkPlayer.setDataSourceHeader()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:118) 设置HTTP请求头
+
+6. **准备播放**:
+   - [`ijkPlayer.prepareAsync()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:154) 异步准备播放器
+   - 准备完成后触发 [`onPrepared()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2003) 回调
+
+7. **开始播放**:
+   - 在 [`onPrepared()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2003) 回调中
+   - 如果不是暂停状态,调用 [`ijkPlayer.start()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:162) 开始播放
+   - 触发 [`onPlaybackStarted()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2026) 回调
+
+8. **状态更新**:
+   - [`stateModel.updatePlayingState(true)`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2033) 更新播放状态
+   - [`startProgressTimer()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2036) 启动进度定时器
+   - [`saveCurrentState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2039) 保存当前状态
+   - [`updateSessionPlayState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2044) 更新系统媒体会话状态
+
+#### 2.2.2 点击暂停
+
+1. **用户触发暂停**:
+   - UI调用 [`UnifiedPlayerService.pause()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:459)
+
+2. **保存播放位置**:
+   - [`savePlaybackPosition()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:471) 保存当前播放位置
+
+3. **暂停播放器**:
+   - [`playerManager.pausePlayback()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:474) 暂停播放器
+   - 内部调用 [`ijkPlayer.pause()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:178)
+
+4. **更新状态**:
+   - [`stateModel.updatePlayingState(false)`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:477) 更新播放状态为暂停
+   - [`stopProgressTimer()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:480) 停止进度定时器
+   - [`saveCurrentState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:486) 保存播放状态
+   - [`updateSessionPlayState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:489) 更新系统媒体会话状态
+
+#### 2.2.3 点击下一首
+
+1. **用户触发下一首**:
+   - UI调用 [`UnifiedPlayerService.playNext()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:550)
+
+2. **服务就绪检查**:
+   - [`isAllServicesReady()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:553) 检查服务是否就绪
+
+3. **播放列表导航**:
+   - [`playlistModel.hasNext()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:565) 检查是否有下一首
+   - [`playlistModel.moveToNext()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:568) 移动到下一首
+
+4. **更新状态模型**:
+   - [`stateModel.updateCurrentIndex()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:574) 更新当前索引
+   - [`stateModel.updateCurrentSong()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:579) 更新当前歌曲
+
+5. **停止当前播放**:
+   - [`stopSilently()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:583) 静默停止当前播放
+
+6. **播放新歌曲**:
+   - [`playNewSongDirectly()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:586) 直接播放新歌曲
+   - 内部调用 [`setupPlayerForSong()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1436) 和 [`ijkPlayer.prepareAsync()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:154)
+
+#### 2.2.4 点击上一首
+
+1. **用户触发上一首**:
+   - UI调用 [`UnifiedPlayerService.playPrevious()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:601)
+
+2. **流程与下一首类似**:
+   - 服务就绪检查
+   - 播放列表导航([`playlistModel.hasPrevious()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:616) 和 [`playlistModel.moveToPrevious()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:624))
+   - 更新状态模型
+   - 停止当前播放
+   - 播放新歌曲
+
+### 2.3 播放器状态管理
+
+#### 2.3.1 状态回调机制
+
+1. **PlayerManager回调**:
+   - [`onPrepared()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2003): 播放器准备完成
+   - [`onPlaybackStarted()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2026): 播放开始
+   - [`onPlaybackCompleted()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2054): 播放完成
+   - [`onPlaybackError()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:2068): 播放错误
+
+2. **PlayerStateModel状态更新**:
+   - [`updatePlayingState()`](entry/src/main/ets/common/service/PlayerStateModel.ets:128): 更新播放状态
+   - [`updateLoadingState()`](entry/src/main/ets/common/service/PlayerStateModel.ets:146): 更新加载状态
+   - [`updateProgress()`](entry/src/main/ets/common/service/PlayerStateModel.ets:157): 更新播放进度
+   - [`updateCurrentSong()`](entry/src/main/ets/common/service/PlayerStateModel.ets:244): 更新当前歌曲
+
+3. **状态监听通知**:
+   - [`notifyStateChanged()`](entry/src/main/ets/common/service/PlayerStateModel.ets:372): 通知状态变化
+   - [`notifyProgressChanged()`](entry/src/main/ets/common/service/PlayerStateModel.ets:386): 通知进度变化
+   - [`notifySongChanged()`](entry/src/main/ets/common/service/PlayerStateModel.ets:407): 通知歌曲变化
+
+#### 2.3.2 进度更新机制
+
+1. **进度定时器**:
+   - [`setupProgressTimer()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1486) 设置进度定时器
+   - 每秒调用 [`updateProgress()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1509) 更新进度
+
+2. **进度获取**:
+   - [`ijkPlayer.getCurrentPosition()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:393) 获取当前播放位置
+   - [`ijkPlayer.getDuration()`](ijkplayer/src/main/ets/ijkplayer/IjkMediaPlayer.ets:382) 获取总时长
+
+3. **进度保存**:
+   - [`savePlaybackPosition()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1553) 保存播放位置
+   - 使用PreferencesUtil保存到本地存储
+
+### 2.4 系统媒体会话控制
+
+#### 2.4.1 AVSession初始化
+
+1. **创建会话**:
+   - [`avSession.createAVSession()`](entry/src/main/ets/controller/AvSessionController.ets:60) 创建系统媒体会话
+
+2. **设置元数据**:
+   - [`setAVMetadataMusic()`](entry/src/main/ets/controller/AvSessionController.ets:138) 设置音乐元数据
+   - 包含标题、艺术家、专辑、封面图等信息
+
+3. **设置播放状态**:
+   - [`setAvSessionPlayState()`](entry/src/main/ets/controller/AvSessionController.ets:213) 设置播放状态
+   - 包含播放状态、位置、循环模式等信息
+
+#### 2.4.2 系统控制命令处理
+
+1. **命令监听**:
+   - [`setAvSessionListener()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1131) 设置系统控制监听器
+   - 监听播放、暂停、停止、下一首、上一首、拖动等命令
+
+2. **命令处理**:
+   - 接收到系统命令后,调用对应的播放控制方法
+   - 例如:播放命令调用 [`startPlayOrResumePlay()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:262)
+
+### 2.5 播放列表管理
+
+#### 2.5.1 播放列表操作
+
+1. **添加歌曲**:
+   - [`addSong()`](entry/src/main/ets/common/service/PlaylistModel.ets:82) 添加单首歌曲
+   - [`addSongs()`](entry/src/main/ets/common/service/PlaylistModel.ets:98) 添加多首歌曲
+
+2. **移除歌曲**:
+   - [`removeSong()`](entry/src/main/ets/common/service/PlaylistModel.ets:120) 移除歌曲
+
+3. **替换播放列表**:
+   - [`replaceSongs()`](entry/src/main/ets/common/service/PlaylistModel.ets:183) 替换整个播放列表
+
+#### 2.5.2 播放模式
+
+1. **播放模式类型**:
+   - [`PlayMode.SEQUENCE`](entry/src/main/ets/common/service/PlayerStateModel.ets:8): 顺序播放
+   - [`PlayMode.SINGLE_REPEAT`](entry/src/main/ets/common/service/PlayerStateModel.ets:9): 单曲循环
+   - [`PlayMode.NORMAL`](entry/src/main/ets/common/service/PlayerStateModel.ets:10): 正常播放
+   - [`PlayMode.RANDOM`](entry/src/main/ets/common/service/PlayerStateModel.ets:11): 随机播放
+
+2. **播放模式切换**:
+   - [`setPlayMode()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:960) 设置播放模式
+   - [`getPlayMode()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:966) 获取当前播放模式
+
+### 2.6 数据持久化
+
+#### 2.6.1 状态保存
+
+1. **播放状态保存**:
+   - [`saveCurrentState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1717) 保存当前播放状态
+   - 使用DataPersistenceService保存到持久化存储
+
+2. **播放位置保存**:
+   - [`savePlaybackPosition()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1553) 保存播放位置
+   - 使用PreferencesUtil保存到本地存储
+
+#### 2.6.2 状态恢复
+
+1. **从内存恢复**:
+   - [`fastRestoreFromMemory()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1604) 从AppStorage快速恢复
+
+2. **从持久化存储恢复**:
+   - [`restorePersistedState()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1647) 从持久化存储恢复状态
+
+3. **播放位置恢复**:
+   - [`restorePlaybackPosition()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1571) 恢复播放位置
+
+## 3. 错误处理机制
+
+### 3.1 错误类型
+
+- [`PlayerErrorType.INITIALIZATION_ERROR`](entry/src/main/ets/common/service/PlayerStateModel.ets:49): 初始化错误
+- [`PlayerErrorType.PLAYBACK_ERROR`](entry/src/main/ets/common/service/PlayerStateModel.ets:50): 播放错误
+- [`PlayerErrorType.NETWORK_ERROR`](entry/src/main/ets/common/service/PlayerStateModel.ets:51): 网络错误
+- [`PlayerErrorType.FILE_NOT_FOUND`](entry/src/main/ets/common/service/PlayerStateModel.ets:52): 文件未找到
+- [`PlayerErrorType.AUDIO_FOCUS_ERROR`](entry/src/main/ets/common/service/PlayerStateModel.ets:53): 音频焦点错误
+
+### 3.2 错误恢复策略
+
+1. **错误处理**:
+   - [`handlePlaybackError()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1231) 处理播放错误
+   - [`executeRecoveryAction()`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1263) 执行恢复动作
+
+2. **恢复动作**:
+   - [`ErrorRecoveryAction.RETRY`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1265): 重试
+   - [`ErrorRecoveryAction.SKIP_TO_NEXT`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1269): 跳到下一首
+   - [`ErrorRecoveryAction.STOP_PLAYBACK`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1273): 停止播放
+   - [`ErrorRecoveryAction.WAIT_AND_RETRY`](entry/src/main/ets/common/service/UnifiedPlayerService.ets:1277): 等待后重试
+
+## 4. 总结
+
+TTMusic的播放流程采用了分层架构设计,通过UnifiedPlayerService提供统一的播放控制接口,底层使用ijkplayer进行实际的音频解码和播放。整个播放流程包括初始化、播放控制、状态管理、系统媒体会话控制、播放列表管理、数据持久化和错误处理等环节,形成了一个完整的音乐播放器系统。
+
+系统通过状态模型、播放列表模型和播放器管理器的协同工作,实现了复杂的播放控制逻辑,同时通过AVSessionController与系统媒体控制进行集成,提供了系统级的媒体控制体验。

+ 48 - 48
entry/src/main/ets/common/service/DataPersistenceService.ets

@@ -125,7 +125,7 @@ export class DataPersistenceService implements IDataPersistenceService {
 
   async initialize(context: common.UIAbilityContext): Promise<void> {
     if (this.isInitialized && this.context) {
-      console.log('Heanup2 DataPersistenceService: Already initialized with valid context');
+      
       
       return;
     }
@@ -133,17 +133,17 @@ export class DataPersistenceService implements IDataPersistenceService {
     try {
       // 验证context是否有效
       if (!context) {
-        console.log('Heanup2 DataPersistenceService: Initialize failed - context is null');
+        
         throw new Error('Context is null');
       }
 
       this.context = context;
       this.isInitialized = true;
 
-      console.log('Heanup2 DataPersistenceService: Initialize successfully with context');
+      
       
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: Initialize error: ${error}`);
+      
       
       throw new Error;
     }
@@ -153,21 +153,21 @@ export class DataPersistenceService implements IDataPersistenceService {
    * 重新初始化context(用于context失效后的恢复)
    */
   async reinitialize(context: common.UIAbilityContext): Promise<void> {
-    console.log('Heanup2 DataPersistenceService: Reinitializing with new context');
+    
     
     try {
       if (!context) {
-        console.log('Heanup2 DataPersistenceService: Reinitialize failed - context is null');
+        
         throw new Error('Context is null');
       }
 
       this.context = context;
       this.isInitialized = true;
 
-      console.log('Heanup2 DataPersistenceService: Reinitialize successfully');
+      
       
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: Reinitialize error: ${error}`);
+      
       
       throw new Error;
     }
@@ -214,7 +214,7 @@ export class DataPersistenceService implements IDataPersistenceService {
         try {
           PreferencesUtil.putSync(key, JSON.stringify(progressData));
         } catch (error) {
-          console.log(`Heanup2 DataPersistenceService: 保存播放进度到PreferencesUtil失败: ${error}`);
+          
           
           // 即使PreferencesUtil失败,AppStorage已保存,不抛出异常
         }
@@ -270,7 +270,7 @@ export class DataPersistenceService implements IDataPersistenceService {
               break; // 没有数据
             }
           } catch (preferencesError) {
-            console.log(`Heanup2 DataPersistenceService: 加载播放进度失败 (尝试 ${retryCount + 1}/${maxRetries}): ${preferencesError}`);
+            
             
             if (preferencesError.toString().includes('context is invalid') && retryCount < maxRetries - 1) {
               await new Promise<void>(resolve => setTimeout(resolve, 50));
@@ -399,7 +399,7 @@ export class DataPersistenceService implements IDataPersistenceService {
   async savePlaylist(playlist: VideoItem[], currentIndex: number, playMode: PlayMode): Promise<void> {
     try {
       if (!this.isInitialized) {
-        console.log('Heanup2 DataPersistenceService: 保存播放列表失败 - 服务未初始化');
+        
         throw new Error('DataPersistenceService not initialized');
       }
 
@@ -412,7 +412,7 @@ export class DataPersistenceService implements IDataPersistenceService {
 
       // 首先保存到AppStorage(确保内存中有数据)
       AppStorage.setOrCreate(DataPersistenceService.KEYS.PLAYLIST, playlistData);
-      console.log(`Heanup2 DataPersistenceService: 已保存到AppStorage,歌曲数量: ${playlist.length}`);
+      
 
       // 如果context有效,尝试保存到PreferencesUtil
       if (this.context) {
@@ -423,14 +423,14 @@ export class DataPersistenceService implements IDataPersistenceService {
         while (retryCount < maxRetries) {
           try {
              PreferencesUtil.putSync(DataPersistenceService.KEYS.PLAYLIST, JSON.stringify(playlistData));
-            console.log(`Heanup2 DataPersistenceService: 已保存到PreferencesUtil (尝试 ${retryCount + 1}/${maxRetries})`);
+            
             break; // 成功,跳出循环
           } catch (error) {
             lastError = error;
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil保存失败 (尝试 ${retryCount + 1}/${maxRetries}): ${error}`);
+            
             
             if (error.toString().includes('context is invalid')) {
-              console.log(`Heanup2 DataPersistenceService: context无效,等待 ${100 * (retryCount + 1)}ms 后重试`);
+              
               await new Promise<void>(resolve => setTimeout(resolve, 100 * (retryCount + 1)));
             } else {
               // 其他错误,不重试
@@ -442,16 +442,16 @@ export class DataPersistenceService implements IDataPersistenceService {
         }
 
         if (retryCount >= maxRetries && lastError) {
-          console.log(`Heanup2 DataPersistenceService: PreferencesUtil保存所有重试都失败,但AppStorage已保存`);
+          
           
         }
       } else {
-        console.log('Heanup2 DataPersistenceService: context无效,仅保存到AppStorage');
+        
       }
 
       
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: 保存播放列表出错: ${error}`);
+      
       
       throw new Error;
     }
@@ -463,7 +463,7 @@ export class DataPersistenceService implements IDataPersistenceService {
   async loadPlaylist(): Promise<PlaylistData | null> {
     try {
       if (!this.isInitialized) {
-        console.log("Heanup2 DataPersistenceService: 服务未初始化");
+        
         throw new Error('DataPersistenceService not initialized');
       }
 
@@ -474,12 +474,12 @@ export class DataPersistenceService implements IDataPersistenceService {
       if (!playlistData) {
         // 检查context是否有效
         if (!this.context) {
-          console.log("Heanup2 DataPersistenceService: context为空,无法从PreferencesUtil加载");
+          
           return null;
         }
 
         // 从PreferencesUtil获取,增加重试机制
-        console.log("Heanup2 DataPersistenceService: 尝试从PreferencesUtil加载播放列表");
+        
 
         const maxRetries = 3;
         let retryCount = 0;
@@ -488,18 +488,18 @@ export class DataPersistenceService implements IDataPersistenceService {
         while (retryCount < maxRetries) {
           try {
             const playlistStr = PreferencesUtil.getStringSync(DataPersistenceService.KEYS.PLAYLIST, '');
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil返回的字符串长度: ${playlistStr.length} (尝试 ${retryCount + 1}/${maxRetries})`);
+            
 
             if (playlistStr) {
               try {
                 const parsedData = JSON.parse(playlistStr) as PlaylistData;
                 playlistData = parsedData;
-                console.log(`Heanup2 DataPersistenceService: 解析成功,歌曲数量: ${playlistData.songs?.length || 0}`);
+                
                 // 同步到AppStorage
                 AppStorage.setOrCreate(DataPersistenceService.KEYS.PLAYLIST, playlistData);
                 break; // 成功,跳出循环
               } catch (parseError) {
-                console.log(`Heanup2 DataPersistenceService: JSON解析失败: ${parseError}`);
+                
                 
                 return null;
               }
@@ -509,11 +509,11 @@ export class DataPersistenceService implements IDataPersistenceService {
             }
           } catch (preferencesError) {
             lastError = preferencesError;
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil访问失败 (尝试 ${retryCount + 1}/${maxRetries}): ${preferencesError}`);
+            
             
             // 如果是context无效错误,增加等待时间
             if (preferencesError.toString().includes('context is invalid')) {
-              console.log(`Heanup2 DataPersistenceService: context无效,等待 ${100 * (retryCount + 1)}ms 后重试`);
+              
               await new Promise<void>(resolve => setTimeout(resolve, 100 * (retryCount + 1)));
             } else {
               // 其他错误,不重试
@@ -526,19 +526,19 @@ export class DataPersistenceService implements IDataPersistenceService {
 
         // 如果所有重试都失败了
         if (retryCount >= maxRetries && lastError) {
-          console.log(`Heanup2 DataPersistenceService: 所有重试都失败,最后一个错误: ${lastError}`);
+          
           return null;
         }
       }
 
       if (playlistData) {
-        console.log(`Heanup2 DataPersistenceService: 最终加载成功,播放列表歌曲数量: ${playlistData.songs.length}`);
+        
         return playlistData;
       }
-      console.log("Heanup2 DataPersistenceService: 没有找到播放列表数据");
+      
       return null;
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: 加载播放列表出错: ${error}`);
+      
       return null;
     }
   }
@@ -551,7 +551,7 @@ export class DataPersistenceService implements IDataPersistenceService {
   async savePlayerState(state: PlayerState): Promise<void> {
     try {
       if (!this.isInitialized) {
-        console.log('Heanup2 DataPersistenceService: 保存播放状态失败 - 服务未初始化');
+        
         throw new Error('DataPersistenceService not initialized');
       }
 
@@ -580,10 +580,10 @@ export class DataPersistenceService implements IDataPersistenceService {
             break; // 成功,跳出循环
           } catch (error) {
             lastError = error;
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil播放状态保存失败 (尝试 ${retryCount + 1}/${maxRetries}): ${error}`);
+            
             
             if (error.toString().includes('context is invalid')) {
-              console.log(`Heanup2 DataPersistenceService: context无效,等待 ${100 * (retryCount + 1)}ms 后重试`);
+              
               await new Promise<void>(resolve => setTimeout(resolve, 100 * (retryCount + 1)));
             } else {
               // 其他错误,不重试
@@ -595,16 +595,16 @@ export class DataPersistenceService implements IDataPersistenceService {
         }
 
         if (retryCount >= maxRetries && lastError) {
-          console.log(`Heanup2 DataPersistenceService: 播放状态PreferencesUtil保存所有重试都失败,但AppStorage已保存`);
+          
           
         }
       } else {
-        console.log('Heanup2 DataPersistenceService: context无效,播放状态仅保存到AppStorage');
+        
       }
 
       
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: 保存播放状态出错: ${error}`);
+      
       
       throw new Error;
     }
@@ -616,11 +616,11 @@ export class DataPersistenceService implements IDataPersistenceService {
   async loadPlayerState(): Promise<PlayerStateData | null> {
     try {
       if (!this.isInitialized) {
-        console.log("Heanup2 DataPersistenceService: 播放状态加载失败 - 服务未初始化");
+        
         throw new Error('DataPersistenceService not initialized');
       }
 
-      console.log("Heanup2 DataPersistenceService: 开始加载播放状态");
+      
 
       // 优先从AppStorage获取
       let stateData = AppStorage.get<PlayerStateData>(DataPersistenceService.KEYS.PLAYER_STATE);
@@ -628,12 +628,12 @@ export class DataPersistenceService implements IDataPersistenceService {
       if (!stateData) {
         // 检查context是否有效
         if (!this.context) {
-          console.log("Heanup2 DataPersistenceService: context为空,无法从PreferencesUtil加载播放状态");
+          
           return null;
         }
 
         // 从PreferencesUtil获取,增加重试机制
-        console.log("Heanup2 DataPersistenceService: 尝试从PreferencesUtil加载播放状态");
+        
 
         const maxRetries = 3;
         let retryCount = 0;
@@ -642,18 +642,18 @@ export class DataPersistenceService implements IDataPersistenceService {
         while (retryCount < maxRetries) {
           try {
             const stateStr = PreferencesUtil.getStringSync(DataPersistenceService.KEYS.PLAYER_STATE, '');
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil返回的播放状态字符串长度: ${stateStr.length} (尝试 ${retryCount + 1}/${maxRetries})`);
+            
 
             if (stateStr) {
               try {
                 const parsedData = JSON.parse(stateStr) as PlayerStateData;
                 stateData = parsedData;
-                console.log(`Heanup2 DataPersistenceService: 播放状态解析成功 - playing: ${stateData.isPlaying}, paused: ${stateData.isPaused}, index: ${stateData.currentIndex}`);
+                
                 // 同步到AppStorage
                 AppStorage.setOrCreate(DataPersistenceService.KEYS.PLAYER_STATE, stateData);
                 break; // 成功,跳出循环
               } catch (parseError) {
-                console.log(`Heanup2 DataPersistenceService: 播放状态JSON解析失败: ${parseError}`);
+                
                 
                 return null;
               }
@@ -663,11 +663,11 @@ export class DataPersistenceService implements IDataPersistenceService {
             }
           } catch (preferencesError) {
             lastError = preferencesError;
-            console.log(`Heanup2 DataPersistenceService: PreferencesUtil播放状态访问失败 (尝试 ${retryCount + 1}/${maxRetries}): ${preferencesError}`);
+            
             
             // 如果是context无效错误,增加等待时间
             if (preferencesError.toString().includes('context is invalid')) {
-              console.log(`Heanup2 DataPersistenceService: context无效,等待 ${100 * (retryCount + 1)}ms 后重试`);
+              
               await new Promise<void>(resolve => setTimeout(resolve, 100 * (retryCount + 1)));
             } else {
               // 其他错误,不重试
@@ -680,7 +680,7 @@ export class DataPersistenceService implements IDataPersistenceService {
 
         // 如果所有重试都失败了
         if (retryCount >= maxRetries && lastError) {
-          console.log(`Heanup2 DataPersistenceService: 播放状态所有重试都失败,最后一个错误: ${lastError}`);
+          
           return null;
         }
       }
@@ -690,10 +690,10 @@ export class DataPersistenceService implements IDataPersistenceService {
         return stateData;
       }
 
-      console.log("Heanup2 DataPersistenceService: 没有找到播放状态数据");
+      
       return null;
     } catch (error) {
-      console.log(`Heanup2 DataPersistenceService: 加载播放状态出错: ${error}`);
+      
       
       return null;
     }

Diff do ficheiro suprimidas por serem muito extensas
+ 282 - 152
entry/src/main/ets/common/service/UnifiedPlayerService.ets


+ 308 - 142
entry/src/main/ets/view/LocalMusic.ets

@@ -48,7 +48,8 @@ import {
   PLAYER_PROGRESS_CHANGED_EVENT
 } from '../common/widget/WidgetEventConstants';
 import {
-// DeviceChangeReason,
+  IjkMediaPlayer,
+  // DeviceChangeReason,
   InterruptEvent,
   InterruptHintType,
   LogUtils
@@ -550,6 +551,8 @@ export struct LocalMusic {
           this.localMusic.oldSeconds = 0;
           this.localMusic.currentTime = "00:00";
           this.localMusic.lastSongPath = song.filePath; // 更新当前歌曲路径
+          this.localMusic.justSwitched = true; // 标记歌曲刚刚切换
+
 
           console.log(`Heanup onSongChanged - 重置后 oldSeconds: ${this.localMusic.oldSeconds}, currentTime: ${this.localMusic.currentTime}`);
 
@@ -4812,6 +4815,14 @@ export struct LocalMusic {
         this.cover = this.currentSong.pixelMapPath
         this.artist = this.currentSong.artist
 
+        // 重置时间显示状态,防止新歌曲时间显示被上一首歌曲的时间"卡住"
+        this.oldSeconds = 0;
+        this.currentTime = "00:00";
+        this.lastSongPath = this.currentSong.filePath;
+        this.justSwitched = true; // 标记歌曲刚刚切换
+
+        console.log(`Heanup doPlay - 重置时间显示状态: oldSeconds=${this.oldSeconds}, currentTime=${this.currentTime}`);
+
         // 同步播放列表到UnifiedPlayerService
         this.syncPlaylistToService();
 
@@ -6586,6 +6597,8 @@ export struct LocalMusic {
   @State isSeekTo: boolean = false;
   @State isCurrentTime: boolean = false;
   @State lastSongPath: string = ""; // 用于检测歌曲切换
+  @State justSwitched: boolean = false; // 标记歌曲刚刚切换
+  @State lastSwitchTime: number = 0; // 记录最后一次歌曲切换的时间戳
   @State videoWidth: string = '100%';
   @State videoHeight: string = '100%';
   @State initAspectRatio: number = 1;
@@ -9919,37 +9932,64 @@ export struct LocalMusic {
     try {
       // 检测歌曲是否发生切换(额外保障机制)
       const currentSongPath = this.currentSong?.filePath || "";
+      let isSongChanged = false;
       if (this.lastSongPath !== currentSongPath && currentSongPath !== "") {
         console.log(`Heanup 在进度更新中检测到歌曲切换: ${this.lastSongPath} -> ${currentSongPath}`);
-        console.log(`Heanup 歌曲切换前 oldSeconds: ${this.oldSeconds}`);
+        console.log(`Heanup 歌曲切换前 oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`);
+        // 立即重置时间显示状态,防止新歌曲时间显示被上一首歌曲的时间"卡住"
         this.oldSeconds = 0;
+        this.currentTime = "00:00";
         this.lastSongPath = currentSongPath;
-        console.log(`Heanup 歌曲切换后 oldSeconds: ${this.oldSeconds}`);
+        this.justSwitched = true; // 标记歌曲刚刚切换
+        isSongChanged = true;
+        console.log(`Heanup 歌曲切换后 oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`);
+        // 歌曲切换时,强制将播放位置重置为0,忽略服务报告的位置
+        progress.currentPosition = 0;
+        console.log(`Heanup 歌曲切换,强制progress.currentPosition为0`);
+        
+        // 立即返回,不更新进度,等待新歌曲开始播放
+        return;
       }
 
-      // 更新进度条
-      if (progress.duration > 0) {
-        this.slideEnable = true;
-        let curPercent = progress.currentPosition / progress.duration;
-        let pos = curPercent * 100;
-        if (pos > this.PROGRESS_MAX_VALUE) {
-          this.progressValue = this.PROGRESS_MAX_VALUE;
-        } else {
-          this.progressValue = pos;
+      // 直接使用ijkplayer获取播放进度,避免状态同步延迟
+      try {
+        const ijkPlayer = this.unifiedPlayerService.getIjkPlayer();
+        if (ijkPlayer && ijkPlayer.isPlaying()) {
+          const currentPosition = ijkPlayer.getCurrentPosition();
+          const duration = ijkPlayer.getDuration();
+          
+          if (duration > 0 && currentPosition >= 0) {
+            // 更新进度条
+            this.slideEnable = true;
+            let curPercent = currentPosition / duration;
+            let pos = curPercent * 100;
+            if (pos > this.PROGRESS_MAX_VALUE) {
+              this.progressValue = this.PROGRESS_MAX_VALUE;
+            } else {
+              this.progressValue = pos;
+            }
+
+            // 更新时间显示
+            this.totalTime = this.stringForTime(duration);
+            console.log(`Heanup 当前时间 (直接从ijkplayer获取) - ${currentPosition} / ${duration}`)
+            console.log(`Heanup 更新前 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
+            this.isCurrentTime = true;
+            this.currentTime = this.stringForTime(currentPosition);
+            this.isCurrentTime = false;
+            console.log(`Heanup 更新后 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
+            
+            // 继续执行后续的歌词更新等逻辑
+          }
         }
+      } catch (error) {
+        console.error('LocalMusic: 获取ijkplayer播放进度失败', error);
+        // 如果直接获取失败,回退到使用服务状态
+        this.updateProgressFromServiceState(progress);
+        return;
       }
 
-      // 更新时间显示
-      this.totalTime = this.stringForTime(progress.duration);
-      if (progress.currentPosition > progress.duration) {
-        progress.currentPosition = progress.duration;
-      }
-      console.log(`Heanup 当前时间 - ${progress.currentPosition} / ${progress.duration}`)
-      console.log(`Heanup 更新前 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
-      this.isCurrentTime = true;
-      this.currentTime = this.stringForTime(progress.currentPosition);
-      this.isCurrentTime = false;
-      console.log(`Heanup 更新后 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
+      // 如果直接获取ijkplayer失败或者不在播放状态,使用服务状态
+      this.updateProgressFromServiceState(progress);
 
       // 更新歌词位置
       const lyricPosition = progress.currentPosition + this.timeOffset * 1000;
@@ -9985,6 +10025,35 @@ export struct LocalMusic {
     }
   }
 
+  /**
+   * 从服务状态更新播放进度(回退方案)
+   */
+  private updateProgressFromServiceState(progress: PlayProgress) {
+    // 更新进度条
+    if (progress.duration > 0) {
+      this.slideEnable = true;
+      let curPercent = progress.currentPosition / progress.duration;
+      let pos = curPercent * 100;
+      if (pos > this.PROGRESS_MAX_VALUE) {
+        this.progressValue = this.PROGRESS_MAX_VALUE;
+      } else {
+        this.progressValue = pos;
+      }
+    }
+
+    // 更新时间显示
+    this.totalTime = this.stringForTime(progress.duration);
+    if (progress.currentPosition > progress.duration) {
+      progress.currentPosition = progress.duration;
+    }
+    console.log(`Heanup 当前时间 (从服务状态获取) - ${progress.currentPosition} / ${progress.duration}`)
+    console.log(`Heanup 更新前 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
+    this.isCurrentTime = true;
+    this.currentTime = this.stringForTime(progress.currentPosition);
+    this.isCurrentTime = false;
+    console.log(`Heanup 更新后 - oldSeconds: ${this.oldSeconds}, currentTime: ${this.currentTime}`)
+  }
+
   updateLastPlayTimeStr(filePath: string) {
     let lastPlayTime = DateUtil.getTodayStr('yyyy-MM-dd HH:mm:ss')
     this.table.updateLastPlayedStrByFilePath(filePath, lastPlayTime, (success: boolean, error?: string) => {
@@ -10005,85 +10074,182 @@ export struct LocalMusic {
     }
   }
 
+  // 纯粹的时间格式化函数,不包含任何业务逻辑
   private stringForTime(timeMs: number): string {
-    let totalSeconds: number | string = (timeMs / 1000);
-    let newSeconds: number | string = totalSeconds % 60;
-    let minutes: number | string = (totalSeconds / 60) % 60;
-    let hours: number | string = totalSeconds / 3600;
-    //LogUtils.getInstance().LOGI("stringForTime hours:" + hours + ",minutes:" + minutes + ",seconds:" + newSeconds);
-    hours = this.completionNum(Math.floor(Math.floor(hours * 100) / 100));
-    minutes = this.completionNum(Math.floor(Math.floor(minutes * 100) / 100));
-    newSeconds = Math.floor(Math.floor(newSeconds * 100) / 100)
+    let totalSeconds: number = Math.floor(timeMs / 1000);
+    let seconds: number = totalSeconds % 60;
+    let minutes: number = Math.floor(totalSeconds / 60) % 60;
+    let hours: number = Math.floor(totalSeconds / 3600);
+
+    // 防抖逻辑:只在当前播放时间更新时生效
     if (this.isCurrentTime) {
-      if (this.oldSeconds < newSeconds || newSeconds === 0 || this.isSeekTo) {
-        this.oldSeconds = newSeconds
+      // 如果歌曲刚刚切换,强制重置并使用新时间
+      if (this.justSwitched) {
+        console.log(`Heanup stringForTime歌曲刚切换 - 强制重置oldSeconds: ${this.oldSeconds} -> ${seconds}, 强制使用新时间`);
+        this.oldSeconds = seconds; // 直接使用新时间
+        this.justSwitched = false; // 重置标志
+        this.lastSwitchTime = Date.now(); // 记录切换时间
+      } else if (this.isSeekTo) {
+        // 如果是拖动进度条,直接使用新时间
+        console.log(`Heanup stringForTime拖动进度条 - 直接使用新时间: ${seconds}`);
+        this.oldSeconds = seconds;
       } else {
-        newSeconds = this.oldSeconds
+        // 正常播放时的防抖逻辑
+        // 检查是否在切换后的冷却期内(切换后5秒内允许更大的时间跳跃)
+        const timeSinceSwitch = this.lastSwitchTime ? Date.now() - this.lastSwitchTime : Number.MAX_VALUE;
+        const isInCooldown = timeSinceSwitch < 5000; // 5秒冷却期
+        
+        // 如果时间差值过大,根据情况处理
+        const timeDiff = Math.abs(seconds - this.oldSeconds);
+        
+        if (timeDiff > 10) {
+          // 如果在冷却期内,允许更大的时间跳跃(可能是新歌曲开始播放)
+          if (isInCooldown) {
+            console.log(`Heanup stringForTime切换后冷却期内检测到时间跳跃 - oldSeconds: ${this.oldSeconds}, newSeconds: ${seconds}, diff: ${timeDiff}, 允许跳跃`);
+            this.oldSeconds = seconds;
+          } else {
+            // 不在冷却期内,可能是异常情况,记录但使用新时间
+            console.log(`Heanup stringForTime检测到异常时间跳跃 - oldSeconds: ${this.oldSeconds}, newSeconds: ${seconds}, diff: ${timeDiff},直接使用新时间`);
+            this.oldSeconds = seconds;
+          }
+        } else if (this.oldSeconds <= seconds || seconds === 0) {
+          // 正常时间递进或重置为0
+          console.log(`Heanup stringForTime正常更新 - oldSeconds: ${this.oldSeconds} -> ${seconds}`);
+          this.oldSeconds = seconds;
+        } else {
+          // 时间倒退,使用防抖
+          console.log(`Heanup stringForTime防抖 - oldSeconds: ${this.oldSeconds}, newSeconds: ${seconds}, 使用oldSeconds`);
+          seconds = this.oldSeconds;
+        }
       }
     }
-    newSeconds = this.completionNum(newSeconds);
+
+    const hoursStr = this.completionNum(hours);
+    const minutesStr = this.completionNum(minutes);
+    const secondsStr = this.completionNum(seconds);
+
     if (hours > 0) {
-      return hours + ":" + minutes + ":" + newSeconds;
+      return `${hoursStr}:${minutesStr}:${secondsStr}`;
     } else {
-      return minutes + ":" + newSeconds;
+      return `${minutesStr}:${secondsStr}`;
     }
   }
 
+
+
   private setProgress() {
-    try {
-      // 优先从UnifiedPlayerService获取进度信息
-      const currentState = this.unifiedPlayerService.getCurrentState();
-      let position = currentState.currentPosition;
-      let duration = currentState.duration;
-      
-      let pos = 0;
-      if (duration > 0) {
-        this.slideEnable = true;
-        let curPercent = position / duration;
-        pos = curPercent * 100;
-        if (pos > this.PROGRESS_MAX_VALUE) {
-          this.progressValue = this.PROGRESS_MAX_VALUE
-        } else {
-          this.progressValue = pos;
-        }
+    let ijkPlayer=this.unifiedPlayerService.getIjkPlayer() as IjkMediaPlayer;
+    let position = ijkPlayer.getCurrentPosition();
+    let duration = ijkPlayer.getDuration();
+    let pos = 0;
+    if (duration > 0) {
+      this.slideEnable = true;
+      let curPercent = position / duration;
+      pos = curPercent * 100;
+      if (pos > this.PROGRESS_MAX_VALUE) {
+        this.progressValue = this.PROGRESS_MAX_VALUE
+      } else {
+        this.progressValue = pos;
       }
+    }
 
-      this.totalTime = this.stringForTime(duration);
-      if (position > duration) {
-        position = duration;
-      }
-      this.isCurrentTime = true;
-      
-      // 更新歌词位置
-      const lyricPosition = position + this.timeOffset * 1000;
-      this.lyricController.updatePosition(lyricPosition);
-      this.lyricControllerXF.updatePosition(lyricPosition);
-      this.lyricControllerSingle.updatePosition(lyricPosition);
 
-      this.currentTime = this.stringForTime(position);
-      this.isCurrentTime = false
+    // LogUtils.getInstance()
+    //   .LOGI("setProgress position:" + position + ",duration:" + duration + ",progressValue:" + pos);
+    this.totalTime = this.stringForTime(duration);
+    if (position > duration) {
+      position = duration;
+    }
+    this.isCurrentTime = true;
+    this.lyricController.updatePosition(position + this.timeOffset * 1000)
+    this.lyricControllerXF.updatePosition(position + this.timeOffset * 1000)
+    this.lyricControllerSingle.updatePosition(position + this.timeOffset * 1000)
 
-      // 检查播放状态以更新随机颜色和跳过逻辑
-      const isPlaying = currentState.isPlaying;
-      if (isPlaying) {
-        this.randomColor =
-          `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})`
+    this.currentTime = this.stringForTime(position);
+    this.isCurrentTime = false
 
-        // 判断是否播放到结束时间
-        if (this.isOpenJump && duration > this.jumpEndTime * 1000) {
-          if (position >= duration - this.jumpEndTime * 1000) {
-            this.playNext()
-          }
+
+    if (ijkPlayer.isPlaying()) {
+      this.randomColor =
+        `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})`
+
+      // 判断是否播放到结束时间
+      if (this.isOpenJump && duration > this.jumpEndTime * 1000) {
+        if (position >= duration - this.jumpEndTime * 1000) {
+          this.playNext()
+          this.broadcastProgressIfNeeded();
         }
-      } else {
-        this.randomColor = 'rbg(0,0,0)'
       }
 
-      // 节流广播进度更新到卡片
-      this.broadcastProgressIfNeeded();
-    } catch (error) {
-      LogUtils.getInstance().LOGI(`LocalMusic setProgress error: ${error}`);
+    } else {
+      this.randomColor = 'rbg(0,0,0)'
+
     }
+    // try {
+    //   // 优先从UnifiedPlayerService获取进度信息
+    //   const currentState = this.unifiedPlayerService.getCurrentState();
+    //   let position = currentState.currentPosition;
+    //   let duration = currentState.duration;
+    //
+    //   // 检测歌曲切换并重置播放位置
+    //   const currentSongPath = this.currentSong?.filePath || "";
+    //   if (this.lastSongPath !== currentSongPath && currentSongPath !== "") {
+    //     console.log(`Heanup setProgress检测到歌曲切换,重置position: ${position} -> 0`);
+    //     this.oldSeconds = 0;
+    //     this.currentTime = "00:00";
+    //     this.lastSongPath = currentSongPath;
+    //     position = 0; // 强制重置播放位置
+    //   }
+    //
+    //   let pos = 0;
+    //   if (duration > 0) {
+    //     this.slideEnable = true;
+    //     let curPercent = position / duration;
+    //     pos = curPercent * 100;
+    //     if (pos > this.PROGRESS_MAX_VALUE) {
+    //       this.progressValue = this.PROGRESS_MAX_VALUE
+    //     } else {
+    //       this.progressValue = pos;
+    //     }
+    //   }
+    //
+    //   this.totalTime = this.stringForTime(duration);
+    //   if (position > duration) {
+    //     position = duration;
+    //   }
+    //
+    //
+    //   // 更新歌词位置
+    //   const lyricPosition = position + this.timeOffset * 1000;
+    //   this.lyricController.updatePosition(lyricPosition);
+    //   this.lyricControllerXF.updatePosition(lyricPosition);
+    //   this.lyricControllerSingle.updatePosition(lyricPosition);
+    //
+    //   this.isCurrentTime = true;
+    //   this.currentTime = this.stringForTime(position);
+    //   this.isCurrentTime = false;
+    //
+    //   // 检查播放状态以更新随机颜色和跳过逻辑
+    //   const isPlaying = currentState.isPlaying;
+    //   if (isPlaying) {
+    //     this.randomColor =
+    //       `rgb(${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)},${Math.floor(Math.random() * 256)})`
+    //
+    //     // 判断是否播放到结束时间
+    //     if (this.isOpenJump && duration > this.jumpEndTime * 1000) {
+    //       if (position >= duration - this.jumpEndTime * 1000) {
+    //         this.playNext()
+    //       }
+    //     }
+    //   } else {
+    //     this.randomColor = 'rbg(0,0,0)'
+    //   }
+    //
+    //   // 节流广播进度更新到卡片
+    //   this.broadcastProgressIfNeeded();
+    // } catch (error) {
+    //   LogUtils.getInstance().LOGI(`LocalMusic setProgress error: ${error}`);
+    // }
   }
 
   private startProgressTask() {
@@ -10106,16 +10272,6 @@ export struct LocalMusic {
     this.replayVisible = Visibility.None;
   }
 
-  private hideLoadIng() {
-    this.loadingVisible = Visibility.None;
-    this.replayVisible = Visibility.None;
-  }
-
-  private showRePlay() {
-    this.loadingVisible = Visibility.None;
-    this.replayVisible = Visibility.Visible;
-  }
-
   // 原来的 play 方法已移除,播放逻辑现在由 UnifiedPlayerService 统一处理
   // private async play(url: string) { ... } 已移除
 
@@ -10148,25 +10304,6 @@ export struct LocalMusic {
 
   }
 
-  public async setAvSessionListener() {
-    if (!this.avSessionController) {
-      return;
-    }
-    this.avSessionController.getAvSession()?.on('play', this.sessionPlayCallback);
-    this.avSessionController.getAvSession()?.on('pause', this.sessionPauseCallback);
-    this.avSessionController.getAvSession()?.on('stop', this.sessionStopCallback);
-    this.avSessionController.getAvSession()?.on('playNext', this.sessionPlayNextCallback);
-    this.avSessionController.getAvSession()?.on('playPrevious', this.sessionPlayPreviousCallback);
-    this.avSessionController.getAvSession()?.on('fastForward', this.sessionFastForwardCallback);
-    this.avSessionController.getAvSession()?.on('rewind', this.sessionRewindCallback);
-    this.avSessionController.getAvSession()?.on('seek', this.sessionSeekCallback);
-    this.avSessionController.getAvSession()?.on('setLoopMode', this.sessionSetLoopModeCallback);
-    this.avSessionController.getAvSession()?.on('toggleFavorite', this.sessionToggleFavoriteCallback);
-
-    this.avSessionController.getAvSession()?.on('outputDeviceChange', this.sessionOutputDeviceChange)
-
-  }
-
   setLoopMode() {
     let itype = this.playType + 1
     if (itype >= 4) {
@@ -10538,14 +10675,14 @@ export struct LocalMusic {
       const currentState = this.unifiedPlayerService.getCurrentState();
       const curPosition = currentState.currentPosition;
       let seeTime = curPosition + time * 1000;
-      
+
       // 限制 seekValue 在合法范围内
       if (seeTime < 0) {
         seeTime = 0;
       } else if (seeTime > currentState.duration) {
         seeTime = currentState.duration;
       }
-      
+
       Logger.info('onecold seeTime= ' + seeTime)
       this.setSeekToActionProgress(seeTime)
       this.seekTo(seeTime + "")
@@ -10581,7 +10718,7 @@ export struct LocalMusic {
     }
     this.isCurrentTime = true;
     this.currentTime = this.stringForTime(position);
-    this.isCurrentTime = false
+    this.isCurrentTime = false;
   }
 
   private sessionRewindCallback = (time?: number) => {
@@ -10616,35 +10753,50 @@ export struct LocalMusic {
   }
 
   private async pause() {
-    try {
-      // 使用UnifiedPlayerService暂停播放
-      await this.unifiedPlayerService.pause();
-      
-      // 保持原有的UI更新逻辑
+
+    if (this.unifiedPlayerService.getIjkPlayer()?.isPlaying()){
+      this.savePlaybackPosition();
+      this.unifiedPlayerService.pause();
       this.setProgress();
       this.mDestroyPage = true;
       this.CONTROL_PlayStatus = PlayStatus.PAUSE;
-      this.setIsPlaying(false);
-      this.updateSessionPlayState(false);
+      this.updateSessionPlayState(false)
       this.playChange()
-      
       if (this.pipController) {
         this.pipController.updatePiPControlStatus(PiPWindow.PiPControlType.VIDEO_PLAY_PAUSE,
           PiPWindow.PiPControlStatus.PAUSE);
       }
-      
-      LogUtils.getInstance().LOGI("LocalMusic: pause completed via UnifiedPlayerService");
-    } catch (error) {
-      LogUtils.getInstance().LOGI(`LocalMusic pause error: ${error}`);
-      ToastUtil.showToast(`暂停失败: ${error}`);
     }
+
+    // try {
+    //   // 使用UnifiedPlayerService暂停播放
+    //   await this.unifiedPlayerService.pause();
+    //
+    //   // 保持原有的UI更新逻辑
+    //   this.setProgress();
+    //   this.mDestroyPage = true;
+    //   this.CONTROL_PlayStatus = PlayStatus.PAUSE;
+    //   this.setIsPlaying(false);
+    //   this.updateSessionPlayState(false);
+    //   this.playChange()
+    //
+    //   if (this.pipController) {
+    //     this.pipController.updatePiPControlStatus(PiPWindow.PiPControlType.VIDEO_PLAY_PAUSE,
+    //       PiPWindow.PiPControlStatus.PAUSE);
+    //   }
+    //
+    //   LogUtils.getInstance().LOGI("LocalMusic: pause completed via UnifiedPlayerService");
+    // } catch (error) {
+    //   LogUtils.getInstance().LOGI(`LocalMusic pause error: ${error}`);
+    //   ToastUtil.showToast(`暂停失败: ${error}`);
+    // }
   }
 
   private async stop() {
     try {
       // 使用UnifiedPlayerService停止播放
       await this.unifiedPlayerService.stop();
-      
+
       // 保持原有的UI更新逻辑
       this.stopProgressTask();
       this.CONTROL_PlayStatus = PlayStatus.INIT;
@@ -10652,7 +10804,7 @@ export struct LocalMusic {
       this.updateSessionPlayState(false)
       this.playChange()
       this.watchStatus();
-      
+
       LogUtils.getInstance().LOGI("LocalMusic: stop completed via UnifiedPlayerService");
     } catch (error) {
       LogUtils.getInstance().LOGI(`LocalMusic stop error: ${error}`);
@@ -10671,7 +10823,7 @@ export struct LocalMusic {
 
       // 如果播放位置接近视频末尾,则保存 position 为 0
       const playbackPosition = (duration - position < threshold) ? 0 : position;
-      
+
       // 同时保存到PreferencesUtil和AppStorage,确保卡片也能访问
       PreferencesUtil.putSync(this.videoUrl, playbackPosition);
       AppStorage.setOrCreate(`playback_${this.videoUrl}`, playbackPosition);
@@ -10689,7 +10841,7 @@ export struct LocalMusic {
     if (position === 0) {
       position = PreferencesUtil.getNumberSync(this.videoUrl, 0);
     }
-    
+
     // ToastUtil.showToast('position = ' + position)
     if (position > 0) {
       // ToastUtil.showToast('seekTo = ' + position)
@@ -10702,14 +10854,14 @@ export struct LocalMusic {
     try {
       // 使用UnifiedPlayerService进行拖动
       await this.unifiedPlayerService.seekTo(value);
-      
+
       // 保持原有的UI更新逻辑
       this.setProgress()
-      
+
       LogUtils.getInstance().LOGI(`LocalMusic: seekTo ${value} completed via UnifiedPlayerService`);
     } catch (error) {
       LogUtils.getInstance().LOGI(`LocalMusic seekTo error: ${error}`);
-      
+
       // 如果是WMA格式错误,显示特定提示
       if (error.toString().includes('WMA format')) {
         ToastUtil.showToast('wma格式不支持拖动快进。');
@@ -10731,7 +10883,7 @@ export struct LocalMusic {
         return
       }
     }
-    
+
     try {
       // 如果未开始播放或队列为空
       if (this.curIndex === -1 || this.songList.length === 0) {
@@ -10743,24 +10895,24 @@ export struct LocalMusic {
 
       // 插入到当前索引+1的位置
       const insertPos = this.curIndex + 1;
-      
+
       // 使用UnifiedPlayerService添加到播放列表
       this.unifiedPlayerService.addToPlaylist(song, insertPos);
-      
+
       // 更新本地播放列表
       this.songList.splice(insertPos, 0, song);
       this.songList = [...this.songList]; // 触发状态更新
       this.sonDataSource.pushArrayData(this.songList);
-      
+
       // 同步到AppStorage
       AppStorage.setOrCreate('songList', this.songList);
-      
+
       ToastUtil.showToast('已添加至下一首播放')
-      
+
       LogUtils.getInstance().LOGI(`LocalMusic: Added song to next play via UnifiedPlayerService - ${song.name}`);
     } catch (error) {
       LogUtils.getInstance().LOGI(`LocalMusic addToNextPlay error: ${error}`);
-      
+
       // 错误处理:回退到原有逻辑
       const insertPos = this.curIndex + 1;
       this.songList.splice(insertPos, 0, song);
@@ -10781,7 +10933,7 @@ export struct LocalMusic {
         this.randomPlay()
         return;
       }
-      
+
       if (ArrayUtil.isNotEmpty(this.songList)) {
         // 确保播放列表已同步到UnifiedPlayerService
         this.unifiedPlayerService.setPlaylist(this.songList, this.curIndex);
@@ -10801,6 +10953,13 @@ export struct LocalMusic {
           this.name = currentSong.name;
           this.cover = currentSong.pixelMapPath;
 
+          // 重置时间显示状态,防止新歌曲时间显示被上一首歌曲的时间"卡住"
+          this.oldSeconds = 0;
+          this.currentTime = "00:00";
+          this.lastSongPath = currentSong.filePath;
+          this.justSwitched = true; // 标记歌曲刚刚切换
+          console.log(`Heanup playNext - 重置时间显示状态: oldSeconds=${this.oldSeconds}, currentTime=${this.currentTime}`);
+
           // 同步到AppStorage,确保卡片能获取到最新状态
           // AppStorage.setOrCreate('songList', this.songList);
           // AppStorage.setOrCreate('currIndex', this.curIndex);
@@ -10984,6 +11143,13 @@ export struct LocalMusic {
           this.artist = currentSong.artist;
           this.cover = currentSong.pixelMapPath;
           
+          // 重置时间显示状态,防止新歌曲时间显示被上一首歌曲的时间"卡住"
+          this.oldSeconds = 0;
+          this.currentTime = "00:00";
+          this.lastSongPath = currentSong.filePath;
+          this.justSwitched = true; // 标记歌曲刚刚切换
+          console.log(`Heanup playPrevious - 重置时间显示状态: oldSeconds=${this.oldSeconds}, currentTime=${this.currentTime}`);
+          
           // 同步到AppStorage,确保卡片能获取到最新状态
           AppStorage.setOrCreate('songList', this.songList);
           AppStorage.setOrCreate('currIndex', this.curIndex);

+ 0 - 1
entry/src/main/ets/view/TitleBar.ets

@@ -509,7 +509,6 @@ export namespace TitleBar {
 
     setTitleBarBackground(value: ResourceColor): Model {
       this.titleBarBackground = value;
-      console.log('Heanup: TitleBar背景色:'+JSON.stringify(value))
       return this;
     }
 

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff