EntryFormAbility.ets 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import { formBindingData, FormExtensionAbility, formProvider } from '@kit.FormKit';
  2. import { Want } from '@kit.AbilityKit';
  3. import { hilog } from '@kit.PerformanceAnalysisKit';
  4. import { WidgetData, WidgetSize } from '../common/widget/WidgetTypes';
  5. import { PreferencesUtil } from '../common/utils/PreferencesUtil';
  6. import { UnifiedPlayerService } from '../common/service/UnifiedPlayerService';
  7. import { VideoItem } from '../viewmodel/VideoItem';
  8. const TAG = 'Heanup EntryFormAbility';
  9. /**
  10. * 桌面播放器卡片扩展能力
  11. * 负责处理卡片的生命周期管理和用户交互事件
  12. * 支持多尺寸适配和UI重构
  13. */
  14. export default class EntryFormAbility extends FormExtensionAbility {
  15. private unifiedPlayerService:UnifiedPlayerService = UnifiedPlayerService.getInstance();
  16. // url -> fileName映射
  17. /**
  18. * 卡片创建时调用
  19. */
  20. onAddForm(want: Want): formBindingData.FormBindingData {
  21. // 检查参数有效性
  22. if (!want || !want.parameters) {
  23. hilog.error(0x0000, TAG, 'FormAbility onAddForm want or want.parameters is undefined');
  24. return formBindingData.createFormBindingData('');
  25. }
  26. // 初始化服务
  27. try {
  28. this.initializeServices();
  29. } catch (error) {
  30. hilog.error(0x0000, TAG, `Heanup EntryFormAbility failed to initialize services: ${error}`);
  31. }
  32. const formId = want.parameters?.['ohos.extra.param.key.form_identity'] as string;
  33. // 持久化保存 Form ID(异步执行,不阻塞返回)
  34. this.saveFormIdToPersistence(formId).then(() => {
  35. console.info('[Heanup] saveFormIdToPersistence success:'+ formId);
  36. })
  37. // 初始化卡片数据
  38. this.initializeWidget(formId);
  39. // 返回初始数据作为临时显示
  40. const adaptedData = this.buildWidgetData();
  41. return formBindingData.createFormBindingData(adaptedData);
  42. }
  43. /**
  44. * 卡片更新时调用
  45. */
  46. onUpdateForm(formId: string): void {
  47. // 只更新指定的卡片,避免重复更新
  48. this.updateWidgetData(formId);
  49. }
  50. /**
  51. * 卡片删除时调用
  52. */
  53. onRemoveForm(formId: string): void {
  54. // 从持久化存储中移除 Form ID(异步执行)
  55. this.removeFormIdFromPersistence(formId).then(() => {
  56. });
  57. }
  58. /**
  59. * 卡片可见性变化时调用
  60. */
  61. onVisibilityChange(newStatus: Record<string, number>): void {
  62. const formIds = Object.keys(newStatus);
  63. for (let i = 0; i < formIds.length; i++) {
  64. const formId = formIds[i];
  65. const isVisible = newStatus[formId] === 1;
  66. if (isVisible) {
  67. // 卡片变为可见时,更新数据
  68. this.updateWidgetData(formId);
  69. }
  70. }
  71. }
  72. /**
  73. * 卡片配置更新时调用
  74. */
  75. onConfigurationUpdate(newConfig: Object): void {
  76. // 更新所有卡片以适应新配置
  77. this.unifiedPlayerService.updateAllForms();
  78. }
  79. /**
  80. * 实现SizeChangeListener接口
  81. * 处理卡片尺寸变化事件
  82. */
  83. onSizeChanged(formId: string, oldSize: WidgetSize, newSize: WidgetSize): void {
  84. }
  85. /**
  86. * 处理卡片尺寸变化(系统调用)
  87. * @param newStatus 新的尺寸状态
  88. */
  89. onAcquireFormState(want: Want): number {
  90. // 返回卡片状态 - 使用数字常量代替枚举
  91. return 1; // READY状态
  92. }
  93. /**
  94. * 初始化服务
  95. */
  96. private initializeServices(): void {
  97. if (!this.unifiedPlayerService) {
  98. this.unifiedPlayerService = UnifiedPlayerService.getInstance();
  99. }
  100. }
  101. /**
  102. * 直接更新卡片(无网络图片)
  103. */
  104. private updateWidgetDirectly(formId: string, adaptedData: VideoItem, retryCount: number = 0): void {
  105. const formData = formBindingData.createFormBindingData(adaptedData);
  106. formProvider.updateForm(formId, formData).then(() => {
  107. }).catch(() => {
  108. hilog.error(0x0000, TAG, `Heanup widget ${formId} update failed, retry count: ${retryCount}`);
  109. // 重试机制:最多重试2次
  110. if (retryCount < 2) {
  111. setTimeout(() => {
  112. this.updateWidgetDirectly(formId, adaptedData, retryCount + 1);
  113. }, 1000 * (retryCount + 1)); // 递增延迟
  114. }
  115. });
  116. }
  117. /**
  118. * 获取默认卡片数据
  119. */
  120. private getDefaultWidgetData(): WidgetData {
  121. return {
  122. playState: {
  123. isPlaying: false,
  124. isPaused: true,
  125. isLoading: false
  126. },
  127. currentSong: {
  128. id: '',
  129. title: '暂无播放',
  130. artist: '未知艺术家',
  131. album: '未知专辑',
  132. coverImagePath: '',
  133. duration: 0
  134. },
  135. progress: {
  136. currentPosition: 0,
  137. duration: 0,
  138. percentage: 0,
  139. currentTimeText: '00:00',
  140. totalTimeText: '00:00'
  141. },
  142. playlist: {
  143. hasNext: false,
  144. hasPrevious: false,
  145. currentIndex: 0,
  146. totalCount: 0
  147. },
  148. config: {
  149. size: 'medium' as WidgetSize,
  150. theme: 'auto' as string,
  151. showProgress: true,
  152. showCover: true
  153. }
  154. };
  155. }
  156. /**
  157. * 初始化卡片
  158. */
  159. private async initializeWidget(formId: string): Promise<void> {
  160. try {
  161. // 立即更新一次卡片数据
  162. await this.updateWidgetData(formId);
  163. } catch (error) {
  164. hilog.error(0x0000, TAG, `Failed to initialize widget ${formId}: ${error}`);
  165. }
  166. }
  167. /**
  168. * 更新卡片数据(简化版本)
  169. */
  170. private async updateWidgetData(formId: string): Promise<void> {
  171. try {
  172. // 适配数据到当前尺寸并直接更新
  173. const adaptedData = this.buildWidgetData();
  174. const formData = formBindingData.createFormBindingData(adaptedData);
  175. await formProvider.updateForm(formId, formData);
  176. } catch (error) {
  177. hilog.error(0x0000, TAG, `Failed to update widget ${formId}: ${error}`);
  178. }
  179. }
  180. private buildWidgetData():VideoItem{
  181. let currentSong=this.unifiedPlayerService.getCurrentSong() as VideoItem;
  182. return currentSong;
  183. }
  184. /**
  185. * 保存 Form ID 到持久化存储
  186. */
  187. private async saveFormIdToPersistence(formId: string): Promise<void> {
  188. try {
  189. const preferencesUtil = PreferencesUtil.getInstance();
  190. const prefs = await preferencesUtil.getPreferences(this.context);
  191. await preferencesUtil.addFormId(prefs, formId);
  192. } catch (error) {
  193. hilog.error(0x0000, TAG, `❌ Failed to save Form ID: ${error}`);
  194. }
  195. }
  196. /**
  197. * 从持久化存储中移除 Form ID
  198. */
  199. private async removeFormIdFromPersistence(formId: string): Promise<void> {
  200. try {
  201. const preferencesUtil = PreferencesUtil.getInstance();
  202. const prefs = await preferencesUtil.getPreferences(this.context);
  203. await preferencesUtil.removeFormId(prefs, formId);
  204. } catch (error) {
  205. hilog.error(0x0000, TAG, `❌ Failed to remove Form ID: ${error}`);
  206. }
  207. }
  208. }