Эх сурвалжийг харах

修复bug:杀掉APP后,第一次点击卡片的播放按钮无法播放音乐,第二次才正常播放

chendeben 1 жил өмнө
parent
commit
895449d79d

+ 32 - 1
entry/src/main/ets/common/service/UnifiedPlayerService.ets

@@ -70,6 +70,7 @@ export interface IPlayerService {
   // 数据恢复状态
   isDataRestorationCompleted(): boolean;
   waitForDataRestoration(maxWaitMs?: number): Promise<boolean>;
+  forceDataRestoration(): Promise<boolean>;
   
   // 服务就绪状态检查
   isAllServicesReady(): boolean;
@@ -252,7 +253,7 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
         // 即使失败也设置数据恢复完成,避免无限等待
         this.isDataRestored = true;
       }
-    }, 50); // 短延迟,让主初始化先完成
+    }, 10); // 缩短延迟,让数据恢复更快开始
   }
 
   // 播放控制方法
@@ -711,6 +712,36 @@ async initialize(context: common.UIAbilityContext): Promise<void> {
     return this.isDataRestored;
   }
 
+  /**
+   * 强制触发数据恢复(用于桌面卡片冷启动场景)
+   */
+  async forceDataRestoration(): Promise<boolean> {
+    try {
+      LogUtils.getInstance().LOGI('UnifiedPlayerService: Force data restoration started');
+      
+      // 如果数据已经恢复,直接返回
+      if (this.isDataRestored) {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Data already restored');
+        return true;
+      }
+      
+      // 强制执行数据恢复
+      await this.restorePersistedState();
+      
+      // 如果播放列表仍为空,尝试从内存快速恢复
+      if (this.playlistModel.getTotalCount() === 0) {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Playlist empty, trying memory restore');
+        await this.fastRestoreFromMemory();
+      }
+      
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Force restoration completed, playlist size: ${this.playlistModel.getTotalCount()}`);
+      return this.isDataRestored;
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Force data restoration failed: ${error}`);
+      return false;
+    }
+  }
+
   /**
    * 检查所有相关服务是否已准备就绪
    * 用于桌面卡片控制等场景,确保在执行播放控制前服务状态正常

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

@@ -541,32 +541,58 @@ export default class EntryAbility extends UIAbility {
             
             // 对于播放控制操作,检查是否有可播放内容
             if ((command === 'PLAY_PAUSE' || command === 'NEXT_SONG' || command === 'PREV_SONG') && playlist.length === 0) {
-                hilog.warn(0x0000, 'Heanup2', '⚠️ 播放列表为空,尝试等待数据恢复');
+                hilog.warn(0x0000, 'Heanup2', '⚠️ 播放列表为空,尝试强制数据恢复');
                 
-                // 当播放列表为空时,可能是数据还没恢复完成,等待一下
-                await new Promise<void>(resolve => setTimeout(resolve, 1000));
+                // 强制触发数据恢复
+                await this.forceDataRestoration(unifiedService);
                 
                 // 重新检查播放列表
                 const updatedPlaylist = unifiedService.getPlaylist();
                 if (updatedPlaylist.length === 0) {
-                    hilog.warn(0x0000, 'Heanup2', '⚠️ 等待后播放列表仍为空,无法执行播放控制操作');
+                    hilog.warn(0x0000, 'Heanup2', '⚠️ 强制数据恢复后播放列表仍为空,无法执行播放控制操作');
                     return;
                 }
-                hilog.info(0x0000, 'Heanup2', `✅ 数据恢复完成,播放列表大小: ${updatedPlaylist.length}`);
+                hilog.info(0x0000, 'Heanup2', `✅ 强制数据恢复完成,播放列表大小: ${updatedPlaylist.length}`);
             }
             
             // 根据命令执行相应的播放控制
             switch (command) {
                 case 'PLAY_PAUSE':
-                    // 重新获取最新状态,因为可能在等待过程中发生了变化
+                    // 获取卡片传递的当前显示状态
+                    const widgetIsPlaying = params['widgetIsPlaying'] as boolean;
+                    const hasWidgetState = widgetIsPlaying !== undefined;
+                    
+                    // 获取服务内部状态
                     const latestState = unifiedService.getCurrentState();
-                    if (latestState.isPlaying) {
-                        await unifiedService.pause();
-                        hilog.info(0x0000, 'Heanup2', '✅ 卡片状态:暂停');
+                    
+                    hilog.info(0x0000, 'Heanup2', `🎵 卡片显示状态: isPlaying=${widgetIsPlaying} (有效: ${hasWidgetState})`);
+                    hilog.info(0x0000, 'Heanup2', `🎵 服务内部状态: isPlaying=${latestState.isPlaying}`);
+                    
+                    if (hasWidgetState) {
+                        // 新逻辑:根据卡片显示的状态来决定操作
+                        // - 如果卡片显示播放按钮(widgetIsPlaying=false),则执行播放操作
+                        // - 如果卡片显示暂停按钮(widgetIsPlaying=true),则执行暂停操作
+                        if (widgetIsPlaying) {
+                            // 卡片显示暂停按钮,用户点击要暂停
+                            await unifiedService.pause();
+                            hilog.info(0x0000, 'Heanup2', '✅ 卡片操作:暂停播放');
+                        } else {
+                            // 卡片显示播放按钮,用户点击要播放
+                            hilog.info(0x0000, 'Heanup2', '🔄 卡片操作:开始播放');
+                            await unifiedService.startPlayOrResumePlay();
+                            hilog.info(0x0000, 'Heanup2', '✅ 卡片操作:开始播放');
+                        }
                     } else {
-                        hilog.info(0x0000, 'Heanup2', '🔄 卡片请求:开始播放');
-                        await unifiedService.startPlayOrResumePlay();
-                        hilog.info(0x0000, 'Heanup2', '✅ 卡片状态:播放');
+                        // 向后兼容:使用原来的逻辑(根据服务内部状态)
+                        hilog.info(0x0000, 'Heanup2', '⚠️ 使用向后兼容模式(基于服务状态)');
+                        if (latestState.isPlaying) {
+                            await unifiedService.pause();
+                            hilog.info(0x0000, 'Heanup2', '✅ 兼容模式:暂停播放');
+                        } else {
+                            hilog.info(0x0000, 'Heanup2', '🔄 兼容模式:开始播放');
+                            await unifiedService.startPlayOrResumePlay();
+                            hilog.info(0x0000, 'Heanup2', '✅ 兼容模式:开始播放');
+                        }
                     }
                     break;
                     
@@ -596,6 +622,38 @@ export default class EntryAbility extends UIAbility {
         }
     }
 
+    /**
+     * 强制数据恢复(用于桌面卡片冷启动场景)
+     */
+    private async forceDataRestoration(unifiedService: UnifiedPlayerService): Promise<void> {
+        try {
+            hilog.info(0x0000, 'Heanup2', '🔄 开始强制数据恢复...');
+            
+            // 检查是否已经有数据恢复完成
+            if (unifiedService.isDataRestorationCompleted()) {
+                hilog.info(0x0000, 'Heanup2', '✅ 数据已恢复,无需强制恢复');
+                return;
+            }
+            
+            // 调用UnifiedPlayerService的强制数据恢复方法
+            const restored = await unifiedService.forceDataRestoration();
+            
+            if (restored) {
+                hilog.info(0x0000, 'Heanup2', '✅ 强制数据恢复成功');
+            } else {
+                hilog.warn(0x0000, 'Heanup2', '⚠️ 强制数据恢复失败,尝试等待');
+                // 如果强制恢复失败,再等待一段时间
+                await unifiedService.waitForDataRestoration(2000);
+            }
+            
+            // 额外等待一小段时间,确保播放列表数据完全加载
+            await new Promise<void>(resolve => setTimeout(resolve, 300));
+            
+        } catch (error) {
+            hilog.error(0x0000, 'Heanup2', `❌ 强制数据恢复失败: ${error}`);
+        }
+    }
+
     /**
      * 智能等待服务就绪(增强版本)
      */
@@ -606,14 +664,27 @@ export default class EntryAbility extends UIAbility {
             // 检查是否是刚启动的应用(数据还没恢复)
             const currentPlaylist = unifiedService.getPlaylist();
             const isJustStarted = currentPlaylist.length === 0;
+            const isDataRestored = unifiedService.isDataRestorationCompleted();
             
-            if (isJustStarted) {
-                hilog.info(0x0000, 'Heanup2', '🔄 检测到应用刚启动,给数据恢复更多时间');
-                // 给刚启动的应用更多时间来恢复数据
-                const isReady = await unifiedService.waitForAllServicesReady(8000, true);
+            if (isJustStarted || !isDataRestored) {
+                hilog.info(0x0000, 'Heanup2', `🔄 检测到冷启动状态 - 播放列表为空: ${isJustStarted}, 数据未恢复: ${!isDataRestored}`);
+                
+                // 对于冷启动,给予更长的等待时间,并强制检查数据恢复
+                const isReady = await unifiedService.waitForAllServicesReady(10000, true);
                 
                 if (isReady) {
-                    hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService完全就绪(刚启动)');
+                    hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService完全就绪(冷启动)');
+                    return true;
+                }
+                
+                // 如果仍未就绪,尝试强制触发数据恢复
+                hilog.warn(0x0000, 'Heanup2', '⚠️ 冷启动等待超时,尝试强制数据恢复');
+                await this.forceDataRestoration(unifiedService);
+                
+                // 再次检查服务状态
+                const retryReady = await unifiedService.waitForAllServicesReady(3000, false);
+                if (retryReady) {
+                    hilog.info(0x0000, 'Heanup2', '✅ 强制恢复后服务就绪');
                     return true;
                 }
             } else {
@@ -660,14 +731,21 @@ export default class EntryAbility extends UIAbility {
                 await UnifiedPlayerService.getInstance().initialize(this.context);
                 hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService 异步初始化成功');
                 
+                // 对于冷启动场景,立即尝试数据恢复
+                const unifiedService = UnifiedPlayerService.getInstance();
+                if (!unifiedService.isDataRestorationCompleted()) {
+                    hilog.info(0x0000, 'Heanup2', '🔄 冷启动检测到数据未恢复,开始预恢复');
+                    await unifiedService.forceDataRestoration();
+                }
+                
                 // 延迟广播当前状态,确保卡片能接收到初始状态
                 setTimeout(() => {
                     this.broadcastCurrentPlayerState();
-                }, 1000);
+                }, 500); // 缩短延迟,让卡片更快收到状态
             } catch (error) {
                 hilog.error(0x0000, 'Heanup2', `❌ UnifiedPlayerService 异步初始化失败: ${error}`);
             }
-        }, 100); // 短延迟,让生命周期方法先完成
+        }, 50); // 缩短延迟,让初始化更快开始
     }
 
     /**

+ 206 - 7
entry/src/main/ets/view/LocalMusic.ets

@@ -38,10 +38,13 @@ import { ColorConversion } from '../common/util/ColorConversion';
 import { LyricController, LyricParser, LyricView2 } from '@seagazer/cclyric';
 import { AvSessionController } from '../controller/AvSessionController';
 import { AvSessionWidgetListener } from '../common/widget/AvSessionWidgetListener';
-import {
-  PlayProgress} from '../common/widget/WidgetTypes';
+import { WidgetData, PlayProgress, PlayState, SongInfo, PlaylistState, PlayerStateBroadcastData } from '../common/widget/WidgetTypes';
 import { PlayerStateListener, PlayerState, PlayerError } from '../common/service/PlayerStateModel';
 import {
+  WIDGET_CONTROL_EVENT,
+  WIDGET_REQUEST_STATE_EVENT,
+  PLAYER_STATE_CHANGED_EVENT,
+  PLAYER_SONG_CHANGED_EVENT,
   PLAYER_PROGRESS_CHANGED_EVENT
 } from '../common/widget/WidgetEventConstants';
 import {
@@ -191,7 +194,7 @@ export struct LocalMusic {
   @StorageProp('windowWidth') windowWidth: number = 0;
   @StorageProp('windowHeight') windowHeight: number = 0;
   @StorageProp('isHiCarStatus') isHiCarStatus: boolean = false;
-  private UNKNOWN:string = '';
+  private UNKONWN:string = '';
   private listArea: Area = {
     width: 0,
     height: 0,
@@ -500,6 +503,8 @@ export struct LocalMusic {
           
           // 更新播放状态相关的UI
           this.localMusic.setIsPlaying(state.isPlaying);
+          this.localMusic.updateSessionPlayState(state.isPlaying);
+          
           // 如果状态发生变化,触发UI更新
           if (previousStatus !== this.localMusic.CONTROL_PlayStatus) {
             this.localMusic.playChange();
@@ -649,7 +654,7 @@ export struct LocalMusic {
       PreferencesUtil.putSync('isFirstTiped',false)
     }
     this.initSetting()
-    this.UNKNOWN = Utility.resourceToString(this.context, $r('app.string.unknown'));
+    this.UNKONWN = Utility.resourceToString(this.context, $r('app.string.unknown'));
     this.topRectHeight = px2vp(AppUtil.getStatusBarHeight());
     Utility.getAppName(getContext(this)).then((appName: string) => {
       this.appName = appName
@@ -3119,7 +3124,7 @@ export struct LocalMusic {
                     .padding({ top: 8 })
                     .maxLines(1)
                     .visibility(StrUtil.isEmpty(this.videoLocalList[0].genre)||
-                    this.videoLocalList[0].genre.includes(this.UNKNOWN)
+                    this.videoLocalList[0].genre.includes(this.UNKONWN)
                       ?Visibility.None:Visibility.Visible)
                     .fontWeight(FontWeight.Bold)
                     .fontColor($r('app.color.text_color'))
@@ -3131,7 +3136,7 @@ export struct LocalMusic {
                     .padding({ top: 8 })
                     .maxLines(1)
                     .visibility(StrUtil.isEmpty(this.videoLocalList[0].year)||
-                       this.videoLocalList[0].year.includes(this.UNKNOWN)
+                       this.videoLocalList[0].year.includes(this.UNKONWN)
                       ?Visibility.None:Visibility.Visible)
                     .fontWeight(FontWeight.Bold)
                     .fontColor($r('app.color.text_color'))
@@ -5813,6 +5818,7 @@ export struct LocalMusic {
     //退出APP
     const mContext = getContext(this) as common.UIAbilityContext
     mContext.terminateSelf();
+    AvSessionController.getInstance(true).unregisterSessionListener()
 
   }
 
@@ -9697,7 +9703,8 @@ export struct LocalMusic {
       // 更新播放状态
       this.CONTROL_PlayStatus = PlayStatus.PLAY;
       this.setIsPlaying(true);
-
+      this.updateSessionPlayState(true);
+      
       LogUtils.getInstance().LOGI("LocalMusic: startPlayOrResumePlay completed via UnifiedPlayerService");
     } catch (error) {
       LogUtils.getInstance().LOGI(`LocalMusic startPlayOrResumePlay error: ${error}`);
@@ -9712,6 +9719,7 @@ export struct LocalMusic {
   private handlePlaybackError() {
     this.CONTROL_PlayStatus = PlayStatus.INIT;
     this.setIsPlaying(false);
+    this.updateSessionPlayState(false);
     this.mDestroyPage = true;
   }
 
@@ -10030,6 +10038,16 @@ export struct LocalMusic {
     this.replayVisible = Visibility.None;
   }
 
+  private hideLoadIng() {
+    this.loadingVisible = Visibility.None;
+    this.replayVisible = Visibility.None;
+  }
+
+  private showRePlay() {
+    this.loadingVisible = Visibility.None;
+    this.replayVisible = Visibility.Visible;
+  }
+
   // 原来的 play 方法已移除,播放逻辑现在由 UnifiedPlayerService 统一处理
   // private async play(url: string) { ... } 已移除
 
@@ -10038,6 +10056,12 @@ export struct LocalMusic {
 
   // 所有的播放器配置和监听器设置已移至 UnifiedPlayerService
 
+  //保存最后播放的那首歌和已经对应的播放列表
+  saveLastPlayList() {
+    PreferencesUtil.putSync('LastMusicInfo', this.currentSong)
+    PreferencesUtil.putSync('LastMusicList', this.songList)
+
+  }
 
   // 清空播放记录
   clearVideoHistory() {
@@ -10056,6 +10080,24 @@ export struct LocalMusic {
 
   }
 
+  public async setAvSessionListener() {
+    if (!this.avSessionController) {
+      return;
+    }
+    this.avSessionController.getAvSession()?.on('play', this.sessionPlayCallback);
+    this.avSessionController.getAvSession()?.on('pause', this.sessionPauseCallback);
+    this.avSessionController.getAvSession()?.on('stop', this.sessionStopCallback);
+    this.avSessionController.getAvSession()?.on('playNext', this.sessionPlayNextCallback);
+    this.avSessionController.getAvSession()?.on('playPrevious', this.sessionPlayPreviousCallback);
+    this.avSessionController.getAvSession()?.on('fastForward', this.sessionFastForwardCallback);
+    this.avSessionController.getAvSession()?.on('rewind', this.sessionRewindCallback);
+    this.avSessionController.getAvSession()?.on('seek', this.sessionSeekCallback);
+    this.avSessionController.getAvSession()?.on('setLoopMode', this.sessionSetLoopModeCallback);
+    this.avSessionController.getAvSession()?.on('toggleFavorite', this.sessionToggleFavoriteCallback);
+
+    this.avSessionController.getAvSession()?.on('outputDeviceChange', this.sessionOutputDeviceChange)
+
+  }
 
   setLoopMode() {
     let itype = this.playType + 1
@@ -10141,6 +10183,54 @@ export struct LocalMusic {
     });
   }
 
+  private sessionToggleFavoriteCallback = (assetId: string) => {
+    if (this.currentSong) {
+      console.info(`on toggleFavorite `);
+      // 应用收到收藏命令,进行收藏处理。
+
+      this.isFac = Utility.getIsFav(this.favList, this.currentSong)
+      this.doFav(this.currentSong)
+      // 应用内完成或者取消收藏,把新的收藏状态设置给AVSession。
+      let playbackState: avSession.AVPlaybackState = {
+        isFavorite: !this.isFac,
+      };
+      this.avSessionController.getAvSession()?.setAVPlaybackState(playbackState).then(() => {
+        console.info(`SetAVPlaybackState successfully`);
+      }).catch((err: BusinessError) => {
+        console.info(`SetAVPlaybackState BusinessError: code: ${err.code}, message: ${err.message}`);
+      });
+    }
+  }
+  private sessionOutputDeviceChange = async (connectState: avSession.ConnectionState,
+    device: avSession.OutputDeviceInfo) => {
+    let currentDevice: avSession.DeviceInfo = device?.devices?.[0];
+    if (currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_REMOTE &&
+      connectState === avSession.ConnectionState.STATE_CONNECTED) {
+
+      await this.startCasting();
+
+    } else if ((currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_REMOTE &&
+      connectState === avSession.ConnectionState.STATE_DISCONNECTED) ||
+      (currentDevice.castCategory === avSession.AVCastCategory.CATEGORY_LOCAL &&
+        connectState === avSession.ConnectionState.STATE_CONNECTED)) {
+      if (device) {
+        this.endCasting();
+      }
+    }
+  };
+
+  private async startCasting() {
+    this.castController = await this.avSessionController.getAvSession()?.getAVCastController();
+    this.setPlaybackStateChangeListener();
+    this.pause();
+    this.initQueueItem();
+    this.prepare();
+    let refToIsCasting: AbstractProperty<boolean> | undefined = AppStorage.ref('isCasting');
+    refToIsCasting?.set(true);
+    this.castSeek = true;
+    this.isCastPlaying = true;
+  }
+
   async changeCasting() {
     this.castController = await this.avSessionController.getAvSession()?.getAVCastController();
     this.initQueueItem();
@@ -10179,6 +10269,37 @@ export struct LocalMusic {
     this.castController?.on('playPrevious', this.playPreviousCallback);
   }
 
+  private updateSessionPlayState(isPlay: boolean): void {
+    // if(!this.isBgPlayOpen)
+    //   return
+    Logger.info(TAG, `updateIsPlay isPlay: ${isPlay}`);
+    try {
+      // 通过UnifiedPlayerService获取当前位置
+      const currentState = this.unifiedPlayerService.getCurrentState();
+      this.setAVSessionPlayState({
+        state: isPlay ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
+        position: {
+          elapsedTime: currentState.currentPosition,
+          updateTime: new Date().getTime()
+        }
+      });
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`updateSessionPlayState error: ${error}`);
+      // 如果获取失败,使用默认值
+      this.setAVSessionPlayState({
+        state: isPlay ? avSession.PlaybackState.PLAYBACK_STATE_PLAY : avSession.PlaybackState.PLAYBACK_STATE_PAUSE,
+        position: {
+          elapsedTime: 0,
+          updateTime: new Date().getTime()
+        }
+      });
+    }
+  }
+
+  private setAVSessionPlayState(playbackState: avSession.AVPlaybackState): void {
+    this.avSessionController.setAvSessionPlayState(playbackState)
+  }
+
   private positionChange(position: number) {
     this.currentTime2 = position / 1000;
     this.currentStringTime = secondToTime(Math.floor(position / 1000));
@@ -10431,6 +10552,7 @@ export struct LocalMusic {
       this.mDestroyPage = true;
       this.CONTROL_PlayStatus = PlayStatus.PAUSE;
       this.setIsPlaying(false);
+      this.updateSessionPlayState(false);
       this.playChange()
       
       if (this.pipController) {
@@ -10454,6 +10576,7 @@ export struct LocalMusic {
       this.stopProgressTask();
       this.CONTROL_PlayStatus = PlayStatus.INIT;
       this.setIsPlaying(false);
+      this.updateSessionPlayState(false)
       this.playChange()
       this.watchStatus();
       
@@ -11249,6 +11372,82 @@ export struct LocalMusic {
     // this.status = "广告加载中..."
   }
 
+  /**
+   * 展示Banner广告
+   */
+  // showBannerAd() {
+  //   if (!this.bannerAd) {
+  //     return
+  //   }
+  //   this.isShowAd = true
+  //   this.status = "已展示"
+  // }
+
+  /**
+   * 穿山甲广告代码结束
+   */
+
+  /**
+   * 初始化AvSession卡片监听器
+   */
+  private initAvSessionWidgetListener(): void {
+    try {
+      // 不需要在这里注册监听器,因为我们直接通过updateWidgetData更新数据
+      // 避免循环调用和重复广播
+      LogUtils.getInstance().LOGI('AvSession widget listener initialized successfully (no circular listener)');
+    } catch (error) {
+      LogUtils.getInstance().error(`Failed to initialize AvSession widget listener: ${error}`);
+    }
+  }
+
+  /**
+   * 广播AvSession状态到卡片
+   */
+  private broadcastAvSessionStateToWidget(widgetData: WidgetData): void {
+    try {
+      // 广播播放状态变化
+      const statePublishInfo: commonEventManager.CommonEventPublishData = {
+        data: JSON.stringify(widgetData)
+      };
+
+      commonEventManager.publish(PLAYER_STATE_CHANGED_EVENT, statePublishInfo, (err) => {
+        if (err) {
+          LogUtils.getInstance().error(`Failed to broadcast AvSession state: ${JSON.stringify(err)}`);
+        } else {
+          LogUtils.getInstance().LOGI('AvSession state broadcasted to widget successfully');
+        }
+      });
+
+      // 如果有歌曲信息变化,也广播歌曲变化事件
+      if (widgetData.currentSong) {
+        const songPublishInfo: commonEventManager.CommonEventPublishData = {
+          data: JSON.stringify({ currentSong: widgetData.currentSong })
+        };
+
+        commonEventManager.publish(PLAYER_SONG_CHANGED_EVENT, songPublishInfo, (err) => {
+          if (err) {
+            LogUtils.getInstance().error(`Failed to broadcast song change: ${JSON.stringify(err)}`);
+          }
+        });
+      }
+
+      // 如果有进度信息变化,也广播进度变化事件
+      if (widgetData.progress) {
+        const progressPublishInfo: commonEventManager.CommonEventPublishData = {
+          data: JSON.stringify(widgetData.progress)
+        };
+
+        commonEventManager.publish(PLAYER_PROGRESS_CHANGED_EVENT, progressPublishInfo, (err) => {
+          if (err) {
+            LogUtils.getInstance().error(`Failed to broadcast progress change: ${JSON.stringify(err)}`);
+          }
+        });
+      }
+    } catch (error) {
+      LogUtils.getInstance().error(`Failed to broadcast AvSession state to widget: ${error}`);
+    }
+  }
+
   /**
    * 节流广播进度更新
    */

+ 2 - 1
entry/src/main/ets/widget/pages/PlayerWidgetMedium.ets

@@ -247,7 +247,8 @@ struct PlayerWidgetMedium {
               'abilityName': 'EntryAbility',
               'params': {
                 'formId': this.formId,
-                'method': 'playPause'
+                'method': 'playPause',
+                'widgetIsPlaying': this.isPlaying // 传递卡片当前显示的播放状态
               }
             });
           }

+ 2 - 1
entry/src/main/ets/widget/pages/PlayerWidgetSmall.ets

@@ -63,7 +63,8 @@ struct PlayerWidgetSmall {
             'abilityName': 'EntryAbility',
             'params': {
               'formId': this.formId,
-              'method': 'playPause'
+              'method': 'playPause',
+              'widgetIsPlaying': this.isPlaying // 传递卡片当前显示的播放状态
             }
           });
         }

+ 2 - 1
entry/src/main/ets/widget/pages/PlayerWidgetSquare.ets

@@ -145,7 +145,8 @@ struct PlayerWidgetSquare {
               'abilityName': 'EntryAbility',
               'params': {
                 'formId': this.formId,
-                'method': 'playPause'
+                'method': 'playPause',
+                'widgetIsPlaying': this.isPlaying // 传递卡片当前显示的播放状态
               }
             });
           }