Просмотр исходного кода

桌面卡片的封面正常显示

chendeben 1 год назад
Родитель
Сommit
7c32e78342

+ 12 - 65
entry/src/main/ets/common/service/UnifiedPlayerService.ets

@@ -330,24 +330,15 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
             // 更新AVSession播放状态
             setTimeout(() => {
               this.updateSessionPlayState(true);
-              LogUtils.getInstance().LOGI('UnifiedPlayerService: AVSession updated for resume from pause');
             }, 200);
             
             // 更新卡片显示播放状态
             await this.updateWidgetsForPlayStateChange(true);
-            
-            LogUtils.getInstance().LOGI('UnifiedPlayerService: Successfully resumed from paused state');
-            console.log("Heanup2 UnifiedPlayerService: 暂停恢复播放成功");
             return;
-          } else {
-            console.log("Heanup2 UnifiedPlayerService: 播放器时长为0,需要重新准备");
           }
         } catch (error) {
-          console.log(`Heanup2 UnifiedPlayerService: 暂停恢复失败: ${error},将重新准备播放器`);
           LogUtils.getInstance().LOGI(`UnifiedPlayerService: Resume from pause failed: ${error}, will re-prepare player`);
         }
-      } else {
-        console.log(`Heanup2 UnifiedPlayerService: 不满足暂停恢复条件 - shouldResumeFromPause: ${shouldResumeFromPause}, isPausedByManager: ${isPausedByManager}, isCurrentlyPlaying: ${isCurrentlyPlaying}`);
       }
 
       // 检查文件是否存在(对于本地文件)
@@ -372,7 +363,6 @@ 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 回调中开始
       }
@@ -386,12 +376,9 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       // 重置重试计数(播放成功)
       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);
     }
@@ -405,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();
@@ -429,31 +414,17 @@ 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 {
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Pausing playback');
-      console.log("Heanup2 UnifiedPlayerService: 开始暂停播放");
-      
+
       const ijkPlayer = this.playerManager.getIjkPlayer();
-      if (ijkPlayer) {
-        const currentPosition = ijkPlayer.getCurrentPosition();
-        const duration = ijkPlayer.getDuration();
-        console.log(`Heanup2 UnifiedPlayerService: 暂停时的播放位置 ${currentPosition}ms, 总时长 ${duration}ms`);
-      }
       
       // 保存当前播放位置
       this.savePlaybackPosition();
@@ -478,20 +449,9 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       
       // 更新卡片显示暂停状态
       await this.updateWidgetsForPlayStateChange(false);
-      
-      // 验证暂停状态
-      setTimeout(() => {
-        const isManagerPaused = this.playerManager.isPausedState();
-        const stateModelState = this.stateModel.getState();
-        console.log(`Heanup2 UnifiedPlayerService: 暂停后状态验证 - Manager暂停: ${isManagerPaused}, State模型暂停: ${stateModelState.isPaused}, State模型播放: ${stateModelState.isPlaying}`);
-      }, 100);
-      
-      LogUtils.getInstance().LOGI('UnifiedPlayerService: Playback paused successfully');
-      console.log("Heanup2 UnifiedPlayerService: 暂停播放成功");
+
     } catch (error) {
       LogUtils.getInstance().LOGI(`UnifiedPlayerService pause error: ${error}`);
-      console.log(`Heanup2 UnifiedPlayerService: 暂停播放出错: ${error}`);
-      throw new Error(`Failed to pause playback: ${error}`);
     }
   }
 
@@ -503,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;
@@ -523,9 +482,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
       }
 
       await this.playerManager.seekToPosition(position);
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Seeked to position ${position}`);
     } catch (error) {
-      LogUtils.getInstance().LOGI(`UnifiedPlayerService seekTo error: ${error}`);
       throw new Error(`Failed to seek to position: ${error}`);
     }
   }
@@ -536,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;
       }
 
@@ -557,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);
       }
       
@@ -575,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);
     }
   }
@@ -587,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;
       }
 
@@ -608,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);
       }
       
@@ -626,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);
     }
   }
@@ -654,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;
     }
   }
@@ -1751,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,

+ 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');
+    
   }
 
   /**

+ 14 - 480
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,115 +146,30 @@ 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`);
-    }
-  }
-
   /**
    * 获取当前播放状态
    */
   async getCurrentPlayState(): Promise<WidgetData> {
     try {
-      // 优先从UnifiedPlayerService获取实时状态
-      if (this.unifiedPlayerService) {
-        const currentState = this.unifiedPlayerService.getCurrentState();
-        const currentSong = this.unifiedPlayerService.getCurrentSong();
-        const playlist = this.unifiedPlayerService.getPlaylist();
-        const currentIndex = this.unifiedPlayerService.getCurrentIndex();
-        
-        if (currentSong) {
-          const widgetData: WidgetData = {
-            playState: {
-              isPlaying: currentState.isPlaying || false,
-              isPaused: currentState.isPaused || true,
-              isLoading: currentState.isLoading || false
-            },
-            currentSong: {
-              id: currentSong.id || '',
-              title: currentSong.name || '暂无播放',
-              artist: currentSong.artist || '未知艺术家',
-              album: currentSong.album || '未知专辑',
-              coverImagePath: currentSong.pixelMapPath || '',
-              duration: currentSong.duration ? Number(currentSong.duration) : 0
-            },
-            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))
-            },
-            playlist: {
-              hasNext: currentState.hasNext || false,
-              hasPrevious: currentState.hasPrevious || false,
-              currentIndex: currentIndex,
-              totalCount: playlist.length
-            },
-            config: {
-              size: 'medium',
-              theme: 'auto',
-              showProgress: true,
-              showCover: true
-            }
-          };
-          
-          hilog.info(0x0000, TAG, `Got current state from UnifiedPlayerService: isPlaying=${widgetData.playState.isPlaying}, title=${widgetData.currentSong.title}`);
-          
-          // 更新AvSession监听器的缓存
-          this.avSessionListener.updateWidgetData(widgetData);
-          
-          return widgetData;
-        }
-      }
-      
-      // 备用方案:从AvSession获取当前状态
+      // 优先从AvSession获取当前状态
       const avSessionData = this.avSessionListener.getCurrentWidgetData();
       
       // 同时请求CommonEvent状态作为备用
@@ -486,81 +219,16 @@ export class PlayerControlService {
       return;
     }
     
-    // 立即尝试从UnifiedPlayerService获取当前状态
-    setTimeout(async () => {
+    // 延迟获取当前状态,给主应用时间来广播真实状态
+    setTimeout(() => {
       try {
-        // 优先从UnifiedPlayerService获取实时状态
-        if (this.unifiedPlayerService) {
-          const currentState = this.unifiedPlayerService.getCurrentState();
-          const currentSong = this.unifiedPlayerService.getCurrentSong();
-          const playlist = this.unifiedPlayerService.getPlaylist();
-          const currentIndex = this.unifiedPlayerService.getCurrentIndex();
-          
-          if (currentSong) {
-            // 构建完整的WidgetData
-            const widgetData: WidgetData = {
-              playState: {
-                isPlaying: currentState.isPlaying || false,
-                isPaused: currentState.isPaused || true,
-                isLoading: currentState.isLoading || false
-              },
-              currentSong: {
-                id: currentSong.id || '',
-                title: currentSong.name || '暂无播放',
-                artist: currentSong.artist || '未知艺术家',
-                album: currentSong.album || '未知专辑',
-                coverImagePath: currentSong.pixelMapPath || '',
-                duration: currentSong.duration ? Number(currentSong.duration) : 0
-              },
-              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))
-              },
-              playlist: {
-                hasNext: currentState.hasNext || false,
-                hasPrevious: currentState.hasPrevious || false,
-                currentIndex: currentIndex,
-                totalCount: playlist.length
-              },
-              config: {
-                size: 'medium',
-                theme: 'auto',
-                showProgress: true,
-                showCover: true
-              }
-            };
-            
-            hilog.info(0x0000, TAG, `Sending UnifiedPlayerService data to listener: isPlaying=${widgetData.playState.isPlaying}, title=${widgetData.currentSong.title}, hasNext=${widgetData.playlist.hasNext}, hasPrevious=${widgetData.playlist.hasPrevious}`);
-            
-            // 更新AvSession监听器的缓存数据
-            this.avSessionListener.updateWidgetData(widgetData);
-            
-            // 立即回调给监听器
-            callback(widgetData);
-            return;
-          }
-        }
-        
-        // 备用方案:从AvSession监听器获取缓存数据
         const currentData = this.avSessionListener.getCurrentWidgetData();
-        hilog.info(0x0000, TAG, `Sending cached AvSession data to listener: hasNext=${currentData.playlist.hasNext}, hasPrevious=${currentData.playlist.hasPrevious}`);
+        hilog.info(0x0000, TAG, `Sending current data to listener: hasNext=${currentData.playlist.hasNext}, hasPrevious=${currentData.playlist.hasPrevious}`);
         callback(currentData);
-        
       } catch (error) {
-        hilog.error(0x0000, TAG, `Error getting current state for new listener: ${error}`);
-        // 发送默认数据作为最后的备用方案
-        const defaultData = this.getDefaultWidgetData();
-        callback(defaultData);
+        hilog.error(0x0000, TAG, `Error getting current AvSession data: ${error}`);
       }
-    }, 500); // 减少延迟到500ms,提高响应速度
-    
-    // 额外的状态请求,确保能获取到最新状态
-    setTimeout(async () => {
-      await this.requestCurrentState();
-    }, 1000);
+    }, 1500); // 延迟1.5秒,确保主应用已经广播了状态
   }
 
   /**
@@ -811,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秒清理一次过期命令
-  }
 }

+ 11 - 20
entry/src/main/ets/common/widget/WidgetDataManager.ets

@@ -2,7 +2,7 @@ import formProvider from '@ohos.app.form.formProvider';
 import formBindingData from '@ohos.app.form.formBindingData';
 import preferences from '@ohos.data.preferences';
 import { hilog } from '@kit.PerformanceAnalysisKit';
-import { WidgetData, WidgetSize, WidgetTheme, FormattedWidgetData, PreferencesData, CacheStats, PlayState, SongInfo, PlayProgress, PlaylistState, WidgetConfig } from './WidgetTypes';
+import { WidgetData, WidgetSize, WidgetTheme, FormattedWidgetData, PreferencesData, CacheStats } from './WidgetTypes';
 
 const TAG = 'WidgetDataManager';
 const WIDGET_PREFERENCES_NAME = 'widget_data_prefs';
@@ -54,21 +54,12 @@ export class WidgetDataManager {
    * 获取初始卡片数据
    */
   getInitialWidgetData(): WidgetData {
-    // 尝试从UnifiedPlayerService获取当前状态作为初始数据
-    try {
-      // 这里需要导入UnifiedPlayerService,但为了避免循环依赖,我们使用默认数据
-      // 实际的状态同步会通过PlayerControlService处理
-      hilog.info(0x0000, TAG, 'Getting initial widget data - using default values, real state will sync via PlayerControlService');
-    } catch (error) {
-      hilog.warn(0x0000, TAG, `Could not get real initial state: ${error}`);
-    }
-    
     const initialData: WidgetData = {
       playState: {
         isPlaying: false,
         isPaused: true,
         isLoading: false
-      } as PlayState,
+      },
       currentSong: {
         id: '',
         title: '暂无播放',
@@ -76,26 +67,26 @@ export class WidgetDataManager {
         album: '未知专辑',
         coverImagePath: '',
         duration: 0
-      } as SongInfo,
+      },
       progress: {
         currentPosition: 0,
         duration: 0,
         percentage: 0,
         currentTimeText: '00:00',
         totalTimeText: '00:00'
-      } as PlayProgress,
+      },
       playlist: {
         hasNext: false,
         hasPrevious: false,
         currentIndex: 0,
         totalCount: 0
-      } as PlaylistState,
+      },
       config: {
         size: WidgetSize.MEDIUM,
         theme: WidgetTheme.AUTO,
         showProgress: true,
         showCover: true
-      } as WidgetConfig
+      }
     };
     return initialData;
   }
@@ -476,7 +467,7 @@ export class WidgetDataManager {
         isPlaying: formattedData.isPlaying,
         isPaused: formattedData.isPaused,
         isLoading: formattedData.isLoading
-      } as PlayState,
+      },
       currentSong: {
         id: '', // FormattedWidgetData中没有id,使用空字符串
         title: formattedData.songTitle,
@@ -484,26 +475,26 @@ export class WidgetDataManager {
         album: formattedData.songAlbum,
         coverImagePath: formattedData.coverImage,
         duration: 0 // FormattedWidgetData中没有duration,使用0
-      } as SongInfo,
+      },
       progress: {
         currentPosition: 0, // 需要从时间文本反推,这里简化处理
         duration: 0,
         percentage: formattedData.progressPercentage,
         currentTimeText: formattedData.currentTime,
         totalTimeText: formattedData.totalTime
-      } as PlayProgress,
+      },
       playlist: {
         hasNext: formattedData.hasNext,
         hasPrevious: formattedData.hasPrevious,
         currentIndex: 0,
         totalCount: 0
-      } as PlaylistState,
+      },
       config: {
         size: this.parseWidgetSize(formattedData.widgetSize),
         theme: WidgetTheme.AUTO,
         showProgress: formattedData.showProgress,
         showCover: formattedData.showCover
-      } as WidgetConfig
+      }
     };
     return widgetData;
   }

+ 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; // 图片文件信息,用于本地图片处理
 }
 
 /**

+ 241 - 298
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}`);
     })
 
     // 检测卡片尺寸并注册到全局管理器
@@ -513,39 +695,15 @@ implements SizeChangeListener {
       }
     }, 2000);
 
-    // 立即获取当前播放状态并更新卡片
+    // 获取当前播放状态而不是初始数据
     this.playerControlService.getCurrentPlayState().then((currentState: WidgetData) => {
-      hilog.info(0x0000, TAG, `Got current state for new widget ${formId}: isPlaying=${currentState.playState.isPlaying}, title=${currentState.currentSong.title}`);
-      
       const adaptedData = this.layoutManager.adaptDataForSize(currentState, widgetSize);
       const formData = formBindingData.createFormBindingData(adaptedData);
-      
       // 立即更新卡片以显示当前状态
-      formProvider.updateForm(formId, formData).then(() => {
-        hilog.info(0x0000, TAG, `✅ Widget ${formId} successfully updated with current state: ${currentState.currentSong.title}`);
-      }).catch(() => {
-        hilog.error(0x0000, TAG, `❌ Failed to update widget ${formId}`);
-      });
-    }).catch(() => {
-      hilog.error(0x0000, TAG, `❌ Failed to get current state for widget ${formId}`);
+      formProvider.updateForm(formId, formData);
+      hilog.info(0x0000, TAG, `Widget ${formId} initialized with current state`);
     });
 
-    // 多次尝试获取状态,确保新卡片能获取到数据
-    setTimeout(() => {
-      this.playerControlService.getCurrentPlayState().then((currentState: WidgetData) => {
-        hilog.info(0x0000, TAG, `Second attempt - Got current state for widget ${formId}: isPlaying=${currentState.playState.isPlaying}, title=${currentState.currentSong.title}`);
-        
-        const adaptedData = this.layoutManager.adaptDataForSize(currentState, widgetSize);
-        const formData = formBindingData.createFormBindingData(adaptedData);
-        
-        formProvider.updateForm(formId, formData).then(() => {
-          hilog.info(0x0000, TAG, `✅ Widget ${formId} second update successful`);
-        }).catch(() => {
-          hilog.error(0x0000, TAG, `❌ Widget ${formId} second update failed`);
-        });
-      });
-    }, 1000);
-
     // 返回初始数据作为临时显示
     const initialData = this.widgetDataManager?.getInitialWidgetData() || this.getDefaultWidgetData();
     const adaptedData = this.layoutManager.adaptDataForSize(initialData, widgetSize);
@@ -741,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}`);
     }
   }
 
@@ -965,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}`);
     }
   }
 
@@ -1004,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
-    };
-  }
 }