Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/feature/桌面卡片-抽离ijkplayer播放控制' into feature/桌面卡片-抽离ijkplayer播放控制

chendeben 1 anno fa
parent
commit
cf5dcff82c
17 ha cambiato i file con 1690 aggiunte e 855 eliminazioni
  1. 1 2
      entry/src/main/ets/common/constants/CommonConstants.ets
  2. 82 13
      entry/src/main/ets/common/service/PlayerManager.ets
  3. 6 1
      entry/src/main/ets/common/service/PlayerStateModel.ets
  4. 605 116
      entry/src/main/ets/common/service/UnifiedPlayerService.ets
  5. 380 50
      entry/src/main/ets/common/widget/EnhancedFormUpdateService.ets
  6. 8 357
      entry/src/main/ets/common/widget/PlayerControlService.ets
  7. 10 0
      entry/src/main/ets/common/widget/WidgetTypes.ets
  8. 139 26
      entry/src/main/ets/controller/AvSessionController.ets
  9. 221 19
      entry/src/main/ets/entryability/EntryAbility.ets
  10. 238 271
      entry/src/main/ets/entryformability/EntryFormAbility.ets
  11. BIN
      oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/.DS_Store
  12. BIN
      oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/media/.DS_Store
  13. BIN
      oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/.DS_Store
  14. BIN
      oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/media/.DS_Store
  15. BIN
      oh_modules/.ohpm/@simplepeng+spider-man@1.0.1/oh_modules/@simplepeng/spider-man/.DS_Store
  16. BIN
      oh_modules/.ohpm/oh_modules/@simplepeng/spider-man/.DS_Store
  17. BIN
      oh_modules/@simplepeng/spider-man/.DS_Store

+ 1 - 2
entry/src/main/ets/common/constants/CommonConstants.ets

@@ -13,7 +13,6 @@
  * limitations under the License.
  */
 
-import { SettingPage } from '../../pages/SettingPage';
 import { VideoSpeed } from '../../viewmodel/VideoSpeed';
 
 /**
@@ -21,7 +20,7 @@ import { VideoSpeed } from '../../viewmodel/VideoSpeed';
  */
 export class CommonConstants {
 
-  static readonly DEFAULT_THEME_COLOR: string = SettingPage.THEME_COLOR_LIST[0].color
+  static readonly DEFAULT_THEME_COLOR: string = '#FF4081' // 玫瑰粉,避免循环依赖
 
   static readonly OPEN_DATE: string = '2025-06-10';
 

+ 82 - 13
entry/src/main/ets/common/service/PlayerManager.ets

@@ -9,7 +9,6 @@ import {
 } from '@ohos/ijkplayer';
 import { common } from '@kit.AbilityKit';
 import { PreferencesUtil } from '@pura/harmony-utils';
-import { SettingPage } from '../../pages/SettingPage';
 
 /**
  * 播放器状态回调接口
@@ -39,10 +38,13 @@ export interface IPlayerManager {
   startPlayOrResumePlay(): Promise<void>;
   pausePlayback(): void;
   stopPlayback(): void;
-  seekToPosition(position: string): void;
+  seekToPosition(position: string): Promise<void>;
   setPlaybackSpeed(speed: string): void;
   setVolume(leftVolume: string, rightVolume: string): void;
   
+  // 状态查询
+  isPausedState(): boolean;
+  
   // 清理资源
   release(): void;
 }
@@ -57,6 +59,7 @@ export class PlayerManager implements IPlayerManager {
   private mContext: common.UIAbilityContext | null = null;
   private audioInterruptCallback: ((event: InterruptEvent) => void) | null = null;
   private stateCallback: PlayerStateCallback | null = null;
+  private isPaused: boolean = false; // 跟踪暂停状态
   
   private constructor() {
     this.mIjkMediaPlayer = IjkMediaPlayer.getInstance();
@@ -154,10 +157,18 @@ export class PlayerManager implements IPlayerManager {
       onPrepared: () => {
         LogUtils.getInstance().LOGI('PlayerManager: Player prepared, starting playback');
         try {
-          this.mIjkMediaPlayer.start();
-          LogUtils.getInstance().LOGI('PlayerManager: Playback started after prepared');
+          // 只有在非暂停状态下才自动开始播放
+          // 如果当前是暂停状态,仅通知准备完成,不自动开始播放
+          if (!this.isPaused) {
+            this.mIjkMediaPlayer.start();
+            LogUtils.getInstance().LOGI('PlayerManager: Playback started after prepared');
+            this.stateCallback?.onPlaybackStarted();
+          } else {
+            LogUtils.getInstance().LOGI('PlayerManager: Player prepared but in paused state, not auto-starting');
+          }
+          
+          // 总是通知准备完成
           this.stateCallback?.onPrepared();
-          this.stateCallback?.onPlaybackStarted();
         } catch (error) {
           LogUtils.getInstance().LOGI(`PlayerManager: Failed to start after prepared: ${error}`);
           this.stateCallback?.onPlaybackError(-1, -1);
@@ -207,10 +218,32 @@ export class PlayerManager implements IPlayerManager {
         return;
       }
       
+      const currentPosition = this.mIjkMediaPlayer.getCurrentPosition();
+      const duration = this.mIjkMediaPlayer.getDuration();
+      const wasPaused = this.isPaused;
+      
+      LogUtils.getInstance().LOGI(`PlayerManager: Starting/resuming playback (isPaused: ${wasPaused}, position: ${currentPosition}ms, duration: ${duration}ms)`);
+      
       // 对于暂停后的恢复播放,直接调用start()
       // 对于新的播放,需要先调用prepareAsync(),在onPrepared回调中自动开始播放
       this.mIjkMediaPlayer.start();
-      LogUtils.getInstance().LOGI('PlayerManager: Playback started/resumed');
+      
+      if (wasPaused) {
+        // 从暂停状态恢复,清除暂停标记
+        this.isPaused = false;
+        LogUtils.getInstance().LOGI(`PlayerManager: Resumed from paused state at position ${currentPosition}ms`);
+      } else {
+        LogUtils.getInstance().LOGI('PlayerManager: Started new playback');
+      }
+      
+      // 验证播放是否真正开始
+      setTimeout(() => {
+        const isNowPlaying = this.mIjkMediaPlayer.isPlaying();
+        const newPosition = this.mIjkMediaPlayer.getCurrentPosition();
+        LogUtils.getInstance().LOGI(`PlayerManager: Playback verification - isPlaying: ${isNowPlaying}, position: ${newPosition}ms`);
+      }, 100);
+      
+      LogUtils.getInstance().LOGI('PlayerManager: Playback started/resumed successfully');
     } catch (error) {
       LogUtils.getInstance().LOGI(`PlayerManager startPlayOrResumePlay error: ${error}`);
       throw new Error(`Failed to start playback: ${error}`);
@@ -219,10 +252,13 @@ export class PlayerManager implements IPlayerManager {
 
   pausePlayback(): void {
     try {
-      if (this.mIjkMediaPlayer.isPlaying()) {
-        this.mIjkMediaPlayer.pause();
-        LogUtils.getInstance().LOGI('PlayerManager: Playback paused');
-      }
+      // 先设置暂停标志,确保状态优先级
+      this.isPaused = true;
+      
+      // 无论播放器报告的状态如何,都尝试暂停
+      this.mIjkMediaPlayer.pause();
+      
+      LogUtils.getInstance().LOGI('PlayerManager: Playback paused, isPaused flag set to true');
     } catch (error) {
       LogUtils.getInstance().LOGI(`PlayerManager pausePlayback error: ${error}`);
     }
@@ -231,18 +267,21 @@ export class PlayerManager implements IPlayerManager {
   stopPlayback(): void {
     try {
       this.mIjkMediaPlayer.stop();
-      this.mIjkMediaPlayer.release();
+      this.isPaused = false; // 清除暂停状态
+      // 注意:不要在这里调用release(),因为这会释放播放器资源
+      // release()应该只在真正需要释放资源时调用(如应用退出)
       LogUtils.getInstance().LOGI('PlayerManager: Playback stopped');
     } catch (error) {
       LogUtils.getInstance().LOGI(`PlayerManager stopPlayback error: ${error}`);
     }
   } 
- seekToPosition(position: string): void {
+ async seekToPosition(position: string): Promise<void> {
     try {
       this.mIjkMediaPlayer.seekTo(position);
       LogUtils.getInstance().LOGI(`PlayerManager: Seeked to position ${position}`);
     } catch (error) {
       LogUtils.getInstance().LOGI(`PlayerManager seekToPosition error: ${error}`);
+      throw new Error(`Failed to seek to position: ${error}`);
     }
   }
 
@@ -264,6 +303,31 @@ export class PlayerManager implements IPlayerManager {
     }
   }
 
+  isPausedState(): boolean {
+    try {
+      // 多重检查确保暂停状态的准确性
+      const internalPausedFlag = this.isPaused;
+      const playerIsPlaying = this.mIjkMediaPlayer.isPlaying();
+      const hasDuration = this.mIjkMediaPlayer.getDuration() > 0;
+      
+      // 如果内部标记为暂停,直接返回true(优先级最高)
+      if (internalPausedFlag) {
+        LogUtils.getInstance().LOGI(`PlayerManager isPausedState: internal=${internalPausedFlag}, isPlaying=${playerIsPlaying}, hasDuration=${hasDuration}, result=true (internal priority)`);
+        return true;
+      }
+      
+      // 如果播放器有时长但没有播放,也认为是暂停状态(但要排除加载中的情况)
+      const playerNotPlayingButReady = !playerIsPlaying && hasDuration;
+      
+      LogUtils.getInstance().LOGI(`PlayerManager isPausedState: internal=${internalPausedFlag}, isPlaying=${playerIsPlaying}, hasDuration=${hasDuration}, result=${playerNotPlayingButReady}`);
+      
+      return playerNotPlayingButReady;
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`PlayerManager isPausedState error: ${error}`);
+      return this.isPaused; // 发生错误时返回内部标记
+    }
+  }
+
   release(): void {
     try {
       // 移除音频中断监听
@@ -274,7 +338,12 @@ export class PlayerManager implements IPlayerManager {
       
       // 停止播放并释放资源
       this.mIjkMediaPlayer.setScreenOnWhilePlaying(false);
-      this.stopPlayback();
+      
+      // 先停止播放
+      this.mIjkMediaPlayer.stop();
+      
+      // 然后释放播放器资源
+      this.mIjkMediaPlayer.release();
       
       LogUtils.getInstance().LOGI('PlayerManager: Resources released');
     } catch (error) {

+ 6 - 1
entry/src/main/ets/common/service/PlayerStateModel.ets

@@ -126,12 +126,17 @@ export class PlayerStateModel {
    * 更新播放状态
    */
   updatePlayingState(isPlaying: boolean): void {
+    const wasPlaying = this.state.isPlaying;
+    const wasPaused = this.state.isPaused;
+    
     if (this.state.isPlaying !== isPlaying) {
       this.state.isPlaying = isPlaying;
       this.state.isPaused = !isPlaying;
       this.state.isLoading = false;
+      
+      LogUtils.getInstance().LOGI(`PlayerStateModel: Playing state updated from ${wasPlaying} to ${isPlaying}, paused from ${wasPaused} to ${!isPlaying}`);
+      
       this.notifyStateChanged();
-      LogUtils.getInstance().LOGI(`PlayerStateModel: Playing state updated to ${isPlaying}`);
     }
   }
 

+ 605 - 116
entry/src/main/ets/common/service/UnifiedPlayerService.ets

@@ -10,6 +10,8 @@ import { DataPersistenceService, PlaylistSyncService, PlaylistSyncListener, IDat
 import { StateSyncService, IStateSyncService, StateChangeCallback, WidgetControlCallback } from './StateSyncService';
 import { ErrorRecoveryStrategy, IErrorRecoveryStrategy, ErrorContext, ErrorRecoveryAction } from './ErrorRecoveryStrategy';
 import { EnhancedFormUpdateService, UpdateStats } from '../widget/EnhancedFormUpdateService';
+import { AvSessionController } from '../../controller/AvSessionController';
+import { avSession } from '@kit.AVSessionKit';
 import json from '@ohos.util.json';
 
 /**
@@ -75,11 +77,13 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
   private stateSync: IStateSyncService;
   private errorRecovery: IErrorRecoveryStrategy;
   private widgetUpdateService: EnhancedFormUpdateService;
+  private avSessionController: AvSessionController | null = null; // 新增:AVSession控制器
   private context: common.UIAbilityContext | null = null;
   private progressTimer: number = -1;
   private isInitialized: boolean = false;
   private isDataRestored: boolean = false; // 新增:数据恢复完成标识
   private currentRetryCount: number = 0;
+  private lastAvSessionUpdate: number = 0; // 新增:上次AVSession更新时间
 
   private constructor() {
     this.playerManager = PlayerManager.getInstance();
@@ -108,23 +112,12 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     }
 
     try {
-      console.log("Heanup2 UnifiedPlayerService: 开始初始化服务");
+      console.log("Heanup2 UnifiedPlayerService: 开始快速初始化服务");
       this.context = context;
       
-      // 初始化各个服务
-      await this.playerManager.initialize(context);
-      
-      // 设置播放器状态回调
+      // 快速初始化核心组件
       this.playerManager.setStateCallback(this);
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: PlayerManager state callback set');
-      
-      await this.dataPersistence.initialize(context);
-      await this.playlistSync.initialize(context);
-      await this.stateSync.initialize(context);
-      
-      // 初始化卡片更新服务
       this.widgetUpdateService.setAppContext(context);
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Widget update service initialized');
       
       // 设置同步监听器
       this.playlistSync.addSyncListener(this);
@@ -145,11 +138,20 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         
         onStateChanged(state: PlayerState): void {
           this.stateSync.broadcastState(state);
+          // 状态变化时更新AVSession
+          this.unifiedService.updateSessionPlayState(state.isPlaying);
           // 状态变化时更新卡片
           this.unifiedService.updateWidgetsForStateChange(state);
         }
         onSongChanged(song: VideoItem): 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);
         }
@@ -165,19 +167,54 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       const stateListener = new StateListenerImpl(this.stateSync, this.widgetUpdateService, this);
       this.stateModel.addStateListener(stateListener);
       
-      // 恢复保存的状态
-      await this.restorePersistedState();
-      
       this.setupProgressTimer();
       this.isInitialized = true;
       
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Initialized successfully');
+      // 异步初始化耗时组件,避免阻塞
+      this.initializeHeavyComponentsAsync(context);
+      
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: Core initialization completed');
     } catch (error) {
       LogUtils.getInstance().LOGI(`UnifiedPlayerService initialization error: ${error}`);
-      throw new Error;
+      throw new Error(`初始化失败: ${error}`);
     }
   }
 
+  /**
+   * 异步初始化耗时组件
+   */
+  private initializeHeavyComponentsAsync(context: common.UIAbilityContext): void {
+    setTimeout(async () => {
+      try {
+        console.log("Heanup2 UnifiedPlayerService: 开始异步初始化耗时组件");
+        
+        // 并行初始化各个服务以提高效率
+        const initPromises = [
+          this.playerManager.initialize(context),
+          this.dataPersistence.initialize(context),
+          this.playlistSync.initialize(context),
+          this.stateSync.initialize(context)
+        ];
+        
+        await Promise.all(initPromises);
+        
+        // 初始化AVSession控制器
+        this.initializeAvSession();
+        
+        // 恢复保存的状态
+        await this.restorePersistedState();
+        
+        console.log("Heanup2 UnifiedPlayerService: 异步组件初始化完成");
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Heavy components initialized');
+      } catch (error) {
+        console.log(`Heanup2 UnifiedPlayerService: 异步组件初始化失败: ${error}`);
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService heavy components init error: ${error}`);
+        // 即使失败也设置数据恢复完成,避免无限等待
+        this.isDataRestored = true;
+      }
+    }, 50); // 短延迟,让主初始化先完成
+  }
+
   // 播放控制方法
   async startPlayOrResumePlay(): Promise<void> {
     try {
@@ -228,20 +265,81 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         return;
       }
 
-      // 如果是暂停状态,直接恢复播放
-      if (this.stateModel.getState().isPaused && !this.stateModel.getState().isLoading) {
-        await this.playerManager.startPlayOrResumePlay();
-        this.stateModel.updatePlayingState(true);
-        this.startProgressTimer();
-        
-        // 保存播放状态变化
-        this.saveCurrentState();
-        
-        // 更新卡片显示播放状态
-        await this.updateWidgetsForPlayStateChange(true);
-        
+      // 检查播放器状态,优先处理暂停恢复情况
+      const ijkPlayer = this.playerManager.getIjkPlayer();
+      const isPausedByManager = this.playerManager.isPausedState();
+      const isCurrentlyPlaying = ijkPlayer ? ijkPlayer.isPlaying() : false;
+      const currentPlayerState = this.stateModel.getState();
+      
+      console.log(`Heanup2 UnifiedPlayerService: 播放器状态检查 - isPausedByManager: ${isPausedByManager}, isCurrentlyPlaying: ${isCurrentlyPlaying}, stateIsPlaying: ${currentPlayerState.isPlaying}, isPaused: ${currentPlayerState.isPaused}`);
+      
+      // 更严格的暂停状态检查:
+      // 1. PlayerManager明确标记为暂停状态,AND
+      // 2. 播放器当前不在播放状态,AND
+      // 3. 播放器有有效的数据源(时长 > 0),AND
+      // 4. 状态模型显示为暂停状态或非播放状态
+      const shouldResumeFromPause = isPausedByManager && 
+        !isCurrentlyPlaying && 
+        ijkPlayer && 
+        ijkPlayer.getDuration() > 0 && 
+        (currentPlayerState.isPaused || !currentPlayerState.isPlaying);
+      
+      // 额外检查:如果播放器正在播放,绝对不应该进入暂停恢复逻辑
+      if (isCurrentlyPlaying) {
+        console.log("Heanup2 UnifiedPlayerService: 播放器正在播放,跳过暂停恢复检查");
+        // 直接返回,不做任何操作,避免重置播放器
+        this.stateModel.updateLoadingState(false);
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Player already playing, no action needed');
         return;
       }
+      
+      if (shouldResumeFromPause && ijkPlayer) {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Resuming from paused state');
+        console.log("Heanup2 UnifiedPlayerService: 检测到暂停状态,准备恢复播放");
+        
+        try {
+          // 检查播放器是否已经有数据源
+          const currentPosition = ijkPlayer.getCurrentPosition();
+          const duration = ijkPlayer.getDuration();
+          console.log(`Heanup2 UnifiedPlayerService: 当前播放位置 ${currentPosition}ms, 总时长 ${duration}ms`);
+          
+          // 只要播放器有有效的时长信息,就说明已经准备好,可以直接恢复
+          if (duration > 0) {
+            console.log("Heanup2 UnifiedPlayerService: 播放器已准备,直接恢复播放");
+            
+            // 更新加载状态为false(恢复播放不需要加载)
+            this.stateModel.updateLoadingState(false);
+            
+            // 直接恢复播放,不需要重新准备
+            await this.playerManager.startPlayOrResumePlay();
+            
+            // 手动更新播放状态
+            this.stateModel.updatePlayingState(true);
+            
+            // 启动进度定时器
+            this.startProgressTimer();
+            
+            // 立即更新一次进度,确保UI显示正确的当前位置
+            setTimeout(() => {
+              this.updateProgress();
+            }, 100);
+            
+            // 保存播放状态变化
+            this.saveCurrentState();
+            
+            // 更新AVSession播放状态
+            setTimeout(() => {
+              this.updateSessionPlayState(true);
+            }, 200);
+            
+            // 更新卡片显示播放状态
+            await this.updateWidgetsForPlayStateChange(true);
+            return;
+          }
+        } catch (error) {
+          LogUtils.getInstance().LOGI(`UnifiedPlayerService: Resume from pause failed: ${error}, will re-prepare player`);
+        }
+      }
 
       // 检查文件是否存在(对于本地文件)
       if (!currentSong.filePath.startsWith('http')) {
@@ -265,23 +363,22 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       // 准备播放器
       const preparedPlayer = this.playerManager.getIjkPlayer();
       if (preparedPlayer) {
-        LogUtils.getInstance().LOGI(`UnifiedPlayerService: Preparing async for ${currentSong.name}`);
         preparedPlayer.prepareAsync();
         // 注意:实际播放和状态更新会在 onPrepared 回调中开始
       }
       
+      // 更新AVSession元数据
+      await this.updateAvSessionMetadata(currentSong);
+      
       // 恢复播放位置(如果有记忆播放功能)
       this.restorePlaybackPosition(currentSong);
       
       // 重置重试计数(播放成功)
       this.currentRetryCount = 0;
       
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Started playing ${currentSong.name}`);
     } catch (error) {
       this.stateModel.updateLoadingState(false);
       this.stateModel.updatePlayingState(false);
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService startPlayOrResumePlay error: ${error}`);
-      
       // 使用错误恢复机制处理错误
       await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
     }
@@ -295,9 +392,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     if (!song) {
       throw new Error('No song provided for direct play');
     }
-    
-    LogUtils.getInstance().LOGI(`UnifiedPlayerService: Starting direct play for ${song.name}`);
-    
+
     this.stateModel.updateLoadingState(true);
     
     const playerInstance = this.playerManager.getIjkPlayer();
@@ -319,37 +414,44 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     // 准备播放器
     const preparedPlayer = this.playerManager.getIjkPlayer();
     if (preparedPlayer) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Preparing async for ${song.name}`);
       preparedPlayer.prepareAsync();
       // 注意:实际播放和状态更新会在 onPrepared 回调中开始
     }
-    
-    // 新歌曲不需要恢复播放位置,从头开始播放
-    // this.restorePlaybackPosition(song); // 注释掉这行
-    
     // 重置重试计数
     this.currentRetryCount = 0;
-    
-    LogUtils.getInstance().LOGI(`UnifiedPlayerService: Started direct playing ${song.name}`);
   }
 
   async pause(): Promise<void> {
     try {
+
+      const ijkPlayer = this.playerManager.getIjkPlayer();
+      
+      // 保存当前播放位置
       this.savePlaybackPosition();
+      
+      // 暂停播放器 - 确保先暂停播放器
       this.playerManager.pausePlayback();
+      
+      // 立即更新状态模型为暂停状态,确保状态同步
       this.stateModel.updatePlayingState(false);
+      
+      // 停止进度定时器
       this.stopProgressTimer();
       
+      // 等待一小段时间确保播放器状态稳定
+      await new Promise<void>(resolve => setTimeout(resolve, 50));
+      
       // 保存播放状态变化
       this.saveCurrentState();
       
+      // 立即更新AVSession播放状态
+      this.updateSessionPlayState(false);
+      
       // 更新卡片显示暂停状态
       await this.updateWidgetsForPlayStateChange(false);
-      
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback paused');
+
     } catch (error) {
       LogUtils.getInstance().LOGI(`UnifiedPlayerService pause error: ${error}`);
-      throw new Error;
     }
   }
 
@@ -361,7 +463,6 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       this.stateModel.updateProgress(0, 0);
       this.stopProgressTimer();
       
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback stopped');
     } catch (error) {
       LogUtils.getInstance().LOGI(`UnifiedPlayerService stop error: ${error}`);
       throw new Error;
@@ -380,11 +481,9 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         throw new Error('WMA format does not support seeking');
       }
 
-      this.playerManager.seekToPosition(position);
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Seeked to position ${position}`);
+      await this.playerManager.seekToPosition(position);
     } catch (error) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService seekTo error: ${error}`);
-      throw new Error;
+      throw new Error(`Failed to seek to position: ${error}`);
     }
   }
 
@@ -394,18 +493,10 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       const playMode = this.stateModel.getState().playMode;
       
       if (!this.playlistModel.hasNext(playMode)) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService: No next song available');
         return;
       }
-
-      // 先获取当前歌曲信息用于日志
-      const currentSong = this.playlistModel.getCurrentSong();
-      const currentIndex = this.playlistModel.getCurrentIndex();
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Moving from index ${currentIndex} (${currentSong?.name || 'unknown'})`);
-
       const moved = this.playlistModel.moveToNext(playMode);
       if (!moved) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService: Failed to move to next song');
         return;
       }
 
@@ -415,7 +506,6 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       this.stateModel.updateCurrentIndex(newIndex);
       
       if (newSong) {
-        LogUtils.getInstance().LOGI(`UnifiedPlayerService: Moved to index ${newIndex} (${newSong.name})`);
         this.stateModel.updateCurrentSong(newSong);
       }
       
@@ -433,9 +523,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         await this.updateWidgetsForSongChange(newSong, true);
       }
       
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Moved to next song');
     } catch (error) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService playNext error: ${error}`);
       await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
     }
   }
@@ -445,18 +533,15 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       const playMode = this.stateModel.getState().playMode;
       
       if (!this.playlistModel.hasPrevious(playMode)) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService: No previous song available');
         return;
       }
 
       // 先获取当前歌曲信息用于日志
       const currentSong = this.playlistModel.getCurrentSong();
       const currentIndex = this.playlistModel.getCurrentIndex();
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Moving from index ${currentIndex} (${currentSong?.name || 'unknown'})`);
 
       const moved = this.playlistModel.moveToPrevious(playMode);
       if (!moved) {
-        LogUtils.getInstance().LOGI('UnifiedPlayerService: Failed to move to previous song');
         return;
       }
 
@@ -466,7 +551,6 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       this.stateModel.updateCurrentIndex(newIndex);
       
       if (newSong) {
-        LogUtils.getInstance().LOGI(`UnifiedPlayerService: Moved to index ${newIndex} (${newSong.name})`);
         this.stateModel.updateCurrentSong(newSong);
       }
       
@@ -484,9 +568,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         await this.updateWidgetsForSongChange(newSong, true);
       }
       
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Moved to previous song');
     } catch (error) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService playPrevious error: ${error}`);
       await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
     }
   }
@@ -512,9 +594,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         this.stateModel.updateCurrentSong(currentSong);
       }
       
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Playing song at index ${index}`);
     } catch (error) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService playSongAtIndex error: ${error}`);
       throw new Error;
     }
   }
@@ -664,6 +744,12 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       // 保存当前状态
       this.saveCurrentState();
       
+      // 清理AVSession
+      if (this.avSessionController) {
+        this.avSessionController.unregisterSessionListener();
+        this.avSessionController = null;
+      }
+      
       // 清理同步监听器
       this.playlistSync.removeSyncListener(this);
       this.playlistSync.release();
@@ -681,6 +767,130 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     }
   }
 
+  // ==================== AVSession 控制方法 ====================
+  
+  /**
+   * 初始化AVSession
+   * 按照官方文档的要求:创建 -> 注册控制命令 -> 设置元数据 -> 激活
+   */
+  private initializeAvSession(): void {
+    try {
+      // 1. 创建AVSession控制器(音频模式)
+      this.avSessionController = AvSessionController.getInstance(false);
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession controller created');
+      
+      // 2. 延迟设置监听器,等待AVSession创建完成
+      setTimeout(() => {
+        this.setAvSessionListener();
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession listeners configured');
+      }, 500);
+      
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to initialize AVSession: ${error}`);
+    }
+  }
+  
+
+  
+  /**
+   * 设置AVSession监听器
+   * 注意:控制命令已在AvSessionController中注册,这里设置实际的处理逻辑
+   */
+  private setAvSessionListener(): void {
+    if (!this.avSessionController) {
+      return;
+    }
+    
+    const avSession = this.avSessionController.getAvSession();
+    if (!avSession) {
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession not available for listener setup');
+      return;
+    }
+    
+    try {
+      // 重新注册监听器,覆盖AvSessionController中的空实现
+      // 播放事件监听
+      avSession.on('play', () => {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession play command received');
+        this.startPlayOrResumePlay().catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession play command failed: ${error}`);
+        });
+      });
+      
+      // 暂停事件监听
+      avSession.on('pause', () => {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession pause command received');
+        this.pause().catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession pause command failed: ${error}`);
+        });
+      });
+      
+      // 停止事件监听
+      avSession.on('stop', () => {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession stop command received');
+        this.stop().catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession stop command failed: ${error}`);
+        });
+      });
+      
+      // 下一首事件监听
+      avSession.on('playNext', () => {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession playNext command received');
+        this.playNext().catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession playNext command failed: ${error}`);
+        });
+      });
+      
+      // 上一首事件监听
+      avSession.on('playPrevious', () => {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession playPrevious command received');
+        this.playPrevious().catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession playPrevious command failed: ${error}`);
+        });
+      });
+      
+      // 拖拽进度事件监听
+      avSession.on('seek', (time: number) => {
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession seek command received: ${time}ms`);
+        this.seekTo(time.toString()).catch((error: Error) => {
+          LogUtils.getInstance().LOGI(`AVSession seek command failed: ${error}`);
+        });
+      });
+      
+      // 循环模式设置监听
+      avSession.on('setLoopMode', (mode: avSession.LoopMode) => {
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService: AVSession setLoopMode command received: ${mode}`);
+        // 转换AVSession循环模式到应用内部播放模式
+        const playMode = this.convertLoopModeToPlayMode(mode);
+        this.setPlayMode(playMode);
+      });
+      
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession listeners set up successfully');
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to set AVSession listeners: ${error}`);
+    }
+  }
+  
+
+  
+  /**
+   * 转换AVSession循环模式为播放模式
+   */
+  private convertLoopModeToPlayMode(loopMode: avSession.LoopMode): number {
+    switch (loopMode) {
+      case avSession.LoopMode.LOOP_MODE_SINGLE:
+        return PlayMode.SINGLE_REPEAT;
+      case avSession.LoopMode.LOOP_MODE_LIST:
+        return PlayMode.NORMAL;
+      case avSession.LoopMode.LOOP_MODE_SHUFFLE:
+        return PlayMode.RANDOM;
+      case avSession.LoopMode.LOOP_MODE_SEQUENCE:
+      default:
+        return PlayMode.SEQUENCE;
+    }
+  }
+
+  
   // ==================== 错误处理和恢复方法 ====================
   
   /**
@@ -864,7 +1074,9 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       throw new Error('Player not initialized');
     }
 
-    // 重置播放器
+    console.log("Heanup2 UnifiedPlayerService: 开始重新设置播放器,这会重置所有状态");
+
+    // 重置播放器 - 这会清除所有状态包括播放位置
     ijkPlayer.reset();
     
     // 重新设置音频模式 - 重置后需要重新设置
@@ -901,6 +1113,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     ijkPlayer.setMessageListener();
     
     LogUtils.getInstance().LOGI(`UnifiedPlayerService: Player setup for song ${song.name}`);
+    console.log("Heanup2 UnifiedPlayerService: 播放器重新设置完成,准备开始新的播放");
   }  
   private setupProgressTimer(): void {
     this.progressTimer = setInterval(() => {
@@ -909,29 +1122,51 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
   }
 
   private startProgressTimer(): void {
-    if (this.progressTimer === -1) {
-      this.setupProgressTimer();
-    }
+    // 先停止现有的定时器,避免重复启动
+    this.stopProgressTimer();
+    
+    // 启动新的定时器
+    this.setupProgressTimer();
+    LogUtils.getInstance().LOGI('UnifiedPlayerService: Progress timer started');
   }
 
   private stopProgressTimer(): void {
     if (this.progressTimer !== -1) {
       clearInterval(this.progressTimer);
       this.progressTimer = -1;
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: Progress timer stopped');
     }
   }
 
   private updateProgress(): void {
     try {
       const ijkPlayer = this.playerManager.getIjkPlayer();
-      if (!ijkPlayer || !this.stateModel.getState().isPlaying) {
+      const currentState = this.stateModel.getState();
+      
+      // 只有在播放器存在且正在播放时才更新进度
+      if (!ijkPlayer || !currentState.isPlaying) {
         return;
       }
 
       const currentPosition = ijkPlayer.getCurrentPosition();
       const duration = ijkPlayer.getDuration();
       
-      this.stateModel.updateProgress(currentPosition, duration);
+      // 确保获取到有效的位置信息
+      if (currentPosition >= 0 && duration > 0) {
+        this.stateModel.updateProgress(currentPosition, duration);
+        
+        // 定期更新AVSession播放状态,确保系统媒体控制界面显示正确的进度
+        // 前30秒每3秒更新一次,之后每10秒更新一次
+        const now = Date.now();
+        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}`);
     }
@@ -975,15 +1210,14 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     }
   }
 
-  private restorePlaybackPosition(song: VideoItem): void {
+  private async restorePlaybackPosition(song: VideoItem): Promise<void> {
     try {
       // 使用DataPersistenceService恢复播放进度
-      this.dataPersistence.loadPlaybackProgress(song.filePath).then(progressData => {
-        if (progressData && progressData.position > 0 && !progressData.completed) {
-          this.playerManager.seekToPosition(progressData.position.toString());
-          LogUtils.getInstance().LOGI(`UnifiedPlayerService: Restored playback position ${progressData.position}ms for ${song.name}`);
-        }
-      })
+      const progressData = await this.dataPersistence.loadPlaybackProgress(song.filePath);
+      if (progressData && progressData.position > 0 && !progressData.completed) {
+        await this.playerManager.seekToPosition(progressData.position.toString());
+        LogUtils.getInstance().LOGI(`UnifiedPlayerService: Restored playback position ${progressData.position}ms for ${song.name}`);
+      }
     } catch (error) {
       LogUtils.getInstance().LOGI(`UnifiedPlayerService restorePlaybackPosition error: ${error}`);
     }
@@ -995,12 +1229,17 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
    */
   private async restorePersistedState(): Promise<void> {
     try {
-      console.log("Heanup2 UnifiedPlayerService: 开始恢复持久化状态");
+      console.log("Heanup2 UnifiedPlayerService: 开始快速恢复持久化状态");
       
-      // 恢复播放列表
-      const playlistData = await this.dataPersistence.loadPlaylist();
-      console.log(`Heanup2 UnifiedPlayerService: 加载到的播放列表数据: ${playlistData ? 'exists' : 'null'}`);
+      // 并行加载播放列表和播放状态,提高效率
+      const loadResults = await Promise.all([
+        this.dataPersistence.loadPlaylist().catch(() => null),
+        this.dataPersistence.loadPlayerState().catch(() => null)
+      ]);
+      const playlistData = loadResults[0];
+      const stateData = loadResults[1];
       
+      // 恢复播放列表
       if (playlistData && playlistData.songs.length > 0) {
         console.log(`Heanup2 UnifiedPlayerService: 恢复播放列表,歌曲数量=${playlistData.songs.length}, 当前索引=${playlistData.currentIndex}`);
         this.playlistModel.replaceSongs(playlistData.songs, playlistData.currentIndex);
@@ -1020,25 +1259,16 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       }
       
       // 恢复播放状态
-      const stateData = await this.dataPersistence.loadPlayerState();
       if (stateData) {
         console.log(`Heanup2 UnifiedPlayerService: 加载到的播放状态 - playing: ${stateData.isPlaying}, paused: ${stateData.isPaused}, index: ${stateData.currentIndex}`);
         
+        // 批量更新状态,减少回调次数
         this.stateModel.updateVolume(stateData.volume);
         this.stateModel.updateSpeed(stateData.speed);
         this.stateModel.updatePlayMode(stateData.playMode);
         
-        // 恢复播放状态(isPlaying 和 isPaused)
-        if (stateData.isPlaying) {
-          console.log("Heanup2 UnifiedPlayerService: 恢复播放状态为播放中");
-          this.stateModel.updatePlayingState(true);
-        } else if (stateData.isPaused) {
-          console.log("Heanup2 UnifiedPlayerService: 恢复播放状态为暂停");
-          this.stateModel.updatePlayingState(false);
-        } else {
-          console.log("Heanup2 UnifiedPlayerService: 恢复播放状态为停止");
-          this.stateModel.updatePlayingState(false);
-        }
+        // 恢复播放状态
+        this.stateModel.updatePlayingState(stateData.isPlaying || false);
         
         // 恢复当前播放索引
         if (stateData.currentIndex >= 0) {
@@ -1051,7 +1281,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         console.log("Heanup2 UnifiedPlayerService: 没有找到保存的播放状态");
       }
       
-      console.log("Heanup2 UnifiedPlayerService: 持久化状态恢复完成");
+      console.log("Heanup2 UnifiedPlayerService: 持久化状态快速恢复完成");
       
       // 设置数据恢复完成标识
       this.isDataRestored = true;
@@ -1347,20 +1577,45 @@ 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());
   }
 
   onPlaybackStarted(): void {
-    LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback started');
+    LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback started (new song)');
+    
+    // 这个回调只应该在新歌曲开始播放时被调用(通过onPrepared触发)
+    // 不应该在暂停恢复时被调用
+    
+    // 立即更新播放状态
     this.stateModel.updatePlayingState(true);
+    
+    // 启动进度定时器
     this.startProgressTimer();
     
     // 保存播放状态变化
     this.saveCurrentState();
     
+    // 延迟更新AVSession,确保播放器状态稳定
+    setTimeout(() => {
+      this.updateSessionPlayState(true);
+      // 设置当前播放模式
+      this.setCurrentPlayMode();
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession state updated for new song playback');
+    }, 200);
+    
     // 播放开始时更新卡片显示播放状态
     this.updateWidgetsForPlayStateChange(true);
+    
+    LogUtils.getInstance().LOGI('UnifiedPlayerService: New song playback started successfully');
   }
 
   onPlaybackCompleted(): void {
@@ -1371,6 +1626,9 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     // 保存播放状态变化
     this.saveCurrentState();
     
+    // 立即更新AVSession播放状态为完成
+    this.updateSessionPlayState(false);
+    
     // 更新卡片显示播放完成状态
     this.updateWidgetsForPlayStateChange(false);
     
@@ -1431,6 +1689,15 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     const totalCount = this.playlistModel.getTotalCount();
     const playMode = currentState.playMode;
 
+    // 调试封面路径信息
+    if (currentSong) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: createWidgetData - Song: ${currentSong.name}`);
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: createWidgetData - pixelMapPath: ${currentSong.pixelMapPath || 'empty'}`);
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: createWidgetData - filePath: ${currentSong.filePath || 'empty'}`);
+    } else {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: createWidgetData - No current song`);
+    }
+
     return {
       playState: {
         isPlaying: currentState.isPlaying,
@@ -1583,23 +1850,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;
     }
-    
-    return 0;
   }
+
+  /**
+   * 更新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}`);
+    }
+  }
+
+  /**
+   * 更新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}`);
+    }
+  }
+
+  // ==================== 辅助方法 ====================
+
+
 }

+ 380 - 50
entry/src/main/ets/common/widget/EnhancedFormUpdateService.ets

@@ -2,7 +2,7 @@ import { hilog } from '@kit.PerformanceAnalysisKit';
 import { formProvider, formBindingData } from '@kit.FormKit';
 import { preferences } from '@kit.ArkData';
 import { Context } from '@kit.AbilityKit';
-import { WidgetData, FormattedWidgetData, WidgetSize } from './WidgetTypes';
+import { WidgetData, FormattedWidgetData, WidgetSize, ImageFileInfo } from './WidgetTypes';
 import { FormLayoutManager } from './FormLayoutManager';
 import { PreferencesUtil } from '../utils/PreferencesUtil';
 import { GlobalWidgetManager } from './GlobalWidgetManager';
@@ -54,6 +54,22 @@ interface ImageCacheItem {
   fileSize: number;
 }
 
+/**
+ * 包含图片文件描述符的卡片数据接口
+ */
+interface FormattedWidgetDataWithImages extends FormattedWidgetData {
+  formImages?: Record<string, number>;
+}
+
+/**
+ * 处理后的本地图片信息接口
+ */
+interface ProcessedImageInfo {
+  fileName: string;
+  memoryUri: string;
+  fd: number;
+}
+
 /**
  * 更新统计接口
  */
@@ -118,7 +134,7 @@ export class EnhancedFormUpdateService {
    */
   public setAppContext(context: Context): void {
     this.appContext = context;
-    hilog.info(0x0000, TAG, '🎯 App context set for EnhancedFormUpdateService');
+    
     this.initializeImageCache();
   }
 
@@ -127,6 +143,10 @@ export class EnhancedFormUpdateService {
    */
   public async updateAllForms(data: WidgetData): Promise<BatchUpdateStats> {
     const batchStartTime = Date.now();
+    console.log("Heanup updateAllForms data:"+JSON.stringify(data))
+    
+    // 预处理图片路径 - 转换本地文件URI为可用格式
+    const processedData = await this.preprocessImageData(data);
     
     try {
       if (!this.appContext) {
@@ -137,53 +157,63 @@ export class EnhancedFormUpdateService {
       // 防抖检查
       const now = Date.now();
       if (now - this.lastUpdateTime < this.updateDebounceDelay) {
-        hilog.info(0x0000, TAG, `⏭️ Update debounced, skipping (${now - this.lastUpdateTime}ms since last update)`);
+        
         return this.createEmptyStats();
       }
 
       // 防止并发更新
       if (this.isUpdating) {
-        hilog.warn(0x0000, TAG, '⚠️ Update already in progress, skipping this request');
+        
         return this.createEmptyStats();
       }
 
       this.isUpdating = true;
       this.lastUpdateTime = now;
 
-      hilog.info(0x0000, TAG, `🚀 Starting enhanced batch form update: isPlaying=${data.playState.isPlaying}, title="${data.currentSong.title}"`);
+      
 
       // 获取所有持久化的 Form ID(使用原有方法)
       const prefs = await this.preferencesUtil.getPreferences(this.appContext);
       const formIds = await this.preferencesUtil.getFormIds(prefs);
 
       if (formIds.length === 0) {
-        hilog.info(0x0000, TAG, '📋 No forms found in persistence, skipping update');
+        
         return this.createEmptyStats();
       }
 
-      hilog.info(0x0000, TAG, `📋 Found ${formIds.length} forms to update: [${formIds.join(', ')}]`);
+      
 
       // 验证活跃卡片与持久化卡片的一致性
       await this.validateActiveWidgets(formIds, prefs);
+      
+      // 预先验证卡片ID的有效性,移除无效的ID
+      const validFormIds = await this.preValidateFormIds(formIds, prefs);
+      
+      if (validFormIds.length === 0) {
+        hilog.warn(0x0000, TAG, '📋 No valid form IDs found after validation');
+        return this.createEmptyStats();
+      }
+      
+      hilog.info(0x0000, TAG, `📋 Valid forms: ${validFormIds.length}/${formIds.length}`);
 
       // 并行更新所有卡片
-      const updatePromises = formIds.map((formId, index) => {
-        hilog.info(0x0000, TAG, `🎯 Creating update task ${index + 1}/${formIds.length} for form: ${formId}`);
-        hilog.info(0x0000, TAG, "更新的卡片数据: "+JSON.stringify(data));
-        return this.updateSingleFormWithRetry(formId, data, prefs);
+      const updatePromises = validFormIds.map((formId, index) => {
+        
+        
+        return this.updateSingleFormWithRetry(formId, processedData, prefs);
       });
 
-      hilog.info(0x0000, TAG, `⏳ Executing ${updatePromises.length} parallel update tasks...`);
+      
 
       // 等待所有更新完成
       const results = await Promise.allSettled(updatePromises);
 
       // 处理结果并生成统计信息
-      const batchStats = this.processBatchResults(formIds, results, batchStartTime);
+      const batchStats = this.processBatchResults(validFormIds, results, batchStartTime);
 
       // 清理无效的 Form ID
       if (batchStats.failed > 0) {
-        await this.cleanupInvalidForms(prefs, formIds, results);
+        await this.cleanupInvalidForms(prefs, validFormIds, results);
       }
 
       // 更新统计信息
@@ -198,7 +228,7 @@ export class EnhancedFormUpdateService {
           (this.updateStats.averageUpdateTime * (this.updateStats.totalUpdates - batchStats.total) + batchStats.averageUpdateTime * batchStats.total) / this.updateStats.totalUpdates;
       }
 
-      hilog.info(0x0000, TAG, `✅ Batch update completed: ${batchStats.success}/${batchStats.total} successful in ${batchStats.duration}ms (avg: ${batchStats.averageUpdateTime.toFixed(1)}ms per form)`);
+      
 
       return batchStats;
 
@@ -221,14 +251,14 @@ export class EnhancedFormUpdateService {
       try {
         if (attempt > 0) {
           const delay = this.retryDelays[Math.min(attempt - 1, this.retryDelays.length - 1)];
-          hilog.info(0x0000, TAG, `🔄 [${formId}] Retry attempt ${attempt}/${this.maxRetryCount} after ${delay}ms delay`);
+          
           await this.sleep(delay);
         }
 
         await this.updateSingleForm(formId, data, prefs);
         
         const updateTime = Date.now() - startTime;
-        hilog.info(0x0000, TAG, `✅ [${formId}] Update successful on attempt ${attempt + 1} (${updateTime}ms)`);
+        
         
         return {
           formId,
@@ -239,7 +269,35 @@ export class EnhancedFormUpdateService {
 
       } catch (error) {
         lastError = error as Error;
-        hilog.warn(0x0000, TAG, `⚠️ [${formId}] Update attempt ${attempt + 1} failed: ${lastError.message}`);
+        const errorStr :string= error.toString();
+        
+        // 如果是无效卡片ID错误,立即停止重试并清理
+        if (errorStr.includes('form not exist') || 
+            errorStr.includes('16501001') ||
+            errorStr.includes('The ID of the form to be operated does not exist')) {
+          hilog.warn(0x0000, TAG, `🗑️ [${formId}] Invalid form ID detected, cleaning up immediately`);
+          
+          // 立即清理无效ID
+          try {
+            await this.preferencesUtil.removeFormId(prefs, formId);
+            this.globalWidgetManager.unregisterWidget(formId);
+            hilog.info(0x0000, TAG, `🗑️ [${formId}] Cleaned up invalid form ID`);
+          } catch (cleanupError) {
+            hilog.error(0x0000, TAG, `❌ [${formId}] Failed to cleanup invalid form ID: ${cleanupError}`);
+          }
+          
+          // 立即返回失败结果,不再重试
+          const updateTime = Date.now() - startTime;
+          return {
+            formId,
+            success: false,
+            error: lastError,
+            updateTime,
+            retryCount: attempt
+          };
+        }
+        
+        
       }
     }
 
@@ -260,14 +318,14 @@ export class EnhancedFormUpdateService {
    */
   private async updateSingleForm(formId: string, data: WidgetData, prefs: preferences.Preferences): Promise<void> {
     try {
-      hilog.info(0x0000, TAG, `🎯 [${formId}] Starting enhanced form update...`);
+      
 
       // 获取卡片的当前状态
       const formState = await this.preferencesUtil.getFormState(prefs, formId);
       const widgetSizeStr = (formState?.size as string) || 'medium';
       const widgetSize: WidgetSize = widgetSizeStr as WidgetSize;
 
-      hilog.info(0x0000, TAG, `🎯 [${formId}] Widget size: ${widgetSizeStr}`);
+      
 
       // 适配数据到卡片尺寸
       const adaptedData = this.layoutManager.adaptDataForSize(data, widgetSize);
@@ -296,13 +354,48 @@ export class EnhancedFormUpdateService {
         imgName: adaptedData.imgName || ''
       };
 
-      hilog.info(0x0000, TAG, `🎯 [${formId}] Formatted data prepared: isPlaying=${formattedData.isPlaying}, title="${formattedData.songTitle}"`);
+      
 
-      // 创建 FormBindingData 并更新卡片
-      const formData = formBindingData.createFormBindingData(formattedData);
+      // 处理图片文件描述符(如果有本地图片)
+      let formData: formBindingData.FormBindingData;
+      if (data.imageFileInfo && formattedData.imgName) {
+        // 创建包含文件描述符的数据
+        const dataWithImages: FormattedWidgetDataWithImages = {
+          isPlaying: formattedData.isPlaying,
+          isPaused: formattedData.isPaused,
+          isLoading: formattedData.isLoading,
+          songTitle: formattedData.songTitle,
+          songArtist: formattedData.songArtist,
+          songAlbum: formattedData.songAlbum,
+          coverImage: formattedData.coverImage,
+          currentTime: formattedData.currentTime,
+          totalTime: formattedData.totalTime,
+          progressPercentage: formattedData.progressPercentage,
+          hasNext: formattedData.hasNext,
+          hasPrevious: formattedData.hasPrevious,
+          showProgress: formattedData.showProgress,
+          showCover: formattedData.showCover,
+          widgetSize: formattedData.widgetSize,
+          timestamp: formattedData.timestamp,
+          imgName: formattedData.imgName,
+          formImages: {} as Record<string, number>
+        };
+        
+        // 设置图片文件描述符
+        if (dataWithImages.formImages) {
+          dataWithImages.formImages[data.imageFileInfo.fileName] = data.imageFileInfo.fd;
+        }
+        
+        formData = formBindingData.createFormBindingData(dataWithImages);
+        hilog.info(0x0000, TAG, `📷 [${formId}] Created form data with image fd: ${data.imageFileInfo.fd} for ${data.imageFileInfo.fileName}`);
+      } else {
+        formData = formBindingData.createFormBindingData(formattedData);
+      }
+
+      // 更新卡片
       await formProvider.updateForm(formId, formData);
       
-      hilog.info(0x0000, TAG, `✅ [${formId}] Form updated successfully`);
+      
 
       // 保存增强状态信息
       await this.saveEnhancedFormState(prefs, formId, widgetSizeStr, data);
@@ -313,22 +406,204 @@ export class EnhancedFormUpdateService {
     }
   }
 
+  /**
+   * 预处理图片数据 - 转换本地文件URI为卡片可用格式
+   */
+  private async preprocessImageData(data: WidgetData): Promise<WidgetData> {
+    try {
+      // 修改点1: 显式声明processedData的类型为WidgetData
+      let processedData: WidgetData = data;
+      const coverImagePath = data.currentSong.coverImagePath;
+      
+      if (!coverImagePath || coverImagePath.trim() === '') {
+        hilog.info(0x0000, TAG, '📷 No cover image path, skipping preprocessing');
+        return data;
+      }
+
+      hilog.info(0x0000, TAG, `📷 Processing cover image: ${coverImagePath}`);
+
+      // 处理本地文件URI
+      if (this.isLocalFileUri(coverImagePath)) {
+        hilog.info(0x0000, TAG, `📷 Detected local file URI: ${coverImagePath}`);
+        
+        const processedImageInfo = await this.processLocalImageFile(coverImagePath);
+        
+        if (processedImageInfo) {
+          // 创建新的数据对象,包含处理后的图片信息
+          processedData.currentSong.coverImagePath = processedImageInfo.memoryUri;
+          processedData.imageFileInfo = processedImageInfo as ImageFileInfo;
+          // const processedData: WidgetData = {
+          //   ...data,
+          //   currentSong: {
+          //     ...data.currentSong,
+          //     coverImagePath: processedImageInfo.memoryUri // 使用 memory:// 格式
+          //   },
+          //   // 添加图片文件信息用于后续处理
+          //   imageFileInfo: processedImageInfo
+          // };
+          
+          hilog.info(0x0000, TAG, `📷 Local image processed successfully: ${processedImageInfo.fileName} -> ${processedImageInfo.memoryUri}`);
+          return processedData;
+        } else {
+          hilog.warn(0x0000, TAG, `📷 Failed to process local image, using original data`);
+          return data;
+        }
+      }
+      // 处理网络图片
+      else if (this.isNetworkUrl(coverImagePath)) {
+        hilog.info(0x0000, TAG, `📷 Detected network image: ${coverImagePath}`);
+        // 网络图片在 handleNetworkImage 中处理
+        return data;
+      }
+      // 其他情况
+      else {
+        hilog.info(0x0000, TAG, `📷 Using image path as-is: ${coverImagePath}`);
+        return data;
+      }
+      
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Error preprocessing image data: ${error}`);
+      return data; // 出错时返回原始数据
+    }
+  }
+
+  /**
+   * 处理本地图片文件
+   */
+  private async processLocalImageFile(fileUri: string): Promise<ProcessedImageInfo | null> {
+    try {
+      hilog.info(0x0000, TAG, `📷 Processing local image file: ${fileUri}`);
+
+      // 转换 file:// URI 为实际文件路径
+      // file://com.xgplayer.ttmusic.hm/data/storage/el2/base/haps/entry/files/xxx.jpg
+      // 转换为 /data/storage/el2/base/haps/entry/files/xxx.jpg
+      let realPath = fileUri.replace('file://', '');
+      
+      // 如果路径包含应用包名,需要移除它并构建正确的绝对路径
+      if (realPath.startsWith('com.xgplayer.ttmusic.hm/')) {
+        // 移除包名前缀,获取相对路径
+        const relativePath = realPath.replace('com.xgplayer.ttmusic.hm/', '');
+        // 使用应用上下文获取正确的文件路径
+        realPath = `${this.appContext!.filesDir}/${relativePath.split('/').pop()}`;
+        hilog.info(0x0000, TAG, `📷 Converted path with package name: ${fileUri} -> ${realPath}`);
+      } else if (!realPath.startsWith('/')) {
+        // 如果不是绝对路径,添加根路径
+        realPath = `/${realPath}`;
+      }
+      
+      hilog.info(0x0000, TAG, `📷 Final resolved path: ${realPath}`);
+      
+      // 检查源文件是否存在
+      if (!fileIo.accessSync(realPath)) {
+        hilog.error(0x0000, TAG, `📷 Source image file does not exist: ${realPath}`);
+        
+        // 尝试备用路径查找
+        const fileName = realPath.split('/').pop();
+        const alternativePaths = [
+          `${this.appContext!.filesDir}/${fileName}`,
+          `${this.appContext!.cacheDir}/${fileName}`,
+          `${this.appContext!.tempDir}/${fileName}`
+        ];
+        
+        let foundPath: string | null = null;
+        for (const altPath of alternativePaths) {
+          if (fileIo.accessSync(altPath)) {
+            foundPath = altPath;
+            hilog.info(0x0000, TAG, `📷 Found file at alternative path: ${altPath}`);
+            break;
+          }
+        }
+        
+        if (!foundPath) {
+          hilog.error(0x0000, TAG, `📷 File not found in any location: ${fileName}`);
+          return null;
+        }
+        
+        realPath = foundPath;
+      }
+
+      // 生成目标文件名(确保每次都不同,符合官方文档要求)
+      const fileExtension = this.getFileExtension(realPath) || 'jpg';
+      const fileName = `widget_local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.${fileExtension}`;
+      
+      // 使用 FormExtensionAbility 的 tempDir(官方文档要求)
+      const formTempDir = this.appContext!.getApplicationContext().tempDir;
+      const tempFilePath = `${formTempDir}/${fileName}`;
+
+      hilog.info(0x0000, TAG, `📷 Using tempDir: ${formTempDir}`);
+
+      // 复制文件到临时目录
+      fileIo.copyFileSync(realPath, tempFilePath);
+
+      // 获取文件描述符
+      const file = fileIo.openSync(tempFilePath, fileIo.OpenMode.READ_ONLY);
+      const fd = file.fd;
+
+      const memoryUri = `memory://${fileName}`;
+      
+      hilog.info(0x0000, TAG, `📷 Local image copied successfully: ${realPath} -> ${tempFilePath}, fd: ${fd}`);
+      
+      const result: ProcessedImageInfo = {
+        fileName,
+        memoryUri,
+        fd
+      };
+      
+      return result;
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Failed to process local image: ${error}`);
+      return null;
+    }
+  }
+
+  /**
+   * 检查是否为本地文件URI
+   */
+  private isLocalFileUri(url: string): boolean {
+    return url.startsWith('file://');
+  }
+
+  /**
+   * 获取文件扩展名
+   */
+  private getFileExtension(filePath: string): string | null {
+    const lastDotIndex = filePath.lastIndexOf('.');
+    if (lastDotIndex === -1 || lastDotIndex === filePath.length - 1) {
+      return null;
+    }
+    return filePath.substring(lastDotIndex + 1).toLowerCase();
+  }
+
   /**
    * 处理网络图片(缓存 + 下载)
    */
   private async handleNetworkImage(adaptedData: FormattedWidgetData): Promise<void> {
-    if (!adaptedData.coverImage || !this.isNetworkUrl(adaptedData.coverImage)) {
+    if (!adaptedData.coverImage) {
       return;
     }
 
     try {
+      // 如果已经是 memory:// 格式(本地图片已处理),直接返回
+      if (adaptedData.coverImage.startsWith('memory://')) {
+        hilog.info(0x0000, TAG, `📷 Image already processed as memory URI: ${adaptedData.coverImage}`);
+        const fileName = adaptedData.coverImage.replace('memory://', '');
+        adaptedData.imgName = fileName;
+        return;
+      }
+
+      // 处理网络图片
+      if (!this.isNetworkUrl(adaptedData.coverImage)) {
+        return;
+      }
+
       const imageUrl = adaptedData.coverImage;
-      hilog.info(0x0000, TAG, `🖼️ Processing network image: ${imageUrl}`);
+      
 
       // 检查缓存
       const cachedItem = this.imageCache.get(imageUrl);
       if (cachedItem && cachedItem.expiry > Date.now()) {
-        hilog.info(0x0000, TAG, `📸 Using cached image: ${cachedItem.fileName}`);
+        
         adaptedData.coverImage = `memory://${cachedItem.fileName}`;
         adaptedData.imgName = cachedItem.fileName;
         return;
@@ -339,12 +614,12 @@ export class EnhancedFormUpdateService {
       if (fileName) {
         adaptedData.coverImage = `memory://${fileName}`;
         adaptedData.imgName = fileName;
-        hilog.info(0x0000, TAG, `📸 Network image processed: ${fileName}`);
+        
       } else {
         // 下载失败,清除图片
         adaptedData.coverImage = '';
         adaptedData.imgName = '';
-        hilog.warn(0x0000, TAG, `⚠️ Failed to download image, using default`);
+        
       }
 
     } catch (error) {
@@ -360,7 +635,7 @@ export class EnhancedFormUpdateService {
   private async downloadAndCacheImage(imageUrl: string): Promise<string | null> {
     // 检查是否正在下载
     if (this.downloadingImages.has(imageUrl)) {
-      hilog.info(0x0000, TAG, `⏳ Image already downloading: ${imageUrl}`);
+      
       return await this.downloadingImages.get(imageUrl)!;
     }
 
@@ -381,7 +656,7 @@ export class EnhancedFormUpdateService {
    */
   private async performImageDownload(imageUrl: string): Promise<string | null> {
     try {
-      hilog.info(0x0000, TAG, `📥 Downloading image: ${imageUrl}`);
+      
       
       const httpRequest = http.createHttp();
       const response = await httpRequest.request(imageUrl, {
@@ -401,7 +676,8 @@ export class EnhancedFormUpdateService {
       const filePath = `${this.appContext!.cacheDir}/${fileName}`;
       const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
       
-      const buffer = response.result as ArrayBuffer;
+      // 修改点2: 显式声明buffer的类型为ArrayBuffer
+      const buffer: ArrayBuffer = response.result as ArrayBuffer;
       fileIo.writeSync(file.fd, new Uint8Array(buffer));
       fileIo.closeSync(file);
 
@@ -416,7 +692,7 @@ export class EnhancedFormUpdateService {
       this.imageCache.set(imageUrl, cacheItem);
       this.cleanupImageCache();
 
-      hilog.info(0x0000, TAG, `✅ Image downloaded and cached: ${fileName} (${buffer.byteLength} bytes)`);
+      
       
       httpRequest.destroy();
       return fileName;
@@ -451,9 +727,9 @@ export class EnhancedFormUpdateService {
           fileIo.unlinkSync(filePath);
         }
         this.imageCache.delete(url);
-        hilog.info(0x0000, TAG, `🗑️ Cleaned up cached image: ${item.fileName}`);
+        
       } catch (error) {
-        hilog.warn(0x0000, TAG, `⚠️ Failed to cleanup image: ${error}`);
+        
       }
     }
   }
@@ -475,13 +751,67 @@ export class EnhancedFormUpdateService {
           // 删除超过24小时的文件
           if (Date.now() - stat.mtime > this.imageCacheExpiry) {
             fileIo.unlinkSync(filePath);
-            hilog.info(0x0000, TAG, `🗑️ Cleaned up expired cache file: ${file}`);
+            
           }
         }
       }
     } catch (error) {
-      hilog.warn(0x0000, TAG, `⚠️ Failed to cleanup cache directory: ${error}`);
+      
+    }
+  }
+
+  /**
+   * 预先验证卡片ID的有效性
+   */
+  private async preValidateFormIds(formIds: string[], prefs: preferences.Preferences): Promise<string[]> {
+    const validFormIds: string[] = [];
+    const invalidFormIds: string[] = [];
+    
+    hilog.info(0x0000, TAG, `🔍 Pre-validating ${formIds.length} form IDs...`);
+    
+    for (const formId of formIds) {
+      try {
+        // 尝试使用一个简单的测试数据来验证卡片ID
+        const testData = formBindingData.createFormBindingData({
+          test: 'validation'
+        });
+        
+        // 尝试更新卡片,如果失败说明卡片ID无效
+        await formProvider.updateForm(formId, testData);
+        validFormIds.push(formId);
+        hilog.debug(0x0000, TAG, `✅ [${formId}] Valid form ID`);
+        
+      } catch (error) {
+        const errorStr :string= error.toString();
+        if (errorStr.includes('form not exist') || 
+            errorStr.includes('16501001') ||
+            errorStr.includes('The ID of the form to be operated does not exist')) {
+          hilog.warn(0x0000, TAG, `❌ [${formId}] Invalid form ID detected during validation`);
+          invalidFormIds.push(formId);
+        } else {
+          // 其他错误,可能是临时性的,保留该ID
+          hilog.warn(0x0000, TAG, `⚠️ [${formId}] Validation error (keeping): ${error}`);
+          validFormIds.push(formId);
+        }
+      }
+    }
+    
+    // 清理无效的卡片ID
+    if (invalidFormIds.length > 0) {
+      hilog.info(0x0000, TAG, `🗑️ Cleaning up ${invalidFormIds.length} invalid form IDs`);
+      for (const invalidFormId of invalidFormIds) {
+        try {
+          await this.preferencesUtil.removeFormId(prefs, invalidFormId);
+          this.globalWidgetManager.unregisterWidget(invalidFormId);
+          hilog.info(0x0000, TAG, `🗑️ [${invalidFormId}] Cleaned up invalid form ID`);
+        } catch (cleanupError) {
+          hilog.error(0x0000, TAG, `❌ [${invalidFormId}] Failed to cleanup: ${cleanupError}`);
+        }
+      }
     }
+    
+    hilog.info(0x0000, TAG, `🔍 Validation complete: ${validFormIds.length} valid, ${invalidFormIds.length} invalid`);
+    return validFormIds;
   }
 
   /**
@@ -491,23 +821,23 @@ export class EnhancedFormUpdateService {
     const activeWidgets = this.globalWidgetManager.getActiveWidgets();
     const activeFormIds = Array.from(activeWidgets.keys());
 
-    hilog.info(0x0000, TAG, `🔍 Validating widgets - Persistent: [${formIds.join(', ')}], Active: [${activeFormIds.join(', ')}]`);
+    
 
     // 检查持久化但不活跃的卡片
     const persistentOnlyIds = formIds.filter(id => !activeWidgets.has(id));
     if (persistentOnlyIds.length > 0) {
-      hilog.warn(0x0000, TAG, `⚠️ Found ${persistentOnlyIds.length} persistent but inactive widgets: [${persistentOnlyIds.join(', ')}]`);
+      
     }
 
     // 检查活跃但未持久化的卡片
     const activeOnlyIds = activeFormIds.filter(id => !formIds.includes(id));
     if (activeOnlyIds.length > 0) {
-      hilog.warn(0x0000, TAG, `⚠️ Found ${activeOnlyIds.length} active but not persistent widgets: [${activeOnlyIds.join(', ')}]`);
+      
       
       // 将活跃的卡片添加到持久化存储
       for (const formId of activeOnlyIds) {
         await this.preferencesUtil.addFormId(prefs, formId);
-        hilog.info(0x0000, TAG, `➕ Added missing form ID to persistence: ${formId}`);
+        
       }
     }
   }
@@ -529,9 +859,9 @@ export class EnhancedFormUpdateService {
       };
 
       await this.preferencesUtil.saveFormState(prefs, formId, stateData);
-      hilog.info(0x0000, TAG, `💾 [${formId}] Enhanced form state saved (update #${updateCount})`);
+      
     } catch (error) {
-      hilog.warn(0x0000, TAG, `⚠️ [${formId}] Failed to save enhanced form state: ${error}`);
+      
     }
   }
 
@@ -552,7 +882,7 @@ export class EnhancedFormUpdateService {
         if (updateResult.success) {
           successCount++;
           totalUpdateTime += updateResult.updateTime;
-          hilog.info(0x0000, TAG, `✅ Form ${index + 1}/${formIds.length} (${formId}) updated successfully in ${updateResult.updateTime}ms (${updateResult.retryCount} retries)`);
+          
         } else {
           failedCount++;
           hilog.error(0x0000, TAG, `❌ Form ${index + 1}/${formIds.length} (${formId}) failed: ${updateResult.error?.message}`);
@@ -587,28 +917,28 @@ export class EnhancedFormUpdateService {
           const errorStr = error.toString();
           const formId = formIds[index];
           
-          hilog.warn(0x0000, TAG, `🔍 Analyzing error for form ${formId}: ${errorStr}`);
+          
           
           if (errorStr.includes('form not exist') || 
               errorStr.includes('16501001') ||
               errorStr.includes('FormProvider') ||
               errorStr.includes('invalid form')) {
-            hilog.warn(0x0000, TAG, `🗑️ Form ${formId} appears to be invalid, marking for cleanup`);
+            
             invalidFormIds.push(formId);
           }
         }
       });
 
       if (invalidFormIds.length > 0) {
-        hilog.info(0x0000, TAG, `🧹 Cleaning up ${invalidFormIds.length} invalid forms: [${invalidFormIds.join(', ')}]`);
+        
         
         for (const invalidFormId of invalidFormIds) {
           await this.preferencesUtil.removeFormId(prefs, invalidFormId);
           this.globalWidgetManager.unregisterWidget(invalidFormId);
-          hilog.info(0x0000, TAG, `🗑️ Removed invalid form ID: ${invalidFormId}`);
+          
         }
         
-        hilog.info(0x0000, TAG, `✅ Invalid forms cleaned up successfully`);
+        
       }
     } catch (error) {
       hilog.error(0x0000, TAG, `❌ Failed to cleanup invalid forms: ${error}`);
@@ -639,7 +969,7 @@ export class EnhancedFormUpdateService {
       failedUpdates: 0,
       averageUpdateTime: 0
     };
-    hilog.info(0x0000, TAG, '📊 Update statistics reset');
+    
   }
 
   /**

+ 8 - 357
entry/src/main/ets/common/widget/PlayerControlService.ets

@@ -2,7 +2,7 @@ import commonEventManager from '@ohos.commonEventManager';
 import Want from '@ohos.app.ability.Want';
 import common from '@ohos.app.ability.common';
 import { hilog } from '@kit.PerformanceAnalysisKit';
-import { WidgetData, WidgetCommand, EventData, RequestData, WidgetControlParams, PlayState as WidgetPlayState, SongInfo, PlayProgress, PlaylistState } from './WidgetTypes';
+import { WidgetData, WidgetCommand, EventData, RequestData, WidgetControlParams } from './WidgetTypes';
 import { WidgetTypeHelpers } from './WidgetTypeHelpers';
 import { 
   WIDGET_CONTROL_EVENT,
@@ -14,11 +14,8 @@ import {
   APP_ABILITY_NAME
 } from './WidgetEventConstants';
 import { AvSessionWidgetListener } from './AvSessionWidgetListener';
-import { UnifiedPlayerService, IPlayerService } from '../service/UnifiedPlayerService';
-import { PlayerState, PlayerStateListener, PlayerError } from '../service/PlayerStateModel';
-import { VideoItem } from '../../viewmodel/VideoItem';
 
-const TAG = 'PlayerControlService';
+const TAG = 'Heanup PlayerControlService';
 
 /**
  * 启动参数接口
@@ -29,83 +26,21 @@ interface LaunchParameters {
   timestamp: string;
 }
 
-/**
- * 命令执行状态
- */
-interface CommandExecutionStatus {
-  command: WidgetCommand;
-  timestamp: number;
-  status: 'pending' | 'executing' | 'completed' | 'failed';
-  error?: string;
-}
+
 
 /**
  * 播放器控制服务
  * 负责与主应用的播放器进行通信和状态同步
- * 优化版本:直接集成UnifiedPlayerService,减少响应延迟
  */
 export class PlayerControlService {
   private stateListeners: Array<(data: WidgetData) => void> = [];
   private isListenerRegistered: boolean = false;
   private avSessionListener: AvSessionWidgetListener;
-  private unifiedPlayerService: IPlayerService | null = null;
-  private commandExecutionQueue: Map<string, CommandExecutionStatus> = new Map();
-  private readonly COMMAND_TIMEOUT = 3000; // 3秒命令超时
-  private readonly MAX_RETRY_ATTEMPTS = 2;
 
   constructor() {
     this.avSessionListener = AvSessionWidgetListener.getInstance();
     this.initializeEventListener();
     this.initializeAvSessionListener();
-    this.initializeUnifiedPlayerService();
-    this.startPeriodicCleanup();
-  }
-
-  /**
-   * 初始化统一播放器服务连接
-   */
-  private async initializeUnifiedPlayerService(): Promise<void> {
-    try {
-      // 尝试获取UnifiedPlayerService实例
-      this.unifiedPlayerService = UnifiedPlayerService.getInstance();
-      
-      if (this.unifiedPlayerService) {
-        hilog.info(0x0000, TAG, 'UnifiedPlayerService connection established for widget control');
-        
-        // 添加状态监听器以实现实时状态同步
-        class WidgetStateListener implements PlayerStateListener {
-          private service: PlayerControlService;
-          
-          constructor(service: PlayerControlService) {
-            this.service = service;
-          }
-          
-          onStateChanged(state: PlayerState): void {
-            this.service.handleUnifiedPlayerStateChange(state);
-          }
-          
-          onSongChanged(song: VideoItem): void {
-            this.service.handleUnifiedPlayerSongChange(song);
-          }
-          
-          onProgressChanged(progress: PlayProgress): void {
-            this.service.handleUnifiedPlayerProgressChange(progress);
-          }
-          
-          onError(error: PlayerError): void {
-            hilog.error(0x0000, TAG, `UnifiedPlayerService error in widget: ${error.message}`);
-          }
-        }
-        
-        const listener = new WidgetStateListener(this);
-        this.unifiedPlayerService.addStateListener(listener);
-      } else {
-        hilog.warn(0x0000, TAG, 'UnifiedPlayerService not available, falling back to CommonEvent communication');
-      }
-    } catch (error) {
-      hilog.error(0x0000, TAG, `Failed to initialize UnifiedPlayerService connection: ${error}`);
-      // 继续使用CommonEvent作为备用方案
-    }
   }
 
   /**
@@ -199,126 +134,9 @@ export class PlayerControlService {
   }
 
   /**
-   * 发送控制命令到主应用(优化版本)
-   * 优先使用UnifiedPlayerService直接调用,提供更快的响应速度
+   * 发送控制命令到主应用
    */
   async sendControlCommand(command: WidgetCommand, params?: WidgetControlParams): Promise<boolean> {
-    const commandId = `${command}_${Date.now()}`;
-    const executionStatus: CommandExecutionStatus = {
-      command: command,
-      timestamp: Date.now(),
-      status: 'pending'
-    };
-    
-    this.commandExecutionQueue.set(commandId, executionStatus);
-    
-    try {
-      // 更新状态为执行中
-      executionStatus.status = 'executing';
-      this.commandExecutionQueue.set(commandId, executionStatus);
-      
-      // 优先尝试直接调用UnifiedPlayerService
-      if (this.unifiedPlayerService) {
-        const success = await this.executeCommandDirectly(command, params);
-        if (success) {
-          executionStatus.status = 'completed';
-          this.commandExecutionQueue.set(commandId, executionStatus);
-          
-          hilog.info(0x0000, TAG, `Control command executed directly: ${command} (${Date.now() - executionStatus.timestamp}ms)`);
-          
-          // 清理执行状态(延迟清理以便状态查询)
-          setTimeout(() => {
-            this.commandExecutionQueue.delete(commandId);
-          }, 5000);
-          
-          return true;
-        }
-      }
-      
-      // 备用方案:使用CommonEvent
-      const success = await this.sendCommandViaCommonEvent(command, params);
-      
-      if (success) {
-        executionStatus.status = 'completed';
-      } else {
-        executionStatus.status = 'failed';
-        executionStatus.error = 'CommonEvent send failed';
-      }
-      
-      this.commandExecutionQueue.set(commandId, executionStatus);
-      
-      hilog.info(0x0000, TAG, `Control command sent via CommonEvent: ${command} (${Date.now() - executionStatus.timestamp}ms)`);
-      
-      // 清理执行状态
-      setTimeout(() => {
-        this.commandExecutionQueue.delete(commandId);
-      }, 5000);
-      
-      return success;
-    } catch (error) {
-      executionStatus.status = 'failed';
-      executionStatus.error = error.message;
-      this.commandExecutionQueue.set(commandId, executionStatus);
-      
-      hilog.error(0x0000, TAG, `Failed to send control command ${command}: ${error}`);
-      
-      // 清理执行状态
-      setTimeout(() => {
-        this.commandExecutionQueue.delete(commandId);
-      }, 5000);
-      
-      return false;
-    }
-  }
-
-  /**
-   * 直接执行控制命令(通过UnifiedPlayerService)
-   */
-  private async executeCommandDirectly(command: WidgetCommand, params?: WidgetControlParams): Promise<boolean> {
-    if (!this.unifiedPlayerService) {
-      return false;
-    }
-
-    try {
-      switch (command) {
-        case 'PLAY_PAUSE':
-          const currentState = this.unifiedPlayerService.getCurrentState();
-          if (currentState.isPlaying) {
-            await this.unifiedPlayerService.pause();
-          } else {
-            await this.unifiedPlayerService.startPlayOrResumePlay();
-          }
-          break;
-          
-        case 'NEXT_SONG':
-          await this.unifiedPlayerService.playNext();
-          break;
-          
-        case 'PREV_SONG':
-          await this.unifiedPlayerService.playPrevious();
-          break;
-          
-        case 'SEEK_TO':
-          const position = params?.position ? String(params.position) : '0';
-          await this.unifiedPlayerService.seekTo(position);
-          break;
-          
-        default:
-          hilog.warn(0x0000, TAG, `Unknown command for direct execution: ${command}`);
-          return false;
-      }
-      
-      return true;
-    } catch (error) {
-      hilog.error(0x0000, TAG, `Direct command execution failed for ${command}: ${error}`);
-      return false;
-    }
-  }
-
-  /**
-   * 通过CommonEvent发送命令(备用方案)
-   */
-  private async sendCommandViaCommonEvent(command: WidgetCommand, params?: WidgetControlParams): Promise<boolean> {
     try {
       const defaultParams: WidgetControlParams = {};
       const eventData: EventData = {
@@ -328,57 +146,24 @@ export class PlayerControlService {
         source: 'widget'
       };
 
+      // 发送CommonEvent到主应用
       const publishInfo: commonEventManager.CommonEventPublishData = {
         data: JSON.stringify(eventData)
       };
-      
       await commonEventManager.publish(WIDGET_CONTROL_EVENT, publishInfo, (err) => {
         if (err) {
-          hilog.error(0x0000, TAG, `Failed to publish CommonEvent: ${err}`);
+          hilog.error(0x0000, TAG, `Failed to publish event: ${err}`);
         }
       });
 
+      hilog.info(0x0000, TAG, `Control command sent: ${command}`);
       return true;
     } catch (error) {
-      hilog.error(0x0000, TAG, `Failed to send command via CommonEvent: ${error}`);
+      hilog.error(0x0000, TAG, `Failed to send control command: ${error}`);
       return false;
     }
   }
 
-  /**
-   * 获取命令执行状态
-   */
-  getCommandExecutionStatus(commandId?: string): CommandExecutionStatus[] {
-    if (commandId) {
-      const status = this.commandExecutionQueue.get(commandId);
-      return status ? [status] : [];
-    }
-    
-    return Array.from(this.commandExecutionQueue.values());
-  }
-
-  /**
-   * 清理过期的命令执行状态
-   */
-  private cleanupExpiredCommands(): void {
-    const now = Date.now();
-    const expiredCommands: string[] = [];
-    
-    this.commandExecutionQueue.forEach((status, commandId) => {
-      if (now - status.timestamp > this.COMMAND_TIMEOUT) {
-        expiredCommands.push(commandId);
-      }
-    });
-    
-    expiredCommands.forEach(commandId => {
-      this.commandExecutionQueue.delete(commandId);
-    });
-    
-    if (expiredCommands.length > 0) {
-      hilog.info(0x0000, TAG, `Cleaned up ${expiredCommands.length} expired command statuses`);
-    }
-  }
-
   /**
    * 获取当前播放状态
    */
@@ -694,138 +479,4 @@ export class PlayerControlService {
     const secs = Math.floor(seconds % 60);
     return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
   }
-
-  // ==================== UnifiedPlayerService 状态处理方法 ====================
-
-  /**
-   * 处理UnifiedPlayerService状态变化
-   */
-  private handleUnifiedPlayerStateChange(state: PlayerState): void {
-    try {
-      hilog.info(0x0000, TAG, `📨 Widget received UnifiedPlayerService state change: isPlaying=${state.isPlaying}`);
-      
-      // 转换为WidgetData格式
-      const widgetData: WidgetData = {
-        playState: {
-          isPlaying: state.isPlaying || false,
-          isPaused: state.isPaused || true,
-          isLoading: state.isLoading || false
-        },
-        currentSong: {
-          id: state.currentSong?.id || '',
-          title: state.currentSong?.name || '暂无播放',
-          artist: state.currentSong?.artist || '未知艺术家',
-          album: state.currentSong?.album || '未知专辑',
-          coverImagePath: state.currentSong?.pixelMapPath || '',
-          duration: state.currentSong?.duration ? Number(state.currentSong.duration) : 0
-        },
-        progress: {
-          currentPosition: state.currentPosition || 0,
-          duration: state.duration || 0,
-          percentage: this.calculatePercentage(state.currentPosition || 0, state.duration || 0),
-          currentTimeText: this.formatTime(Math.floor((state.currentPosition || 0) / 1000)),
-          totalTimeText: this.formatTime(Math.floor((state.duration || 0) / 1000))
-        },
-        playlist: {
-          hasNext: state.hasNext || false,
-          hasPrevious: state.hasPrevious || false,
-          currentIndex: state.currentIndex || 0,
-          totalCount: state.totalCount || 0
-        },
-        config: {
-          size: 'medium',
-          theme: 'auto',
-          showProgress: true,
-          showCover: true
-        }
-      };
-      
-      // 更新AvSession监听器数据
-      this.avSessionListener.updateWidgetData(widgetData);
-      
-      hilog.info(0x0000, TAG, `📨 Widget state updated from UnifiedPlayerService: ${widgetData.currentSong.title}`);
-    } catch (error) {
-      hilog.error(0x0000, TAG, `❌ Failed to handle UnifiedPlayerService state change: ${error}`);
-    }
-  }
-
-  /**
-   * 处理UnifiedPlayerService歌曲变化
-   */
-  private handleUnifiedPlayerSongChange(song: VideoItem): void {
-    try {
-      hilog.info(0x0000, TAG, `📨 Widget received UnifiedPlayerService song change: ${song.name}`);
-      
-      // 获取当前缓存数据并更新歌曲信息
-      const currentData = this.avSessionListener.getCurrentWidgetData();
-      
-      const currentSong: SongInfo = {
-        id: song.id || '',
-        title: song.name || '暂无播放',
-        artist: song.artist || '未知艺术家',
-        album: song.album || '未知专辑',
-        coverImagePath: song.pixelMapPath || '',
-        duration: song.duration ? Number(song.duration) : 0
-      };
-
-      const updatedData: WidgetData = {
-        playState: currentData.playState,
-        currentSong: currentSong,
-        progress: currentData.progress,
-        playlist: currentData.playlist,
-        config: currentData.config,
-        castingInfo: currentData.castingInfo
-      };
-      
-      // 更新AvSession监听器数据
-      this.avSessionListener.updateWidgetData(updatedData);
-      
-      hilog.info(0x0000, TAG, `📨 Widget song updated from UnifiedPlayerService: ${song.name} by ${song.artist || '未知艺术家'}`);
-    } catch (error) {
-      hilog.error(0x0000, TAG, `❌ Failed to handle UnifiedPlayerService song change: ${error}`);
-    }
-  }
-
-  /**
-   * 处理UnifiedPlayerService进度变化
-   */
-  private handleUnifiedPlayerProgressChange(progress: PlayProgress): void {
-    try {
-      // 获取当前缓存数据并更新进度信息
-      const currentData = this.avSessionListener.getCurrentWidgetData();
-      
-      const progressInfo: PlayProgress = {
-        currentPosition: progress.currentPosition || 0,
-        duration: progress.duration || 0,
-        percentage: this.calculatePercentage(progress.currentPosition || 0, progress.duration || 0),
-        currentTimeText: this.formatTime(Math.floor((progress.currentPosition || 0) / 1000)),
-        totalTimeText: this.formatTime(Math.floor((progress.duration || 0) / 1000))
-      };
-
-      const updatedData: WidgetData = {
-        playState: currentData.playState,
-        currentSong: currentData.currentSong,
-        progress: progressInfo,
-        playlist: currentData.playlist,
-        config: currentData.config,
-        castingInfo: currentData.castingInfo
-      };
-      
-      // 更新AvSession监听器数据
-      this.avSessionListener.updateWidgetData(updatedData);
-      
-      hilog.info(0x0000, TAG, `📨 Widget progress updated from UnifiedPlayerService: ${updatedData.progress.percentage.toFixed(1)}%`);
-    } catch (error) {
-      hilog.error(0x0000, TAG, `❌ Failed to handle UnifiedPlayerService progress change: ${error}`);
-    }
-  }
-
-  /**
-   * 启动定期清理任务
-   */
-  private startPeriodicCleanup(): void {
-    setInterval(() => {
-      this.cleanupExpiredCommands();
-    }, 30000); // 每30秒清理一次过期命令
-  }
 }

+ 10 - 0
entry/src/main/ets/common/widget/WidgetTypes.ets

@@ -94,6 +94,15 @@ export interface WidgetConfig {
   showCover: boolean;
 }
 
+/**
+ * 图片文件信息接口
+ */
+export interface ImageFileInfo {
+  fileName: string;
+  memoryUri: string;
+  fd: number;
+}
+
 /**
  * 卡片数据接口
  */
@@ -104,6 +113,7 @@ export interface WidgetData {
   playlist: PlaylistState;
   config: WidgetConfig;
   castingInfo?: CastingInfo;
+  imageFileInfo?: ImageFileInfo; // 图片文件信息,用于本地图片处理
 }
 
 /**

+ 139 - 26
entry/src/main/ets/controller/AvSessionController.ets

@@ -21,7 +21,6 @@ import { BackgroundTaskManager } from '../common/util/BackgroundTaskManager';
 import { VideoItem } from '../viewmodel/VideoItem';
 import { ImageUtil, PreferencesUtil } from '@pura/harmony-utils';
 import { image } from '@kit.ImageKit';
-import { SettingPage } from '../pages/SettingPage';
 import { Utility } from '../common/util/Utility';
 import LyricUtil from '../common/util/LyricUtil';
 import ImageUtils from '../common/util/ImageUtils';
@@ -47,7 +46,7 @@ export class AvSessionController {
 
   public initAvSession(isVideo:boolean) {
     if(isVideo){
-      let isBgPlayOpen = PreferencesUtil.getBooleanSync(SettingPage.IS_BGPLAY_OPEN,true)
+      let isBgPlayOpen = PreferencesUtil.getBooleanSync('isBgPlayOpen',true)
       if(!isBgPlayOpen)
         return
     }
@@ -58,17 +57,25 @@ export class AvSessionController {
       return;
     }
     let type: avSession.AVSessionType = isVideo ? 'video' : 'audio';
-    avSession.createAVSession(this.context, 'sessionName', type).then(async (avSession) => {
+    avSession.createAVSession(this.context, 'TTMusic_Session', type).then(async (avSession) => {
       this.avSession = avSession;
       hilog.info(0x0000, TAG, `session create successed : sessionId : ${this.avSession.sessionId}`);
       BackgroundTaskManager.startContinuousTask(this.context);
       this.setLaunchAbility();
-      this.avSession.activate();
+      
+      // 设置扩展信息
       this.avSession.setExtras({
         requireAbilityList: ['url-cast']
       });
+      
+      // 注册控制命令监听器 - 必须在激活前注册
+      this.registerControlCommands();
+      
+      hilog.info(0x0000, TAG, 'Control commands registered, AVSession ready for metadata and activation');
+      
     }).catch((error:Error) => {
       console.error('Failed to create AVSession:', error);
+      hilog.error(0x0000, TAG, `Failed to create AVSession: ${error}`);
     });
   }
 
@@ -128,48 +135,79 @@ export class AvSessionController {
     }
   }
 
-  public async setAVMetadataMusic(curSource: VideoItem, duration: number,lyricContent?:string) {
+  public async setAVMetadataMusic(curSource: VideoItem, duration: number, lyricContent?: string) {
     if (curSource === undefined) {
       hilog.error(0x0000, TAG, 'SetAVMetadata Error, curSource is null');
       return;
     }
     try {
       BackgroundTaskManager.startContinuousTask(this.context);
-      let pixelMapPath:string|undefined = curSource.pixelMapPath
+      let pixelMapPath: string | undefined = curSource.pixelMapPath
 
-      let imagePixMap: PixelMap|string ;
-      if(pixelMapPath){
+      let imagePixMap: PixelMap | string;
+      if (pixelMapPath) {
         imagePixMap = await ImageUtils.imagePathToPixelMap(pixelMapPath)
-      }else{
+      } else {
         imagePixMap = await ImageUtil.getPixelMapFromMedia($r('app.media.ic_avatar2'));
       }
       let lyric = ''
-      if(lyricContent)
+      if (lyricContent)
         lyric = LyricUtil.convertLyricToSimpleLrc(lyricContent)
 
-      hilog.info(0x0000, TAG, 'onecold SetAVMetadata successfully curSource.pixelMapPath '+curSource.pixelMapPath);
+      hilog.info(0x0000, TAG, 'Setting AVMetadata with required fields');
+      
+      // 验证duration是否有效
+      let validDuration = 0;
+      if (typeof duration === 'number' && !isNaN(duration) && duration > 0) {
+        validDuration = Math.floor(duration); // 确保是整数
+      } else {
+        hilog.warn(0x0000, TAG, `Invalid duration received: ${duration} (type: ${typeof duration}), using 0 instead`);
+      }
+      
+      // 按照官方文档要求,设置必要的元数据:标题、副标题/歌手、封面图
       let metadata: avSession.AVMetadata = {
         assetId: `${curSource.filePath}`,
-        title: curSource.name,
-        filter: avSession.ProtocolType.TYPE_CAST_PLUS_STREAM|avSession.ProtocolType.TYPE_DLNA,
-        artist: curSource.artist,
-        mediaImage: imagePixMap,
-        duration: duration,
-        lyric:lyric,
+        title: curSource.name || '未知标题', // 必需:标题
+        artist: curSource.artist || '未知艺术家', // 必需:副标题/歌手
+        mediaImage: imagePixMap, // 必需:封面图
+        album: curSource.album || '未知专辑',
+        duration: validDuration, // 时长,单位:毫秒,确保是有效数字
+        lyric: lyric,
+        filter: avSession.ProtocolType.TYPE_CAST_PLUS_STREAM | avSession.ProtocolType.TYPE_DLNA,
       };
+      
+      hilog.info(0x0000, TAG, `Setting AVMetadata - Title: ${metadata.title}, Artist: ${metadata.artist}, Duration: ${validDuration}ms (original: ${duration}, type: ${typeof duration})`);
 
       if (this.avSession) {
-        this.avSession.setAVMetadata(metadata).then(() => {
-          this.avSessionMetadata = metadata;
-          hilog.info(0x0000, TAG, 'SetAVMetadata successfully');
-        }).catch((err: BusinessError) => {
-          hilog.error(0x0000, TAG, `SetAVMetadata BusinessError: code: ${err.code}, message: ${err.message}`);
-        });
+        // 设置元数据
+        await this.avSession.setAVMetadata(metadata);
+        this.avSessionMetadata = metadata;
+        hilog.info(0x0000, TAG, 'AVMetadata set successfully');
+        
+        // 按照官方文档:激活接口要在元数据、控制命令注册完成之后再执行
+        // 直接激活AVSession
+        await this.avSession.activate();
+        hilog.info(0x0000, TAG, 'AVSession activated successfully - should now be visible in system media controls');
+        
+        // 设置初始播放状态 - 根据文档,这是必需的
+        const initialPlaybackState: avSession.AVPlaybackState = {
+          state: avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
+          position: {
+            elapsedTime: 0,
+            updateTime: Date.now()
+          },
+          bufferedTime: 0,
+          loopMode: avSession.LoopMode.LOOP_MODE_SEQUENCE,
+          isFavorite: false
+        };
+        
+        this.setAvSessionPlayState(initialPlaybackState);
+        hilog.info(0x0000, TAG, 'Initial playback state set - AVSession should now be visible in system controls');
       }
     } catch (error) {
-      console.warn(' setAVMetadataMusic:', error.message);
+      console.warn('setAVMetadataMusic error:', error.message);
+      hilog.error(0x0000, TAG, `SetAVMetadata error: ${error}`);
     }
-
   }
 
   public setAvSessionPlayState(playbackState: avSession.AVPlaybackState) {
@@ -179,9 +217,84 @@ export class AvSessionController {
         if (err) {
           hilog.error(0x0000, TAG, `SetAVPlaybackState BusinessError: code: ${err.code}, message: ${err.message}`);
         } else {
-          hilog.info(0x0000, TAG, 'SetAVPlaybackState successfully');
+          hilog.info(0x0000, TAG, `SetAVPlaybackState successfully - State: ${playbackState.state}, Position: ${playbackState.position?.elapsedTime}ms`);
         }
       });
+    } else {
+      hilog.error(0x0000, TAG, 'Cannot set playback state: AVSession is null');
+    }
+  }
+
+  /**
+   * 注册控制命令监听器
+   * 根据官方文档,必须在激活前注册所有需要的控制命令
+   */
+  private registerControlCommands(): void {
+    if (!this.avSession) {
+      hilog.error(0x0000, TAG, 'Cannot register commands: AVSession is null');
+      return;
+    }
+
+    try {
+      // 注册播放命令
+      this.avSession.on('play', () => {
+        hilog.info(0x0000, TAG, 'AVSession: Received play command');
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册暂停命令
+      this.avSession.on('pause', () => {
+        hilog.info(0x0000, TAG, 'AVSession: Received pause command');
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册停止命令
+      this.avSession.on('stop', () => {
+        hilog.info(0x0000, TAG, 'AVSession: Received stop command');
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册下一首命令
+      this.avSession.on('playNext', () => {
+        hilog.info(0x0000, TAG, 'AVSession: Received playNext command');
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册上一首命令
+      this.avSession.on('playPrevious', () => {
+        hilog.info(0x0000, TAG, 'AVSession: Received playPrevious command');
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册进度控制命令
+      this.avSession.on('seek', (time: number) => {
+        hilog.info(0x0000, TAG, `AVSession: Received seek command to ${time}ms`);
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      // 注册循环模式命令
+      this.avSession.on('setLoopMode', (mode: avSession.LoopMode) => {
+        hilog.info(0x0000, TAG, `AVSession: Received setLoopMode command: ${mode}`);
+        // 这里会通过UnifiedPlayerService的监听器处理
+      });
+
+      hilog.info(0x0000, TAG, 'All control commands registered successfully');
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to register control commands: ${error}`);
+    }
+  }
+
+  /**
+   * 检查AVSession状态
+   */
+  public checkAvSessionStatus(): void {
+    if (this.avSession) {
+      hilog.info(0x0000, TAG, `AVSession status - ID: ${this.avSession.sessionId}`);
+      if (this.avSessionMetadata) {
+        hilog.info(0x0000, TAG, `AVSession metadata - Title: ${this.avSessionMetadata.title}, Artist: ${this.avSessionMetadata.artist}`);
+      }
+    } else {
+      hilog.warn(0x0000, TAG, 'AVSession is null');
     }
   }
 

+ 221 - 19
entry/src/main/ets/entryability/EntryAbility.ets

@@ -14,17 +14,63 @@ import { AbilityConstant, Want } from '@kit.AbilityKit';
 import { BusinessError, emitter } from '@kit.BasicServicesKit';
 import { AppUtil, ArrayUtil, GlobalContext, LogUtil, StrUtil } from '@pura/harmony-utils';
 import { rpc } from '@kit.IPCKit';
-
 import { Utility } from '../common/util/Utility';
 import { WXApi, WXEventHandler } from '../common/util/WXApiWrap';
 import { UnifiedPlayerService } from '../common/service/UnifiedPlayerService';
 import { WidgetRegistrationFix } from '../common/widget/WidgetRegistrationFix';
-
 import { systemShare } from '@kit.ShareKit';
 import { SpiderMan } from '@simplepeng/spider-man';
 import { smartMobilityCommon } from '@kit.CarKit';
 
 
+
+/**
+ * 播放状态广播数据接口
+ */
+interface PlayStateBroadcast {
+  isPlaying: boolean;
+  isPaused: boolean;
+  isLoading: boolean;
+}
+
+interface SongBroadcast {
+  id: string;
+  title: string;
+  artist: string;
+  album: string;
+  coverImagePath: string;
+  duration: number;
+}
+
+interface ProgressBroadcast {
+  currentPosition: number;
+  duration: number;
+  percentage: number;
+  currentTimeText: string;
+  totalTimeText: string;
+}
+
+interface PlaylistBroadcast {
+  hasNext: boolean;
+  hasPrevious: boolean;
+  currentIndex: number;
+  totalCount: number;
+}
+
+interface BroadcastData {
+  playState: PlayStateBroadcast;
+  currentSong: SongBroadcast;
+  progress: ProgressBroadcast;
+  playlist: PlaylistBroadcast;
+}
+
+interface PublishInfo {
+  data: string;
+}
+
+interface EventDataWrapper {
+  data: BroadcastData;
+}
 /**
  * RPC通信返回类型的实现,用于RPC通信数据序列化和反序列化
  */
@@ -111,35 +157,27 @@ export default class EntryAbility extends UIAbility {
         // 注册卡片call事件监听器
         this.registerWidgetCallListeners();
         
-        // 初始化统一播放器服务(与主应用共享)
-        try {
-            await UnifiedPlayerService.getInstance().initialize(this.context);
-            hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService initialized successfully');
-        } catch (error) {
-            hilog.error(0x0000, 'Heanup2', `❌ Failed to initialize UnifiedPlayerService: ${error}`);
-        }
+        // 异步初始化统一播放器服务,避免阻塞生命周期
+        this.initializePlayerServiceAsync();
 
         // 执行卡片注册修复(异步执行,不阻塞启动)
         this.fixWidgetRegistrationAsync();
 
-        setTimeout(async ()=>{
-            this.loadDoWant(want)
-            await this.handleParam(want)
-        },2000)
+        // 异步处理Want参数,避免阻塞生命周期
+        this.handleWantAsync(want);
 
         this.handleWeChatCallIfNeed(want)
 
         this.getHiCarStatus()
-
     }
 
     async onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
         hilog.info(0x0000, 'Heanup2', `onNewWant, want=${JSON.stringify(want)}`);
         super.onNewWant(want, launchParam);
-        this.loadDoWant(want)
-        await this.handleParam(want)
+        
+        // 异步处理Want参数,避免阻塞生命周期
+        this.handleWantAsync(want);
         this.handleWeChatCallIfNeed(want)
-
     }
 
     private handleWeChatCallIfNeed(want: Want) {
@@ -293,12 +331,26 @@ export default class EntryAbility extends UIAbility {
 
     onForeground() {
         // Ability has brought to foreground
-        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onForeground');
+        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onForeground start');
+        
+        // 异步处理前台逻辑,避免阻塞生命周期
+        setTimeout(() => {
+            this.handleForegroundAsync();
+        }, 10);
+        
+        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onForeground end');
     }
 
     onBackground() {
         // Ability has back to background
-        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground');
+        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground start');
+        
+        // 异步处理后台逻辑,避免阻塞生命周期
+        setTimeout(() => {
+            this.handleBackgroundAsync();
+        }, 10);
+        
+        hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground end');
     }
 
 
@@ -484,6 +536,77 @@ export default class EntryAbility extends UIAbility {
         }
     }
 
+    /**
+     * 异步初始化播放器服务,避免阻塞生命周期
+     */
+    private initializePlayerServiceAsync(): void {
+        // 使用 setTimeout 将初始化操作移到下一个事件循环
+        setTimeout(async () => {
+            try {
+                hilog.info(0x0000, 'Heanup2', '🔄 开始异步初始化 UnifiedPlayerService');
+                await UnifiedPlayerService.getInstance().initialize(this.context);
+                hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService 异步初始化成功');
+                
+                // 延迟广播当前状态,确保卡片能接收到初始状态
+                setTimeout(() => {
+                    this.broadcastCurrentPlayerState();
+                }, 1000);
+            } catch (error) {
+                hilog.error(0x0000, 'Heanup2', `❌ UnifiedPlayerService 异步初始化失败: ${error}`);
+            }
+        }, 100); // 短延迟,让生命周期方法先完成
+    }
+
+    /**
+     * 异步处理前台逻辑
+     */
+    private handleForegroundAsync(): void {
+        try {
+            hilog.info(0x0000, 'Heanup2', '🔄 处理前台逻辑');
+            
+            // 确保播放器服务可用
+            const playerService = UnifiedPlayerService.getInstance();
+            if (playerService) {
+                // 广播当前状态给卡片
+                this.broadcastCurrentPlayerState();
+            }
+            
+            hilog.info(0x0000, 'Heanup2', '✅ 前台逻辑处理完成');
+        } catch (error) {
+            hilog.error(0x0000, 'Heanup2', `❌ 前台逻辑处理失败: ${error}`);
+        }
+    }
+
+    /**
+     * 异步处理后台逻辑
+     */
+    private handleBackgroundAsync(): void {
+        try {
+            hilog.info(0x0000, 'Heanup2', '🔄 处理后台逻辑');
+            
+            // 后台时可以执行一些清理或保存操作
+            // 但要确保不会阻塞生命周期
+            
+            hilog.info(0x0000, 'Heanup2', '✅ 后台逻辑处理完成');
+        } catch (error) {
+            hilog.error(0x0000, 'Heanup2', `❌ 后台逻辑处理失败: ${error}`);
+        }
+    }
+
+    /**
+     * 异步处理Want参数,避免阻塞生命周期
+     */
+    private handleWantAsync(want: Want): void {
+        setTimeout(async () => {
+            try {
+                this.loadDoWant(want);
+                await this.handleParam(want);
+            } catch (error) {
+                hilog.error(0x0000, 'Heanup2', `❌ 处理Want参数失败: ${error}`);
+            }
+        }, 200);
+    }
+
     /**
      * 异步执行卡片注册修复
      */
@@ -498,4 +621,83 @@ export default class EntryAbility extends UIAbility {
             }
         }, 3000);
     }
+
+    /**
+     * 广播当前播放器状态给卡片
+     */
+    private broadcastCurrentPlayerState(): void {
+        try {
+            const unifiedService = UnifiedPlayerService.getInstance();
+            const currentState = unifiedService.getCurrentState();
+            const currentSong = unifiedService.getCurrentSong();
+            const playlist = unifiedService.getPlaylist();
+            const currentIndex = unifiedService.getCurrentIndex();
+            
+            if (currentSong) {
+                // 构建播放器状态广播数据
+                const broadcastData: BroadcastData = {
+                    playState: {
+                        isPlaying: currentState.isPlaying || false,
+                        isPaused: currentState.isPaused || true,
+                        isLoading: currentState.isLoading || false
+                    } as PlayStateBroadcast,
+                    currentSong: {
+                        id: currentSong.id || '',
+                        title: currentSong.name || '暂无播放',
+                        artist: currentSong.artist || '未知艺术家',
+                        album: currentSong.album || '未知专辑',
+                        coverImagePath: currentSong.pixelMapPath || '',
+                        duration: currentSong.duration ? Number(currentSong.duration) : 0
+                    } as SongBroadcast,
+                    progress: {
+                        currentPosition: currentState.currentPosition || 0,
+                        duration: currentState.duration || 0,
+                        percentage: this.calculatePercentage(currentState.currentPosition || 0, currentState.duration || 0),
+                        currentTimeText: this.formatTime(Math.floor((currentState.currentPosition || 0) / 1000)),
+                        totalTimeText: this.formatTime(Math.floor((currentState.duration || 0) / 1000))
+                    } as ProgressBroadcast,
+                    playlist: {
+                        hasNext: currentState.hasNext || false,
+                        hasPrevious: currentState.hasPrevious || false,
+                        currentIndex: currentIndex,
+                        totalCount: playlist.length
+                    } as PlaylistBroadcast
+                };
+                
+                // 发送状态变化事件
+                const publishInfo: PublishInfo = {
+                    data: JSON.stringify(broadcastData)
+                };
+                
+                // 使用emitter发送事件
+                const eventData: EventDataWrapper = {
+                    data: broadcastData
+                };
+                emitter.emit({ eventId: 1001 }, eventData); // 使用特定的事件ID
+                
+                hilog.info(0x0000, 'Heanup2', `📡 Broadcasted current player state: ${currentSong.name}, isPlaying=${currentState.isPlaying}`);
+            } else {
+                hilog.info(0x0000, 'Heanup2', '📡 No current song to broadcast');
+            }
+        } catch (error) {
+            hilog.error(0x0000, 'Heanup2', `❌ Failed to broadcast current player state: ${error}`);
+        }
+    }
+
+    /**
+     * 计算播放进度百分比
+     */
+    private calculatePercentage(current: number, total: number): number {
+        if (total <= 0) return 0;
+        return Math.min(100, Math.max(0, (current / total) * 100));
+    }
+
+    /**
+     * 格式化时间显示
+     */
+    private formatTime(seconds: number): string {
+        const mins = Math.floor(seconds / 60);
+        const secs = Math.floor(seconds % 60);
+        return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
+    }
 }

+ 238 - 271
entry/src/main/ets/entryformability/EntryFormAbility.ets

@@ -15,21 +15,13 @@ import { PreferencesUtil } from '../common/utils/PreferencesUtil';
 
 const TAG = 'Heanup';
 
-/**
- * 同步状态信息接口
- */
-interface SyncStatusInfo {
-  lastUpdate: number;
-  source: string;
-  processId: string;
-}
+
 
 /**
- * 扩展的卡片数据接口,支持图片传递和同步状态
+ * 扩展的卡片数据接口,支持图片传递
  */
 interface ExtendedWidgetData extends FormattedWidgetData {
   formImages?: Record<string, number>;
-  syncStatus?: SyncStatusInfo;
 }
 
 /**
@@ -243,13 +235,8 @@ implements SizeChangeListener {
 
       hilog.info(0x0000, TAG, `Heanup widget ${formId} calling formProvider.updateForm with isPlaying=${adaptedData.isPlaying}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}, coverImage=${adaptedData.coverImage || 'empty'}`);
 
-      // 检查是否有网络图片需要下载
-      if (adaptedData.coverImage && this.isNetworkUrl(adaptedData.coverImage)) {
-        this.updateWidgetWithNetworkImage(formId, adaptedData, retryCount);
-      } else {
-        // 没有网络图片,直接更新
-        this.updateWidgetDirectly(formId, adaptedData, retryCount);
-      }
+      // 使用统一的图片处理方法
+      this.updateWidgetWithImage(formId, adaptedData, retryCount);
     } catch (error) {
       hilog.error(0x0000, TAG, `Heanup widget ${formId} process error: ${error}`);
 
@@ -265,32 +252,111 @@ implements SizeChangeListener {
   /**
    * 直接更新卡片(无网络图片)
    */
-  private async updateWidgetDirectly(formId: string, adaptedData: ExtendedWidgetData, retryCount: number = 0): Promise<void> {
-    const updateStartTime = Date.now();
-    
-    try {
-      const formData = formBindingData.createFormBindingData(adaptedData);
-      await formProvider.updateForm(formId, formData);
-      
-      const updateDuration = Date.now() - updateStartTime;
-      hilog.info(0x0000, TAG, `Widget ${formId} updated directly in ${updateDuration}ms: isPlaying=${adaptedData.isPlaying}, title=${adaptedData.songTitle}, progress=${adaptedData.progressPercentage?.toFixed(1)}%, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}`);
-      
-    } catch (error) {
-      const updateDuration = Date.now() - updateStartTime;
-      hilog.error(0x0000, TAG, `Widget ${formId} direct update failed after ${updateDuration}ms: ${error}`);
+  private updateWidgetDirectly(formId: string, adaptedData: ExtendedWidgetData, retryCount: number = 0): void {
+    const formData = formBindingData.createFormBindingData(adaptedData);
+    formProvider.updateForm(formId, formData).then(() => {
+      hilog.info(0x0000, TAG, `Heanup widget ${formId} updated successfully: isPlaying=${adaptedData.isPlaying}, title=${adaptedData.songTitle}, hasNext=${adaptedData.hasNext}, hasPrevious=${adaptedData.hasPrevious}`);
+    }).catch(() => {
+      hilog.error(0x0000, TAG, `Heanup widget ${formId} update failed, retry count: ${retryCount}`);
 
       // 重试机制:最多重试2次
       if (retryCount < 2) {
-        hilog.warn(0x0000, TAG, `Widget ${formId} update failed, retrying... (${retryCount + 1}/3)`);
-        
-        const retryDelay = 1000 * (retryCount + 1);
-        setTimeout(async () => {
-          await this.updateWidgetDirectly(formId, adaptedData, retryCount + 1);
-        }, retryDelay);
+        setTimeout(() => {
+          this.updateWidgetDirectly(formId, adaptedData, retryCount + 1);
+        }, 1000 * (retryCount + 1)); // 递增延迟
+      }
+    });
+  }
+
+  /**
+   * 统一处理图片更新
+   */
+  private async updateWidgetWithImage(formId: string, adaptedData: ExtendedWidgetData, retryCount: number = 0): Promise<void> {
+    try {
+      if (!adaptedData.coverImage || adaptedData.coverImage.trim() === '') {
+        // 没有封面图片,直接更新
+        this.updateWidgetDirectly(formId, adaptedData, retryCount);
+        return;
+      }
+
+      hilog.info(0x0000, TAG, `Heanup widget ${formId} processing image: ${adaptedData.coverImage}`);
+
+      if (this.isNetworkUrl(adaptedData.coverImage)) {
+        // 处理网络图片
+        await this.updateWidgetWithNetworkImage(formId, adaptedData, retryCount);
+      } else if (this.isLocalFileUri(adaptedData.coverImage)) {
+        // 处理本地文件URI
+        await this.updateWidgetWithLocalImage(formId, adaptedData, retryCount);
       } else {
-        hilog.error(0x0000, TAG, `Widget ${formId} update failed after ${retryCount + 1} attempts, giving up`);
-        throw new Error(`Widget ${formId} update failed after ${retryCount + 1} attempts: ${error}`);
+        // 其他情况,可能是相对路径或其他格式,直接使用
+        hilog.info(0x0000, TAG, `Heanup widget ${formId} using image path as-is: ${adaptedData.coverImage}`);
+        this.updateWidgetDirectly(formId, adaptedData, retryCount);
       }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Heanup widget ${formId} image update error: ${error}`);
+      // 失败时使用默认数据
+      const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { coverImage: '' });
+      this.updateWidgetDirectly(formId, dataWithoutImage, retryCount);
+    }
+  }
+
+  /**
+   * 处理本地文件URI图片
+   */
+  private async updateWidgetWithLocalImage(formId: string, adaptedData: ExtendedWidgetData, retryCount: number = 0): Promise<void> {
+    try {
+      const localFileUri: string = adaptedData.coverImage;
+      hilog.info(0x0000, TAG, `Heanup widget ${formId} processing local image: ${localFileUri}`);
+
+      // 先用无图片的数据快速更新一次,确保界面响应性
+      const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { 
+        coverImage: '',
+        imgName: '',
+        formImages: undefined 
+      });
+      this.updateWidgetDirectly(formId, dataWithoutImage, 0);
+
+      // 处理本地图片文件
+      const fileName = await this.processLocalImageFile(localFileUri);
+
+      if (fileName) {
+        try {
+          // 按照官方文档要求,准备 formImages 和文件描述符
+          const imageMap: Record<string, number> = {};
+          const fileDescriptor = await this.getImageFileDescriptor(fileName);
+          imageMap[fileName] = fileDescriptor;
+
+          // 按照官方文档要求,imgName 必须与 formImages 中的 key 相同
+          const dataWithImage: ExtendedWidgetData = copyWidgetData(adaptedData, {
+            coverImage: '',  // 清空原路径
+            imgName: fileName,  // 设置图片名称用于 memory:// 协议
+            formImages: imageMap  // 必填字段,不可缺省
+          });
+
+          const formDataWithImage = formBindingData.createFormBindingData(dataWithImage);
+          await formProvider.updateForm(formId, formDataWithImage);
+
+          hilog.info(0x0000, TAG, `Heanup widget ${formId} updated with local image: ${fileName}, fd: ${fileDescriptor}`);
+        } catch (fdError) {
+          hilog.error(0x0000, TAG, `Heanup widget ${formId} failed to get file descriptor: ${fdError}`);
+          // 文件描述符获取失败,使用默认图片
+          this.updateWidgetDirectly(formId, dataWithoutImage, 0);
+        }
+      } else {
+        hilog.warn(0x0000, TAG, `Heanup widget ${formId} failed to process local image, using default`);
+        // 图片处理失败,使用默认图片
+        this.updateWidgetDirectly(formId, dataWithoutImage, 0);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Heanup widget ${formId} local image update error: ${error}`);
+
+      // 失败后回退到无图片模式
+      const dataWithoutImage: ExtendedWidgetData = copyWidgetData(adaptedData, { 
+        coverImage: '',
+        imgName: '',
+        formImages: undefined 
+      });
+      this.updateWidgetDirectly(formId, dataWithoutImage, retryCount);
     }
   }
 
@@ -345,6 +411,117 @@ implements SizeChangeListener {
     return url.startsWith('http://') || url.startsWith('https://');
   }
 
+  /**
+   * 检查是否为本地文件URI
+   */
+  private isLocalFileUri(url: string): boolean {
+    return url.startsWith('file://');
+  }
+
+  /**
+   * 处理本地图片文件,将其复制到卡片可访问的临时目录
+   */
+  private async processLocalImageFile(fileUri: string): Promise<string | null> {
+    try {
+      hilog.info(0x0000, TAG, `Processing local image file: ${fileUri}`);
+
+      // 检查缓存
+      if (this.imageCache.has(fileUri)) {
+        const fileName = this.imageCache.get(fileUri)!;
+        hilog.info(0x0000, TAG, `Using cached local image: ${fileName} for ${fileUri}`);
+        
+        // 验证缓存文件是否仍然存在 - 使用 FormExtensionAbility 的 tempDir
+        const formTempDir = this.context.getApplicationContext().tempDir;
+        const tempFilePath = `${formTempDir}/${fileName}`;
+        if (fileIo.accessSync(tempFilePath)) {
+          return fileName;
+        } else {
+          // 缓存文件已不存在,清除缓存记录
+          this.imageCache.delete(fileUri);
+          hilog.warn(0x0000, TAG, `Cached file no longer exists, will reprocess: ${fileName}`);
+        }
+      }
+
+      // 检查是否正在处理
+      if (this.downloadingImages.has(fileUri)) {
+        hilog.info(0x0000, TAG, `Local image already processing, waiting: ${fileUri}`);
+        const existingPromise = this.downloadingImages.get(fileUri);
+        if (existingPromise) {
+          return await existingPromise;
+        }
+      }
+
+      // 开始处理本地文件
+      const processPromise = this.performLocalImageCopy(fileUri);
+      this.downloadingImages.set(fileUri, processPromise);
+
+      const fileName = await processPromise;
+
+      // 清理处理状态
+      this.downloadingImages.delete(fileUri);
+
+      if (fileName) {
+        this.imageCache.set(fileUri, fileName);
+        hilog.info(0x0000, TAG, `Local image processed successfully: ${fileName}`);
+      }
+
+      return fileName;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to process local image ${fileUri}: ${error}`);
+      this.downloadingImages.delete(fileUri);
+      return null;
+    }
+  }
+
+  /**
+   * 执行本地图片文件复制
+   */
+  private async performLocalImageCopy(fileUri: string): Promise<string | null> {
+    try {
+      hilog.info(0x0000, TAG, `Copying local image file: ${fileUri}`);
+
+      // 转换 file:// URI 为实际文件路径
+      const realPath = fileUri.replace('file://', '');
+      
+      // 检查源文件是否存在
+      if (!fileIo.accessSync(realPath)) {
+        hilog.error(0x0000, TAG, `Source image file does not exist: ${realPath}`);
+        return null;
+      }
+
+      // 生成目标文件名(包含时间戳和随机数,确保每次都不同)
+      const fileExtension = this.getFileExtension(realPath) || 'jpg';
+      const fileName = `widget_local_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.${fileExtension}`;
+      
+      // 使用 FormExtensionAbility 的 tempDir(官方文档要求)
+      const formTempDir = this.context.getApplicationContext().tempDir;
+      const tempFilePath = `${formTempDir}/${fileName}`;
+
+      hilog.info(0x0000, TAG, `Using FormExtensionAbility tempDir: ${formTempDir}`);
+
+      // 复制文件到临时目录
+      fileIo.copyFileSync(realPath, tempFilePath);
+
+      hilog.info(0x0000, TAG, `Local image copied successfully: ${realPath} -> ${tempFilePath}`);
+      return fileName;
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to copy local image: ${error}`);
+      return null;
+    }
+  }
+
+  /**
+   * 获取文件扩展名
+   */
+  private getFileExtension(filePath: string): string | null {
+    const lastDotIndex = filePath.lastIndexOf('.');
+    if (lastDotIndex === -1 || lastDotIndex === filePath.length - 1) {
+      return null;
+    }
+    return filePath.substring(lastDotIndex + 1).toLowerCase();
+  }
+
   /**
    * 下载网络图片
    */
@@ -404,17 +581,21 @@ implements SizeChangeListener {
       });
 
       if (response.responseCode === http.ResponseCode.OK && response.result) {
-        // 生成文件名
-        const fileName = 'cover_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
-        const tempDir = this.context.getApplicationContext().tempDir;
-        const filePath = tempDir + '/' + fileName;
+        // 生成文件名(确保每次都不同,符合官方文档要求)
+        const fileName = `widget_cover_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`;
+        
+        // 使用 FormExtensionAbility 的 tempDir(官方文档要求)
+        const formTempDir = this.context.getApplicationContext().tempDir;
+        const filePath = `${formTempDir}/${fileName}`;
+
+        hilog.info(0x0000, TAG, `Using FormExtensionAbility tempDir for download: ${formTempDir}`);
 
         // 保存文件
         const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
         await fileIo.write(file.fd, response.result as ArrayBuffer);
         fileIo.closeSync(file);
         
-        hilog.info(0x0000, TAG, `Image downloaded successfully: ${fileName}`);
+        hilog.info(0x0000, TAG, `Network image downloaded successfully: ${fileName}`);
         httpRequest.destroy();
         return fileName;
       } else {
@@ -433,8 +614,11 @@ implements SizeChangeListener {
    */
   private async getImageFileDescriptor(fileName: string): Promise<number> {
     try {
-      const tempDir = this.context.getApplicationContext().tempDir;
-      const filePath = tempDir + '/' + fileName;
+      // 使用 FormExtensionAbility 的 tempDir(官方文档要求)
+      const formTempDir = this.context.getApplicationContext().tempDir;
+      const filePath = `${formTempDir}/${fileName}`;
+      
+      hilog.info(0x0000, TAG, `Opening file for descriptor: ${filePath}`);
       const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY);
       
       // 注意:文件描述符会被系统自动管理,不需要手动关闭
@@ -478,8 +662,6 @@ implements SizeChangeListener {
     // 持久化保存 Form ID(异步执行,不阻塞返回)
     this.saveFormIdToPersistence(formId).then(() => {
       hilog.info(0x0000, TAG, `💾 Form ID persistence completed for: ${formId}`);
-    }).catch(() => {
-      hilog.error(0x0000, TAG, `❌ Form ID persistence failed for ${formId}`);
     })
 
     // 检测卡片尺寸并注册到全局管理器
@@ -717,192 +899,23 @@ implements SizeChangeListener {
   }
 
   /**
-   * 更新卡片数据(增强版本 - 支持实时同步
+   * 更新卡片数据(简化版本
    */
-  private async updateWidgetData(formId: string, forceUpdate: boolean = false): Promise<void> {
-    const updateStartTime = Date.now();
-    
+  private async updateWidgetData(formId: string): Promise<void> {
     try {
-      // 防抖处理,避免过于频繁的更新(除非强制更新)
-      if (!forceUpdate && Date.now() - this.lastUpdateTime < this.updateDebounceDelay) {
-        hilog.info(0x0000, TAG, `Widget ${formId} update skipped due to debounce`);
-        return;
-      }
-      
-      this.lastUpdateTime = Date.now();
-      
-      // 获取当前播放状态(优化:支持缓存)
       const currentState = await this.playerControlService.getCurrentPlayState();
-      
-      // 验证状态数据完整性
-      if (!this.validateWidgetData(currentState)) {
-        hilog.warn(0x0000, TAG, `Invalid widget data for ${formId}, using fallback`);
-        // 使用备用数据或重新请求
-        await this.handleInvalidWidgetData(formId);
-        return;
-      }
 
       // 获取卡片当前尺寸
       const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
 
-      // 适配数据到当前尺寸
+      // 适配数据到当前尺寸并直接更新
       const adaptedData = this.layoutManager.adaptDataForSize(currentState, currentSize);
-      
-      // 添加实时状态标记
-      const syncStatus: SyncStatusInfo = {
-        lastUpdate: Date.now(),
-        source: 'realtime_sync',
-        processId: this.processStartTime.toString()
-      };
-
-      const enhancedData: ExtendedWidgetData = this.copyFormattedWidgetData(adaptedData, {
-        timestamp: Date.now(),
-        syncStatus: syncStatus
-      });
-
-      // 检查是否需要下载网络图片
-      if (this.needsImageDownload(enhancedData)) {
-        await this.handleImageDownloadAndUpdate(formId, enhancedData);
-      } else {
-        // 直接更新卡片
-        await this.updateWidgetDirectly(formId, enhancedData);
-      }
-      
-      const updateDuration = Date.now() - updateStartTime;
-      hilog.info(0x0000, TAG, `Widget ${formId} updated successfully in ${updateDuration}ms: isPlaying=${enhancedData.isPlaying}, progress=${enhancedData.progressPercentage?.toFixed(1)}%`);
-      
-    } catch (error) {
-      const updateDuration = Date.now() - updateStartTime;
-      hilog.error(0x0000, TAG, `Failed to update widget ${formId} after ${updateDuration}ms: ${error}`);
-      
-      // 尝试恢复性更新
-      await this.attemptRecoveryUpdate(formId);
-    }
-  }
-
-  /**
-   * 验证卡片数据完整性
-   */
-  private validateWidgetData(data: WidgetData): boolean {
-    return !!(
-      data &&
-      data.playState &&
-      data.currentSong &&
-      data.progress &&
-      data.playlist &&
-      typeof data.playState.isPlaying === 'boolean' &&
-      typeof data.currentSong.title === 'string' &&
-      typeof data.progress.percentage === 'number'
-    );
-  }
-
-  /**
-   * 处理无效的卡片数据
-   */
-  private async handleInvalidWidgetData(formId: string): Promise<void> {
-    try {
-      hilog.warn(0x0000, TAG, `Handling invalid widget data for ${formId}`);
-      
-      // 强制重新连接播放器服务
-      await this.playerControlService.forceReconnect();
-      
-      // 等待一段时间后重试
-      setTimeout(async () => {
-        await this.updateWidgetData(formId, true);
-      }, 1000);
-      
-    } catch (error) {
-      hilog.error(0x0000, TAG, `Failed to handle invalid widget data: ${error}`);
-    }
-  }
-
-  /**
-   * 检查是否需要下载图片
-   */
-  private needsImageDownload(data: ExtendedWidgetData): boolean {
-    return !!(
-      data.coverImage &&
-      data.coverImage.startsWith('http') &&
-      !this.imageCache.has(data.coverImage)
-    );
-  }
-
-  /**
-   * 处理图片下载并更新卡片
-   */
-  private async handleImageDownloadAndUpdate(formId: string, data: ExtendedWidgetData): Promise<void> {
-    try {
-      if (!data.coverImage) {
-        await this.updateWidgetDirectly(formId, data);
-        return;
-      }
-      
-      // 检查是否正在下载
-      if (this.downloadingImages.has(data.coverImage)) {
-        const fileName = await this.downloadingImages.get(data.coverImage);
-        if (fileName) {
-          const formImages: Record<string, number> = {};
-          formImages[fileName] = 0;
-          const dataWithImage: ExtendedWidgetData = this.copyFormattedWidgetData(data, {
-            imgName: fileName,
-            formImages: formImages
-          });
-          await this.updateWidgetDirectly(formId, dataWithImage);
-        } else {
-          await this.updateWidgetDirectly(formId, data);
-        }
-        return;
-      }
-      
-      // 启动图片下载
-      const downloadPromise = this.downloadNetworkImage(data.coverImage);
-      this.downloadingImages.set(data.coverImage, downloadPromise);
-      
-      const fileName = await downloadPromise;
-      
-      if (fileName) {
-        this.imageCache.set(data.coverImage, fileName);
-        const formImages: Record<string, number> = {};
-        formImages[fileName] = 0;
-        const dataWithImage: ExtendedWidgetData = this.copyFormattedWidgetData(data, {
-          imgName: fileName,
-          formImages: formImages
-        });
-        await this.updateWidgetDirectly(formId, dataWithImage);
-      } else {
-        await this.updateWidgetDirectly(formId, data);
-      }
-      
-    } catch (error) {
-      hilog.error(0x0000, TAG, `Failed to handle image download: ${error}`);
-      await this.updateWidgetDirectly(formId, data);
-    } finally {
-      if (data.coverImage) {
-        this.downloadingImages.delete(data.coverImage);
-      }
-    }
-  }
+      const formData = formBindingData.createFormBindingData(adaptedData);
+      await formProvider.updateForm(formId, formData);
 
-  /**
-   * 尝试恢复性更新
-   */
-  private async attemptRecoveryUpdate(formId: string): Promise<void> {
-    try {
-      hilog.info(0x0000, TAG, `Attempting recovery update for widget ${formId}`);
-      
-      // 使用默认数据进行恢复性更新
-      const defaultData = this.getDefaultWidgetData();
-      const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
-      const formattedData = this.layoutManager.adaptDataForSize(defaultData, currentSize);
-      
-      // 转换为ExtendedWidgetData
-      const adaptedData: ExtendedWidgetData = this.copyFormattedWidgetData(formattedData, {});
-      
-      await this.updateWidgetDirectly(formId, adaptedData, 0);
-      
-      hilog.info(0x0000, TAG, `Recovery update completed for widget ${formId}`);
+      hilog.info(0x0000, TAG, `Heanup widget ${formId} updated successfully with size: ${currentSize}, isPlaying=${adaptedData.isPlaying}`);
     } catch (error) {
-      hilog.error(0x0000, TAG, `Recovery update failed for widget ${formId}: ${error}`);
+      hilog.error(0x0000, TAG, `Failed to update widget ${formId}: ${error}`);
     }
   }
 
@@ -941,28 +954,10 @@ implements SizeChangeListener {
       hilog.info(0x0000, TAG, `💾 Saving Form ID to persistence: ${formId}`);
       const preferencesUtil = PreferencesUtil.getInstance();
       const prefs = await preferencesUtil.getPreferences(this.context);
-      
-      // 先检查是否已存在,避免重复添加
-      const existingIds = await preferencesUtil.getFormIds(prefs);
-      if (existingIds.includes(formId)) {
-        hilog.info(0x0000, TAG, `💾 Form ID already exists: ${formId}`);
-        return;
-      }
-      
-      hilog.info(0x0000, TAG, `💾 Current persisted IDs before adding: [${existingIds.join(', ')}]`);
-      
       await preferencesUtil.addFormId(prefs, formId);
-      
-      // 简化验证,只检查是否添加成功
-      const updatedIds = await preferencesUtil.getFormIds(prefs);
-      if (updatedIds.includes(formId)) {
-        hilog.info(0x0000, TAG, `✅ Form ID saved successfully: ${formId}`);
-      } else {
-        hilog.warn(0x0000, TAG, `⚠️ Form ID save verification failed, but continuing: ${formId}`);
-      }
+      hilog.info(0x0000, TAG, `✅ Form ID saved successfully: ${formId}`);
     } catch (error) {
-      hilog.error(0x0000, TAG, `❌ Failed to save Form ID ${formId}: ${error}`);
-      // 不再抛出错误,避免阻塞卡片创建
+      hilog.error(0x0000, TAG, `❌ Failed to save Form ID: ${error}`);
     }
   }
 
@@ -980,32 +975,4 @@ implements SizeChangeListener {
       hilog.error(0x0000, TAG, `❌ Failed to remove Form ID: ${error}`);
     }
   }
-
-  /**
-   * 复制 FormattedWidgetData 对象
-   */
-  private copyFormattedWidgetData(target: FormattedWidgetData, overrides: Partial<ExtendedWidgetData>): ExtendedWidgetData {
-    return {
-      isPlaying: overrides.isPlaying !== undefined ? overrides.isPlaying : target.isPlaying,
-      isPaused: overrides.isPaused !== undefined ? overrides.isPaused : target.isPaused,
-      isLoading: overrides.isLoading !== undefined ? overrides.isLoading : target.isLoading,
-      songTitle: overrides.songTitle !== undefined ? overrides.songTitle : target.songTitle,
-      songArtist: overrides.songArtist !== undefined ? overrides.songArtist : target.songArtist,
-      songAlbum: overrides.songAlbum !== undefined ? overrides.songAlbum : target.songAlbum,
-      coverImage: overrides.coverImage !== undefined ? overrides.coverImage : target.coverImage,
-      currentTime: overrides.currentTime !== undefined ? overrides.currentTime : target.currentTime,
-      totalTime: overrides.totalTime !== undefined ? overrides.totalTime : target.totalTime,
-      progressPercentage: overrides.progressPercentage !== undefined ? overrides.progressPercentage : target.progressPercentage,
-      hasNext: overrides.hasNext !== undefined ? overrides.hasNext : target.hasNext,
-      hasPrevious: overrides.hasPrevious !== undefined ? overrides.hasPrevious : target.hasPrevious,
-      showProgress: overrides.showProgress !== undefined ? overrides.showProgress : target.showProgress,
-      showCover: overrides.showCover !== undefined ? overrides.showCover : target.showCover,
-      widgetSize: overrides.widgetSize !== undefined ? overrides.widgetSize : target.widgetSize,
-      timestamp: overrides.timestamp !== undefined ? overrides.timestamp : target.timestamp,
-      imgName: overrides.imgName !== undefined ? overrides.imgName : target.imgName,
-      formImages: overrides.formImages !== undefined ? overrides.formImages : target.formImages,
-      imageColorHex: overrides.imageColorHex !== undefined ? overrides.imageColorHex : target.imageColorHex,
-      syncStatus: overrides.syncStatus !== undefined ? overrides.syncStatus : undefined
-    };
-  }
 }

BIN
oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/.DS_Store


BIN
oh_modules/.ohpm/@alipay+blueshieldsdk@cow+0gass5tzqhymzjby2f6sd+g2xtoatqsiyvi9qsy=/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/media/.DS_Store


BIN
oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/.DS_Store


BIN
oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.32/oh_modules/@alipay/blueshieldsdk/src/main/resources/base/media/.DS_Store


BIN
oh_modules/.ohpm/@simplepeng+spider-man@1.0.1/oh_modules/@simplepeng/spider-man/.DS_Store


BIN
oh_modules/.ohpm/oh_modules/@simplepeng/spider-man/.DS_Store


BIN
oh_modules/@simplepeng/spider-man/.DS_Store