GlobalWidgetService.ets 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { hilog } from '@kit.PerformanceAnalysisKit';
  2. import { PlaylistState, PlayProgress, PlayState, SongInfo, WidgetConfig, WidgetData } from './WidgetTypes';
  3. import { AvSessionWidgetListener } from './AvSessionWidgetListener';
  4. import commonEventManager from '@ohos.commonEventManager';
  5. import {
  6. PLAYER_STATE_CHANGED_EVENT,
  7. PLAYER_SONG_CHANGED_EVENT,
  8. PLAYER_PROGRESS_CHANGED_EVENT
  9. } from './WidgetEventConstants';
  10. const TAG = 'GlobalWidgetService';
  11. /**
  12. * 全局卡片服务
  13. * 用于主应用直接更新卡片数据,绕过跨进程通信限制
  14. */
  15. interface GeneratedObjectLiteralInterface_1 {
  16. playState: PlayState;
  17. currentSong: SongInfo;
  18. progress: PlayProgress;
  19. playlist: PlaylistState;
  20. config: WidgetConfig;
  21. timestamp: number;
  22. source: string;
  23. }
  24. export class GlobalWidgetService {
  25. private static instance: GlobalWidgetService | null = null;
  26. private avSessionListener: AvSessionWidgetListener;
  27. private constructor() {
  28. this.avSessionListener = AvSessionWidgetListener.getInstance();
  29. }
  30. public static getInstance(): GlobalWidgetService {
  31. if (!GlobalWidgetService.instance) {
  32. GlobalWidgetService.instance = new GlobalWidgetService();
  33. }
  34. return GlobalWidgetService.instance;
  35. }
  36. /**
  37. * 更新卡片数据(主应用调用)
  38. */
  39. public updateWidgetData(data: WidgetData): void {
  40. try {
  41. // 在全局服务层面也进行按钮状态验证和修复
  42. const correctedData = this.validateAndFixButtonStates(data);
  43. // 同步更新主进程的AvSession监听器数据(用于主应用内的逻辑)
  44. this.avSessionListener.updateWidgetData(correctedData);
  45. // 通过 CommonEvent 发送数据到 Form 进程
  46. this.broadcastToFormProcess(correctedData);
  47. 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}`);
  48. } catch (error) {
  49. hilog.error(0x0000, TAG, `Failed to update widget data globally: ${error}`);
  50. }
  51. }
  52. /**
  53. * 通过 CommonEvent 广播数据到 Form 进程
  54. */
  55. private async broadcastToFormProcess(data: WidgetData): Promise<void> {
  56. try {
  57. hilog.info(0x0000, TAG, `🚀 Starting broadcast to form process for: ${data.currentSong.title}`);
  58. // 构造广播数据
  59. const broadcastData: GeneratedObjectLiteralInterface_1 = {
  60. playState: data.playState,
  61. currentSong: data.currentSong,
  62. progress: data.progress,
  63. playlist: data.playlist,
  64. config: data.config,
  65. timestamp: Date.now(),
  66. source: 'main_app_global_service'
  67. };
  68. const publishInfo: commonEventManager.CommonEventPublishData = {
  69. data: JSON.stringify(broadcastData)
  70. };
  71. hilog.info(0x0000, TAG, `🚀 Publishing CommonEvent: ${PLAYER_STATE_CHANGED_EVENT}, data size: ${publishInfo.data?.length || 0} characters`);
  72. // 发送状态变化事件到 Form 进程
  73. await commonEventManager.publish(PLAYER_STATE_CHANGED_EVENT, publishInfo, (err) => {
  74. if (err) {
  75. hilog.error(0x0000, TAG, `❌ Failed to broadcast to form process: ${JSON.stringify(err)}`);
  76. } else {
  77. hilog.info(0x0000, TAG, `✅ Successfully broadcasted widget data to form process: ${data.currentSong.title}`);
  78. }
  79. });
  80. } catch (error) {
  81. hilog.error(0x0000, TAG, `❌ Error broadcasting to form process: ${error}`);
  82. }
  83. }
  84. /**
  85. * 验证和修复按钮状态
  86. */
  87. private validateAndFixButtonStates(data: WidgetData): WidgetData {
  88. hilog.info(0x0000, TAG, `Validating button states: original hasNext=${data.playlist.hasNext}, hasPrevious=${data.playlist.hasPrevious}, currentIndex=${data.playlist.currentIndex}, totalCount=${data.playlist.totalCount}`);
  89. // 创建新的 WidgetData 对象
  90. const correctedData: WidgetData = {
  91. playState: {
  92. isPlaying: data.playState.isPlaying,
  93. isPaused: data.playState.isPaused,
  94. isLoading: data.playState.isLoading
  95. },
  96. currentSong: {
  97. id: data.currentSong.id,
  98. title: data.currentSong.title,
  99. artist: data.currentSong.artist,
  100. album: data.currentSong.album,
  101. coverImagePath: data.currentSong.coverImagePath,
  102. duration: data.currentSong.duration
  103. },
  104. progress: {
  105. currentPosition: data.progress.currentPosition,
  106. duration: data.progress.duration,
  107. percentage: data.progress.percentage,
  108. currentTimeText: data.progress.currentTimeText,
  109. totalTimeText: data.progress.totalTimeText
  110. },
  111. playlist: {
  112. hasNext: data.playlist.hasNext,
  113. hasPrevious: data.playlist.hasPrevious,
  114. currentIndex: data.playlist.currentIndex,
  115. totalCount: data.playlist.totalCount
  116. },
  117. config: {
  118. size: data.config.size,
  119. theme: data.config.theme,
  120. showProgress: data.config.showProgress,
  121. showCover: data.config.showCover
  122. }
  123. };
  124. // 注意:这里不再简单地基于索引修复按钮状态
  125. // 因为按钮状态应该由 UnifiedPlayerService 中的播放模式逻辑正确计算
  126. // 在随机播放模式下,按钮状态取决于播放历史记录,而不是简单的索引位置
  127. if (data.playlist.totalCount > 1) {
  128. // 保持从 UnifiedPlayerService 传来的状态,这些状态已经考虑了播放模式
  129. hilog.info(0x0000, TAG, `Keeping original button states from UnifiedPlayerService: hasNext=${data.playlist.hasNext}, hasPrevious=${data.playlist.hasPrevious}`);
  130. } else {
  131. // 单首歌或无歌曲时,禁用所有按钮
  132. correctedData.playlist.hasNext = false;
  133. correctedData.playlist.hasPrevious = false;
  134. hilog.info(0x0000, TAG, `Single song or empty playlist, disabled all navigation buttons`);
  135. }
  136. return correctedData;
  137. }
  138. }