Explorar o código

修复应用更新卡片数据

chendeben hai 1 ano
pai
achega
183914404a

+ 184 - 0
entry/src/main/ets/common/utils/PreferencesUtil.ets

@@ -0,0 +1,184 @@
+import { preferences } from '@kit.ArkData';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { Context } from '@kit.AbilityKit';
+
+// 定义支持的值类型
+type SupportedValueType = string | number | boolean | Uint8Array;
+
+const TAG = 'PreferencesUtil';
+const FORM_IDS_KEY = 'widget_form_ids';
+const PREFERENCES_NAME = 'ttmusic_widget_prefs';
+
+/**
+ * 首选项工具类 - 用于持久化存储 Form ID 和卡片状态
+ */
+export class PreferencesUtil {
+  private static instance: PreferencesUtil | null = null;
+  private preferencesMap: Map<string, preferences.Preferences> = new Map();
+
+  private constructor() {}
+
+  public static getInstance(): PreferencesUtil {
+    if (!PreferencesUtil.instance) {
+      PreferencesUtil.instance = new PreferencesUtil();
+    }
+    return PreferencesUtil.instance;
+  }
+
+  /**
+   * 获取 Preferences 实例
+   */
+  public async getPreferences(context: Context): Promise<preferences.Preferences> {
+    const contextKey = context.toString();
+    
+    if (!this.preferencesMap.has(contextKey)) {
+      try {
+        const prefs = await preferences.getPreferences(context, PREFERENCES_NAME);
+        this.preferencesMap.set(contextKey, prefs);
+        hilog.info(0x0000, TAG, 'Preferences instance created successfully');
+      } catch (error) {
+        hilog.error(0x0000, TAG, `Failed to get preferences: ${JSON.stringify(error)}`);
+        throw new Error(`Failed to get preferences: ${JSON.stringify(error)}`);
+      }
+    }
+    
+    return this.preferencesMap.get(contextKey)!;
+  }
+
+  /**
+   * 添加 Form ID 到存储列表
+   */
+  public async addFormId(prefs: preferences.Preferences, formId: string): Promise<void> {
+    try {
+      const formIds = await this.getFormIds(prefs);
+      if (!formIds.includes(formId)) {
+        formIds.push(formId);
+        await prefs.put(FORM_IDS_KEY, JSON.stringify(formIds));
+        await prefs.flush();
+        hilog.info(0x0000, TAG, `Form ID added: ${formId}, total: ${formIds.length}`);
+      } else {
+        hilog.info(0x0000, TAG, `Form ID already exists: ${formId}`);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to add form ID: ${error}`);
+    }
+  }
+
+  /**
+   * 移除 Form ID 从存储列表
+   */
+  public async removeFormId(prefs: preferences.Preferences, formId: string): Promise<void> {
+    try {
+      const formIds = await this.getFormIds(prefs);
+      const index = formIds.indexOf(formId);
+      if (index > -1) {
+        formIds.splice(index, 1);
+        await prefs.put(FORM_IDS_KEY, JSON.stringify(formIds));
+        await prefs.flush();
+        hilog.info(0x0000, TAG, `Form ID removed: ${formId}, remaining: ${formIds.length}`);
+        
+        // 同时清理该 Form ID 相关的其他数据
+        await this.clearFormData(prefs, formId);
+      } else {
+        hilog.warn(0x0000, TAG, `Form ID not found for removal: ${formId}`);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to remove form ID: ${error}`);
+    }
+  }
+
+  /**
+   * 获取所有存储的 Form ID
+   */
+  public async getFormIds(prefs: preferences.Preferences): Promise<string[]> {
+    try {
+      const formIdsStr = await prefs.get(FORM_IDS_KEY, '[]') as string;
+      const formIds = JSON.parse(formIdsStr) as string[];
+      hilog.info(0x0000, TAG, `Retrieved ${formIds.length} form IDs: ${formIds.join(', ')}`);
+      return formIds;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get form IDs: ${error}`);
+      return [];
+    }
+  }
+
+  /**
+   * 保存卡片当前显示的数据索引或状态
+   */
+  public async saveFormState(prefs: preferences.Preferences, formId: string, state: Record<string, SupportedValueType>): Promise<void> {
+    try {
+      const key = `${formId}_state`;
+      await prefs.put(key, JSON.stringify(state));
+      await prefs.flush();
+      hilog.info(0x0000, TAG, `Form state saved for: ${formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to save form state: ${error}`);
+    }
+  }
+
+  /**
+   * 获取卡片当前状态
+   */
+  public async getFormState(prefs: preferences.Preferences, formId: string): Promise<Record<string, SupportedValueType> | null> {
+    try {
+      const key = `${formId}_state`;
+      const stateStr = await prefs.get(key, '') as string;
+      if (stateStr) {
+        return JSON.parse(stateStr) as Record<string, SupportedValueType>;
+      }
+      return null;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get form state: ${error}`);
+      return null;
+    }
+  }
+
+  /**
+   * 清理指定 Form ID 相关的所有数据
+   */
+  private async clearFormData(prefs: preferences.Preferences, formId: string): Promise<void> {
+    try {
+      const keys = [`${formId}_state`, `${formId}_size`, `${formId}_config`];
+      for (const key of keys) {
+        if (await prefs.has(key)) {
+          await prefs.delete(key);
+        }
+      }
+      await prefs.flush();
+      hilog.info(0x0000, TAG, `Cleared data for form: ${formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to clear form data: ${error}`);
+    }
+  }
+
+  /**
+   * 通用的保存方法
+   */
+  public async put(prefs: preferences.Preferences, key: string, value: SupportedValueType): Promise<void> {
+    try {
+      await prefs.put(key, value);
+      await prefs.flush();
+      hilog.info(0x0000, TAG, `Data saved for key: ${key}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to save data for key ${key}: ${error}`);
+    }
+  }
+
+  /**
+   * 通用的获取方法
+   */
+  public async get(prefs: preferences.Preferences, key: string, defaultValue: SupportedValueType): Promise<SupportedValueType> {
+    try {
+      const result = await prefs.get(key, defaultValue);
+      // 只返回支持的类型,过滤掉 bigint
+      if (typeof result === 'bigint') {
+        hilog.warn(0x0000, TAG, `Received bigint value for key ${key}, converting to number`);
+        return Number(result);
+      }
+      return result as SupportedValueType;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get data for key ${key}: ${error}`);
+      return defaultValue;
+    }
+  }
+}

+ 11 - 2
entry/src/main/ets/common/widget/AvSessionWidgetListener.ets

@@ -1,5 +1,5 @@
 import { hilog } from '@kit.PerformanceAnalysisKit';
-import { WidgetData, PlayState, SongInfo, PlayProgress, PlaylistState } from './WidgetTypes';
+import { WidgetData } from './WidgetTypes';
 import { WidgetTypeHelpers } from './WidgetTypeHelpers';
 
 const TAG = 'Heanup AvSessionWidgetListener';
@@ -71,6 +71,13 @@ export class AvSessionWidgetListener {
     }, 500); // 延迟500ms,给主应用时间广播状态
   }
 
+  /**
+   * 获取当前监听器数量(调试用)
+   */
+  public getListenerCount(): number {
+    return this.stateListeners.length;
+  }
+
   /**
    * 更新卡片数据(由主应用调用)
    */
@@ -83,7 +90,9 @@ export class AvSessionWidgetListener {
     
     this.lastWidgetData = data;
     
-    hilog.info(0x0000, TAG, `[${this.processId}] Updating widget data: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}, listeners=${this.stateListeners.length}`);
+    // 添加调用栈信息以便调试
+    const callerInfo = new Error().stack?.split('\n')[2]?.trim() || 'Unknown caller';
+    hilog.info(0x0000, TAG, `[${this.processId}] Updating widget data: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}, listeners=${this.stateListeners.length}, caller: ${callerInfo}`);
     
     // 通知所有监听器
     this.stateListeners.forEach((listener: (data: WidgetData) => void, index: number) => {

+ 457 - 0
entry/src/main/ets/common/widget/DirectFormUpdateService.ets

@@ -0,0 +1,457 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { formProvider, formBindingData } from '@kit.FormKit';
+import { preferences } from '@kit.ArkData';
+import { WidgetData, FormattedWidgetData, WidgetSize } from './WidgetTypes';
+import { FormLayoutManager } from './FormLayoutManager';
+import { PreferencesUtil } from '../utils/PreferencesUtil';
+import { Context } from '@kit.AbilityKit';
+
+// 定义支持的值类型
+type SupportedValueType = string | number | boolean | Uint8Array;
+
+const TAG = 'DirectFormUpdateService';
+
+/**
+ * 表单状态数据接口
+ */
+interface FormStateData extends Record<string, SupportedValueType> {
+  size: string;
+  lastUpdate: number;
+  lastSongId: string;
+}
+
+/**
+ * 表单验证结果接口
+ */
+interface FormValidationResult {
+  formId: string;
+  isValid: boolean;
+  error: Error | null;
+}
+
+/**
+ * 测试数据接口
+ */
+interface TestFormData {
+  test: string;
+}
+
+/**
+ * 直接卡片更新服务
+ * 按照 HarmonyOS 官方推荐方式,通过持久化的 Form ID 直接更新卡片
+ */
+export class DirectFormUpdateService {
+  private static instance: DirectFormUpdateService | null = null;
+  private layoutManager: FormLayoutManager = FormLayoutManager.getInstance();
+  private preferencesUtil: PreferencesUtil = PreferencesUtil.getInstance();
+  private appContext: Context | null = null;
+
+  private constructor() {}
+
+  public static getInstance(): DirectFormUpdateService {
+    if (!DirectFormUpdateService.instance) {
+      DirectFormUpdateService.instance = new DirectFormUpdateService();
+    }
+    return DirectFormUpdateService.instance;
+  }
+
+  /**
+   * 设置应用上下文
+   */
+  public setAppContext(context: Context): void {
+    this.appContext = context;
+    hilog.info(0x0000, TAG, '🎯 App context set for DirectFormUpdateService');
+  }
+
+  /**
+   * 更新所有卡片数据
+   */
+  public async updateAllForms(data: WidgetData): Promise<void> {
+    try {
+      if (!this.appContext) {
+        hilog.error(0x0000, TAG, '❌ App context not set, cannot update forms');
+        return;
+      }
+
+      hilog.info(0x0000, TAG, `🎯 Starting direct 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;
+      }
+
+      hilog.info(0x0000, TAG, `📋 Found ${formIds.length} forms to update: [${formIds.join(', ')}]`);
+
+      // 为每个卡片创建单独的更新任务,添加详细日志
+      const updatePromises = formIds.map((formId, index) => {
+        hilog.info(0x0000, TAG, `🚀 Creating update task ${index + 1}/${formIds.length} for form: ${formId}`);
+        return this.updateSingleForm(formId, data, prefs);
+      });
+
+      hilog.info(0x0000, TAG, `⏳ Executing ${updatePromises.length} parallel update tasks...`);
+
+      // 更新每个卡片
+      const results = await Promise.allSettled(updatePromises);
+
+      // 统计更新结果
+      const successCount = results.filter(result => result.status === 'fulfilled').length;
+      const failureCount = results.filter(result => result.status === 'rejected').length;
+
+      hilog.info(0x0000, TAG, `🎯 Form update completed: ${successCount} succeeded, ${failureCount} failed`);
+
+      // 详细记录每个结果
+      results.forEach((result, index) => {
+        const formId = formIds[index];
+        if (result.status === 'fulfilled') {
+          hilog.info(0x0000, TAG, `✅ Form ${index + 1}/${formIds.length} (${formId}) updated successfully`);
+        } else {
+          const error = result.reason as Error;
+          hilog.error(0x0000, TAG, `❌ Form ${index + 1}/${formIds.length} (${formId}) failed: ${error.message}`);
+        }
+      });
+
+      // 清理无效的 Form ID(16501001 错误表示 Form 不存在)
+      if (failureCount > 0) {
+        hilog.info(0x0000, TAG, `🧹 Starting cleanup of failed forms...`);
+        await this.cleanupInvalidForms(prefs, formIds, results);
+        
+        // 重新获取清理后的 Form ID 列表
+        const remainingFormIds = await this.preferencesUtil.getFormIds(prefs);
+        hilog.info(0x0000, TAG, `📋 After cleanup: ${remainingFormIds.length} forms remaining: [${remainingFormIds.join(', ')}]`);
+      }
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Failed to update forms: ${error}`);
+    }
+  }
+
+  /**
+   * 更新单个卡片
+   */
+  private async updateSingleForm(formId: string, data: WidgetData, prefs: preferences.Preferences): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `🎯 [${formId}] Starting form update...`);
+
+      // 获取卡片的当前状态(如果有保存的话)
+      const formState = await this.preferencesUtil.getFormState(prefs, formId);
+      const widgetSizeStr = (formState?.size as string) || 'medium'; // 默认使用 medium 尺寸
+      hilog.info(0x0000, TAG, `🎯 [${formId}] Widget size: ${widgetSizeStr}, formState: ${JSON.stringify(formState)}`);
+
+      // 转换为 WidgetSize 类型
+      const widgetSize: WidgetSize = widgetSizeStr as WidgetSize;
+
+      // 适配数据到卡片尺寸
+      const adaptedData = this.layoutManager.adaptDataForSize(data, widgetSize);
+      hilog.info(0x0000, TAG, `🎯 [${formId}] Data adapted for size ${widgetSize}`);
+
+      // 转换为 FormattedWidgetData
+      const formattedData: FormattedWidgetData = {
+        isPlaying: adaptedData.isPlaying,
+        isPaused: adaptedData.isPaused,
+        isLoading: adaptedData.isLoading,
+        songTitle: adaptedData.songTitle,
+        songArtist: adaptedData.songArtist,
+        songAlbum: adaptedData.songAlbum,
+        coverImage: adaptedData.coverImage,
+        currentTime: adaptedData.currentTime,
+        totalTime: adaptedData.totalTime,
+        progressPercentage: adaptedData.progressPercentage,
+        hasNext: adaptedData.hasNext,
+        hasPrevious: adaptedData.hasPrevious,
+        showProgress: adaptedData.showProgress,
+        showCover: adaptedData.showCover,
+        widgetSize: adaptedData.widgetSize,
+        timestamp: Date.now(),
+        imgName: adaptedData.imgName || ''
+      };
+
+      hilog.info(0x0000, TAG, `🎯 [${formId}] Formatted data prepared: isPlaying=${formattedData.isPlaying}, title="${formattedData.songTitle}"`);
+
+      // 创建 FormBindingData 并更新卡片
+      const formData = formBindingData.createFormBindingData(formattedData);
+      hilog.info(0x0000, TAG, `🎯 [${formId}] FormBindingData created, calling formProvider.updateForm...`);
+      
+      await formProvider.updateForm(formId, formData);
+      
+      hilog.info(0x0000, TAG, `✅ [${formId}] Form updated successfully: isPlaying=${formattedData.isPlaying}, title="${formattedData.songTitle}"`);
+
+      // 保存当前状态
+      const stateData: FormStateData = {
+        size: widgetSizeStr,
+        lastUpdate: Date.now(),
+        lastSongId: data.currentSong.id
+      };
+      await this.preferencesUtil.saveFormState(prefs, formId, stateData);
+      
+      hilog.info(0x0000, TAG, `💾 [${formId}] Form state saved`);
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ [${formId}] Failed to update form: ${JSON.stringify(error)}`);
+      throw new Error(`Failed to update form ${formId}: ${JSON.stringify(error)}`); // 重新抛出错误,让 Promise.allSettled 捕获
+    }
+  }
+
+  /**
+   * 清理无效的 Form ID
+   */
+  private async cleanupInvalidForms(prefs: preferences.Preferences, formIds: string[], results: PromiseSettledResult<void>[]): Promise<void> {
+    try {
+      const invalidFormIds: string[] = [];
+
+      results.forEach((result: PromiseSettledResult<void>, index: number) => {
+        if (result.status === 'rejected') {
+          const error = result.reason as Error;
+          const errorStr = error.toString();
+          const formId = formIds[index];
+          
+          hilog.warn(0x0000, TAG, `🔍 Analyzing error for form ${formId}: ${errorStr}`);
+          
+          // 检查是否是因为 Form 不存在导致的错误
+          // 16501001 是 Form 不存在的错误代码
+          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 (error: ${errorStr}), marking for cleanup`);
+            invalidFormIds.push(formId);
+          } else {
+            hilog.error(0x0000, TAG, `⚠️ Form ${formId} failed with unknown error: ${errorStr}`);
+          }
+        }
+      });
+
+      if (invalidFormIds.length > 0) {
+        hilog.info(0x0000, TAG, `🧹 Cleaning up ${invalidFormIds.length} invalid forms: [${invalidFormIds.join(', ')}]`);
+        
+        for (const invalidFormId of invalidFormIds) {
+          hilog.info(0x0000, TAG, `🗑️ Removing invalid form ID: ${invalidFormId}`);
+          await this.preferencesUtil.removeFormId(prefs, invalidFormId);
+        }
+        
+        hilog.info(0x0000, TAG, `✅ Invalid forms cleaned up successfully. Remaining forms will be updated normally.`);
+      } else {
+        hilog.warn(0x0000, TAG, `⚠️ ${results.filter(r => r.status === 'rejected').length} forms failed but none appear to be invalid (may be temporary errors)`);
+      }
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Failed to cleanup invalid forms: ${error}`);
+    }
+  }
+
+  /**
+   * 获取当前注册的卡片数量
+   */
+  public async getRegisteredFormCount(): Promise<number> {
+    try {
+      if (!this.appContext) {
+        return 0;
+      }
+
+      const prefs = await this.preferencesUtil.getPreferences(this.appContext);
+      const formIds = await this.preferencesUtil.getFormIds(prefs);
+      return formIds.length;
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get registered form count: ${error}`);
+      return 0;
+    }
+  }
+
+  /**
+   * 获取所有注册的 Form ID
+   */
+  public async getRegisteredFormIds(): Promise<string[]> {
+    try {
+      if (!this.appContext) {
+        return [];
+      }
+
+      const prefs = await this.preferencesUtil.getPreferences(this.appContext);
+      return await this.preferencesUtil.getFormIds(prefs);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `Failed to get registered form IDs: ${error}`);
+      return [];
+    }
+  }
+
+  /**
+   * 调试方法:强制刷新所有卡片
+   */
+  public async debugRefreshAllForms(): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, '🔧 DEBUG: Starting manual refresh of all forms...');
+      
+      if (!this.appContext) {
+        hilog.error(0x0000, TAG, '🔧 DEBUG: App context not available');
+        return;
+      }
+
+      const formIds = await this.getRegisteredFormIds();
+      hilog.info(0x0000, TAG, `🔧 DEBUG: Found ${formIds.length} registered forms: [${formIds.join(', ')}]`);
+
+      if (formIds.length === 0) {
+        hilog.warn(0x0000, TAG, '🔧 DEBUG: No forms to refresh');
+        return;
+      }
+
+      // 创建模拟数据进行测试
+      const testData: WidgetData = {
+        playState: {
+          isPlaying: true,
+          isPaused: false,
+          isLoading: false
+        },
+        currentSong: {
+          id: 'debug-song',
+          title: '调试测试歌曲',
+          artist: '调试艺术家',
+          album: '调试专辑',
+          coverImagePath: '',
+          duration: 180000
+        },
+        progress: {
+          currentPosition: 60000,
+          duration: 180000,
+          percentage: 33.33,
+          currentTimeText: '01:00',
+          totalTimeText: '03:00'
+        },
+        playlist: {
+          hasNext: true,
+          hasPrevious: true,
+          currentIndex: 1,
+          totalCount: 5
+        },
+        config: {
+          size: 'medium',
+          theme: 'auto',
+          showProgress: true,
+          showCover: true
+        }
+      };
+
+      await this.updateAllForms(testData);
+      hilog.info(0x0000, TAG, '🔧 DEBUG: Manual refresh completed');
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `🔧 DEBUG: Manual refresh failed: ${error}`);
+    }
+  }
+
+  /**
+   * 验证和清理所有无效的 Form ID
+   */
+  public async validateAndCleanupForms(): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, '🔍 Starting Form ID validation...');
+      
+      if (!this.appContext) {
+        hilog.error(0x0000, TAG, '❌ App context not available for validation');
+        return;
+      }
+
+      const prefs = await this.preferencesUtil.getPreferences(this.appContext);
+      const formIds = await this.preferencesUtil.getFormIds(prefs);
+      
+      hilog.info(0x0000, TAG, `🔍 Validating ${formIds.length} Form IDs: [${formIds.join(', ')}]`);
+
+      if (formIds.length === 0) {
+        hilog.info(0x0000, TAG, '✅ No Form IDs to validate');
+        return;
+      }
+
+      // 尝试获取每个 Form 的信息来验证其有效性
+      const validationPromises = formIds.map(async (formId): Promise<FormValidationResult> => {
+        try {
+          // 尝试创建一个简单的数据来测试 Form 是否存在
+          const testFormData: TestFormData = { test: 'validation' };
+          const testData = formBindingData.createFormBindingData(testFormData);
+          await formProvider.updateForm(formId, testData);
+          hilog.info(0x0000, TAG, `✅ Form ${formId} is valid`);
+          
+          const result: FormValidationResult = { formId, isValid: true, error: null };
+          return result;
+        } catch (error) {
+          hilog.warn(0x0000, TAG, `❌ Form ${formId} validation failed: ${JSON.stringify(error)}`);
+          
+          const result: FormValidationResult = { formId, isValid: false, error: error as Error };
+          return result;
+        }
+      });
+
+      const validationResults = await Promise.allSettled(validationPromises);
+      const invalidFormIds: string[] = [];
+
+      validationResults.forEach((result, index) => {
+        if (result.status === 'fulfilled') {
+          if (!result.value.isValid) {
+            const error = result.value.error?.message as string;
+            if (error.includes('16501001')) {
+              hilog.info(0x0000, TAG, `🗑️ Form ${result.value.formId} is invalid (error code: 16501001), marking for removal`);
+              invalidFormIds.push(result.value.formId);
+            }
+          }
+        } else {
+          hilog.error(0x0000, TAG, `⚠️ Validation promise failed for form ${formIds[index]}: ${result.reason}`);
+        }
+      });
+
+      // 清理无效的 Form ID
+      if (invalidFormIds.length > 0) {
+        hilog.info(0x0000, TAG, `🧹 Cleaning up ${invalidFormIds.length} invalid Form IDs: [${invalidFormIds.join(', ')}]`);
+        
+        for (const invalidFormId of invalidFormIds) {
+          await this.preferencesUtil.removeFormId(prefs, invalidFormId);
+        }
+        
+        const remainingFormIds = await this.preferencesUtil.getFormIds(prefs);
+        hilog.info(0x0000, TAG, `✅ Cleanup completed. Remaining valid forms: ${remainingFormIds.length} [${remainingFormIds.join(', ')}]`);
+      } else {
+        hilog.info(0x0000, TAG, '✅ All Form IDs are valid');
+      }
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Form validation failed: ${error}`);
+    }
+  }
+
+  /**
+   * 调试方法:显示当前持久化存储状态
+   */
+  public async debugShowPersistenceStatus(): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, '🔧 DEBUG: Checking persistence status...');
+      
+      if (!this.appContext) {
+        hilog.error(0x0000, TAG, '🔧 DEBUG: App context not available');
+        return;
+      }
+
+      const prefs = await this.preferencesUtil.getPreferences(this.appContext);
+      const formIds = await this.preferencesUtil.getFormIds(prefs);
+      
+      hilog.info(0x0000, TAG, `🔧 DEBUG: Current Form IDs in storage: ${formIds.length}`);
+      
+      if (formIds.length > 0) {
+        hilog.info(0x0000, TAG, `🔧 DEBUG: Form IDs: [${formIds.join(', ')}]`);
+        
+        // 检查每个 Form ID 的状态
+        for (const formId of formIds) {
+          const formState = await this.preferencesUtil.getFormState(prefs, formId);
+          hilog.info(0x0000, TAG, `🔧 DEBUG: Form ${formId} state: ${JSON.stringify(formState)}`);
+        }
+      } else {
+        hilog.warn(0x0000, TAG, '🔧 DEBUG: No Form IDs found in storage!');
+        hilog.info(0x0000, TAG, '🔧 DEBUG: This means either:');
+        hilog.info(0x0000, TAG, '🔧 DEBUG: 1. No widgets have been added');
+        hilog.info(0x0000, TAG, '🔧 DEBUG: 2. Widget addition failed to save Form IDs');
+        hilog.info(0x0000, TAG, '🔧 DEBUG: 3. All Form IDs were cleaned up due to invalid widgets');
+      }
+
+    } catch (error) {
+      hilog.error(0x0000, TAG, `🔧 DEBUG: Persistence status check failed: ${error}`);
+    }
+  }
+}

+ 58 - 2
entry/src/main/ets/common/widget/GlobalWidgetService.ets

@@ -1,6 +1,12 @@
 import { hilog } from '@kit.PerformanceAnalysisKit';
-import { WidgetData } from './WidgetTypes';
+import { PlaylistState, PlayProgress, PlayState, SongInfo, WidgetConfig, WidgetData } from './WidgetTypes';
 import { AvSessionWidgetListener } from './AvSessionWidgetListener';
+import commonEventManager from '@ohos.commonEventManager';
+import {
+  PLAYER_STATE_CHANGED_EVENT,
+  PLAYER_SONG_CHANGED_EVENT,
+  PLAYER_PROGRESS_CHANGED_EVENT
+} from './WidgetEventConstants';
 
 const TAG = 'GlobalWidgetService';
 
@@ -8,6 +14,16 @@ const TAG = 'GlobalWidgetService';
  * 全局卡片服务
  * 用于主应用直接更新卡片数据,绕过跨进程通信限制
  */
+interface GeneratedObjectLiteralInterface_1 {
+  playState: PlayState;
+  currentSong: SongInfo;
+  progress: PlayProgress;
+  playlist: PlaylistState;
+  config: WidgetConfig;
+  timestamp: number;
+  source: string;
+}
+
 export class GlobalWidgetService {
   private static instance: GlobalWidgetService | null = null;
   private avSessionListener: AvSessionWidgetListener;
@@ -31,15 +47,55 @@ export class GlobalWidgetService {
       // 在全局服务层面也进行按钮状态验证和修复
       const correctedData = this.validateAndFixButtonStates(data);
       
-      // 更新AvSession监听器数据
+      // 同步更新主进程的AvSession监听器数据(用于主应用内的逻辑)
       this.avSessionListener.updateWidgetData(correctedData);
       
+      // 通过 CommonEvent 发送数据到 Form 进程
+      this.broadcastToFormProcess(correctedData);
+      
       hilog.info(0x0000, TAG, `Widget data updated globally: isPlaying=${correctedData.playState.isPlaying}, title=${correctedData.currentSong.title}, hasNext=${correctedData.playlist.hasNext}, hasPrevious=${correctedData.playlist.hasPrevious}, currentIndex=${correctedData.playlist.currentIndex}, totalCount=${correctedData.playlist.totalCount}`);
     } catch (error) {
       hilog.error(0x0000, TAG, `Failed to update widget data globally: ${error}`);
     }
   }
 
+  /**
+   * 通过 CommonEvent 广播数据到 Form 进程
+   */
+  private async broadcastToFormProcess(data: WidgetData): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `🚀 Starting broadcast to form process for: ${data.currentSong.title}`);
+      
+      // 构造广播数据
+      const broadcastData: GeneratedObjectLiteralInterface_1 = {
+        playState: data.playState,
+        currentSong: data.currentSong,
+        progress: data.progress,
+        playlist: data.playlist,
+        config: data.config,
+        timestamp: Date.now(),
+        source: 'main_app_global_service'
+      };
+
+      const publishInfo: commonEventManager.CommonEventPublishData = {
+        data: JSON.stringify(broadcastData)
+      };
+
+      hilog.info(0x0000, TAG, `🚀 Publishing CommonEvent: ${PLAYER_STATE_CHANGED_EVENT}, data size: ${publishInfo.data?.length || 0} characters`);
+      
+      // 发送状态变化事件到 Form 进程
+      await commonEventManager.publish(PLAYER_STATE_CHANGED_EVENT, publishInfo, (err) => {
+        if (err) {
+          hilog.error(0x0000, TAG, `❌ Failed to broadcast to form process: ${JSON.stringify(err)}`);
+        } else {
+          hilog.info(0x0000, TAG, `✅ Successfully broadcasted widget data to form process: ${data.currentSong.title}`);
+        }
+      });
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Error broadcasting to form process: ${error}`);
+    }
+  }
+
   /**
    * 验证和修复按钮状态
    */

+ 10 - 6
entry/src/main/ets/common/widget/PlayerControlService.ets

@@ -68,10 +68,11 @@ export class PlayerControlService {
       
       await commonEventManager.subscribe(subscriber, (err, data: commonEventManager.CommonEventData) => {
         if (!err) {
-          hilog.info(0x0000, TAG, `CommonEvent received: ${data.event}`);
+          hilog.info(0x0000, TAG, `📡 CommonEvent received in Form process: ${data.event}`);
+          hilog.info(0x0000, TAG, `📡 Event data length: ${data.data?.length || 0} characters`);
           this.handlePlayerStateChange(data);
         } else {
-          hilog.error(0x0000, TAG, `CommonEvent error: ${JSON.stringify(err)}`);
+          hilog.error(0x0000, TAG, `CommonEvent error: ${JSON.stringify(err)}`);
         }
       });
 
@@ -179,7 +180,7 @@ export class PlayerControlService {
       const requestInfo: commonEventManager.CommonEventPublishData = {
         data: JSON.stringify(requestData)
       };
-      await commonEventManager.publish(WIDGET_REQUEST_STATE_EVENT, requestInfo, (err) => {
+       commonEventManager.publish(WIDGET_REQUEST_STATE_EVENT, requestInfo, (err) => {
         if (err) {
           hilog.error(0x0000, TAG, `Failed to publish request state event: ${err}`);
         }
@@ -299,7 +300,8 @@ export class PlayerControlService {
    */
   private handlePlayerStateChange(eventData: commonEventManager.CommonEventData): void {
     try {
-      hilog.info(0x0000, TAG, `CommonEvent received in form process: ${eventData.event}, data: ${eventData.data}`);
+      hilog.info(0x0000, TAG, `📨 Form process handling CommonEvent: ${eventData.event}`);
+      hilog.info(0x0000, TAG, `📨 Event data: ${eventData.data?.substring(0, 200)}...`);
       
       const data = JSON.parse(eventData.data || '{}') as Object;
       let widgetData: WidgetData;
@@ -312,13 +314,15 @@ export class PlayerControlService {
         widgetData = this.convertToWidgetData(data);
       }
       
+      hilog.info(0x0000, TAG, `📨 Form process converted data: isPlaying=${widgetData.playState.isPlaying}, title=${widgetData.currentSong.title}`);
+      
       // 只更新AvSession监听器的数据,避免重复通知
       // AvSession监听器会自动通知所有注册的监听器
       this.avSessionListener.updateWidgetData(widgetData);
       
-      hilog.info(0x0000, TAG, `Player ${eventData.event} handled, data updated in AvSession`);
+      hilog.info(0x0000, TAG, `📨 Form process: ${eventData.event} handled, data updated in AvSession`);
     } catch (error) {
-      hilog.error(0x0000, TAG, `Failed to handle player state change: ${error}`);
+      hilog.error(0x0000, TAG, `Form process failed to handle player state change: ${error}`);
     }
   }
 

+ 14 - 0
entry/src/main/ets/entryability/EntryAbility.ets

@@ -195,6 +195,20 @@ export default class EntryAbility extends UIAbility {
         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
         SpiderMan.init();
         AppUtil.init(this.context);
+        
+        // 初始化 DirectFormUpdateService 的上下文
+        try {
+            import('../common/widget/DirectFormUpdateService').then((module) => {
+                const directFormService = module.DirectFormUpdateService.getInstance();
+                directFormService.setAppContext(this.context);
+                hilog.info(0x0000, 'testTag', 'DirectFormUpdateService context initialized');
+            }).catch((error: Error) => {
+                hilog.error(0x0000, 'testTag', `Failed to initialize DirectFormUpdateService: ${error.message}`);
+            });
+        } catch (error) {
+            hilog.error(0x0000, 'testTag', `Error initializing DirectFormUpdateService: ${error}`);
+        }
+        
         //1.获取应用主窗口。
         let windowClass: window.Window | null = null;
         windowStage.getMainWindow((err: BusinessError, data) => {

+ 71 - 5
entry/src/main/ets/entryformability/EntryFormAbility.ets

@@ -1,6 +1,5 @@
 import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
-import { Configuration, Want } from '@kit.AbilityKit';
-import { BusinessError } from '@kit.BasicServicesKit';
+import { Want } from '@kit.AbilityKit';
 import { hilog } from '@kit.PerformanceAnalysisKit';
 import { fileIo } from '@kit.CoreFileKit';
 import { http } from '@kit.NetworkKit';
@@ -12,6 +11,7 @@ import { WidgetCommand, WidgetControlParams, WidgetData, WidgetSize, FormattedWi
 import { FormLayoutManager } from '../common/widget/FormLayoutManager';
 import { GlobalWidgetManager } from '../common/widget/GlobalWidgetManager';
 import { WidgetSizeAdapter, SizeChangeListener } from '../common/widget/WidgetSizeAdapter';
+import { PreferencesUtil } from '../common/utils/PreferencesUtil';
 import {
   PLAY_PAUSE_EVENT,
   NEXT_SONG_EVENT,
@@ -136,7 +136,13 @@ implements SizeChangeListener {
     try {
       hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] getting AvSessionWidgetListener instance...`);
       const avSessionListener = AvSessionWidgetListener.getInstance();
+      
+      // 检查当前监听器数量
+      const currentListenerCount = avSessionListener.getListenerCount();
+      hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] current listener count before adding: ${currentListenerCount}`);
+      
       hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] adding state listener...`);
+      
       avSessionListener.addStateListener((data: WidgetData) => {
         const now = Date.now();
         hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] global listener received state update: isPlaying=${data.playState.isPlaying}, title=${data.currentSong.title}, age=${now - this.processStartTime}ms`);
@@ -147,6 +153,10 @@ implements SizeChangeListener {
         // 总是尝试更新,让updateAllWidgetsWithData自己检查
         this.updateAllWidgetsWithData(data);
       });
+      
+      // 验证监听器是否成功注册
+      const listenerCount = avSessionListener.getListenerCount();
+      hilog.info(0x0000, TAG, `Heanup EntryFormAbility [Process:${this.processStartTime}] listener registered successfully, total listeners: ${listenerCount}`);
 
       // 启动健康检查定时器
       this.startHealthCheck();
@@ -450,6 +460,12 @@ implements SizeChangeListener {
   onAddForm(want: Want): formBindingData.FormBindingData {
     hilog.info(0x0000, TAG, 'Heanup EntryFormAbility onAddForm called');
     
+    // 检查参数有效性
+    if (!want || !want.parameters) {
+      hilog.error(0x0000, TAG, 'FormAbility onAddForm want or want.parameters is undefined');
+      return formBindingData.createFormBindingData('');
+    }
+    
     // 初始化服务
     try {
       hilog.info(0x0000, TAG, 'Heanup EntryFormAbility initializing services...');
@@ -465,6 +481,11 @@ implements SizeChangeListener {
 
     hilog.info(0x0000, TAG, `Form added: ${formId}, name: ${formName}, temp: ${tempFlag}`);
 
+    // 持久化保存 Form ID(异步执行,不阻塞返回)
+    this.saveFormIdToPersistence(formId).then(() => {
+      hilog.info(0x0000, TAG, `💾 Form ID persistence completed for: ${formId}`);
+    })
+
     // 检测卡片尺寸并注册到全局管理器
     const widgetSize = this.sizeAdapter.detectSizeFromWant(want);
     try {
@@ -482,6 +503,19 @@ implements SizeChangeListener {
     // 初始化卡片数据
     this.initializeWidget(formId, widgetSize);
 
+    // 验证监听器设置状态
+    setTimeout(() => {
+      const avSessionListener = AvSessionWidgetListener.getInstance();
+      const listenerCount = avSessionListener.getListenerCount();
+      hilog.info(0x0000, TAG, `📊 Form process listener status check: ${listenerCount} listeners registered in AvSessionWidgetListener`);
+      
+      if (listenerCount === 0) {
+        hilog.warn(0x0000, TAG, `⚠️ No listeners found! Form process may not receive data updates!`);
+      } else {
+        hilog.info(0x0000, TAG, `✅ Form process has ${listenerCount} listeners, should receive data updates`);
+      }
+    }, 2000);
+
     // 添加数据流测试 - 仅在开发环境中
     setTimeout(() => {
       this.testWidgetDataFlow(formId);
@@ -571,6 +605,11 @@ implements SizeChangeListener {
   onRemoveForm(formId: string): void {
     hilog.info(0x0000, TAG, `onRemoveForm called: ${formId}`);
 
+    // 从持久化存储中移除 Form ID(异步执行)
+    this.removeFormIdFromPersistence(formId).then(() => {
+      hilog.info(0x0000, TAG, `🗑️ Form ID removal completed for: ${formId}`);
+    });
+
     // 注销各种监听器
     this.sizeAdapter.unregisterSizeChangeListener(formId);
 
@@ -912,9 +951,6 @@ implements SizeChangeListener {
     try {
       hilog.info(0x0000, TAG, `Opening widget config page for form: ${formId}`);
 
-      // 获取当前卡片信息
-      const currentSize = this.globalWidgetManager.getWidgetSize(formId) || WidgetSize.MEDIUM;
-
       // 启动主应用到卡片配置页面
       const configParams: WidgetConfigParams = {
         formId: formId,
@@ -956,4 +992,34 @@ implements SizeChangeListener {
       }
     }, 2000);
   }
+
+  /**
+   * 保存 Form ID 到持久化存储
+   */
+  private async saveFormIdToPersistence(formId: string): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `💾 Saving Form ID to persistence: ${formId}`);
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(this.context);
+      await preferencesUtil.addFormId(prefs, formId);
+      hilog.info(0x0000, TAG, `✅ Form ID saved successfully: ${formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Failed to save Form ID: ${error}`);
+    }
+  }
+
+  /**
+   * 从持久化存储中移除 Form ID
+   */
+  private async removeFormIdFromPersistence(formId: string): Promise<void> {
+    try {
+      hilog.info(0x0000, TAG, `🗑️ Removing Form ID from persistence: ${formId}`);
+      const preferencesUtil = PreferencesUtil.getInstance();
+      const prefs = await preferencesUtil.getPreferences(this.context);
+      await preferencesUtil.removeFormId(prefs, formId);
+      hilog.info(0x0000, TAG, `✅ Form ID removed successfully: ${formId}`);
+    } catch (error) {
+      hilog.error(0x0000, TAG, `❌ Failed to remove Form ID: ${error}`);
+    }
+  }
 }

+ 17 - 17
entry/src/main/ets/view/LocalMusic.ets

@@ -11397,32 +11397,32 @@ export struct LocalMusic {
         }
       };
 
-      // 更新AvSession监听器的数据
-      this.avSessionWidgetListener.updateWidgetData(widgetData);
-      
-      // 直接通过全局服务更新卡片数据(解决跨进程通信问题)
+      // 直接通过 Form ID 更新卡片数据(官方推荐方式)
       try {
-        interface GlobalWidgetServiceInstance {
-          updateWidgetData(data: WidgetData): void;
+        interface DirectFormUpdateServiceInstance {
+          updateAllForms(data: WidgetData): Promise<void>;
         }
         
-        interface GlobalWidgetServiceClass {
-          getInstance(): GlobalWidgetServiceInstance;
+        interface DirectFormUpdateServiceClass {
+          getInstance(): DirectFormUpdateServiceInstance;
         }
         
-        interface GlobalWidgetServiceModule {
-          GlobalWidgetService: GlobalWidgetServiceClass;
+        interface DirectFormUpdateServiceModule {
+          DirectFormUpdateService: DirectFormUpdateServiceClass;
         }
         
-        import('../common/widget/GlobalWidgetService').then((module: GlobalWidgetServiceModule) => {
-          const globalWidgetService = module.GlobalWidgetService.getInstance();
-          globalWidgetService.updateWidgetData(widgetData);
-          LogUtils.getInstance().LOGI('Global widget service updated successfully');
-        }).catch((error: Error) => {
-          LogUtils.getInstance().error(`Failed to import GlobalWidgetService: ${error}`);
+        import('../common/widget/DirectFormUpdateService').then((module: DirectFormUpdateServiceModule) => {
+          const directFormService = module.DirectFormUpdateService.getInstance();
+          directFormService.updateAllForms(widgetData).then(() => {
+            LogUtils.getInstance().LOGI('Direct form update completed successfully');
+          }).catch((error: Error) => {
+            LogUtils.getInstance().error(`Direct form update failed: ${error.message}`);
+          });
+        }).catch((importError: Error) => {
+          LogUtils.getInstance().error(`Failed to import DirectFormUpdateService: ${importError.message}`);
         });
       } catch (error) {
-        LogUtils.getInstance().error(`Direct widget update failed: ${error}`);
+        LogUtils.getInstance().error(`Failed to update widget via DirectFormUpdateService: ${error}`);
       }
 
       const stateData: PlayerStateBroadcastData = {