Explorar el Código

处理音频冲突

chendeben hace 1 año
padre
commit
0701fe29be

+ 5 - 18
entry/src/main/ets/common/service/PlayerManager.ets

@@ -28,8 +28,7 @@ export interface IPlayerManager {
   getIjkPlayer(): IjkMediaPlayer | null;
   setupIjkPlayerOptions(): void;
   setupPlayerCallbacks(): void;
-  handleAudioInterrupt(event: InterruptEvent): void;
-  
+
   // 播放器状态回调
   setStateCallback(callback: PlayerStateCallback): void;
   
@@ -141,11 +140,8 @@ export class PlayerManager implements IPlayerManager {
   }
 
   setupPlayerCallbacks(): void {
-    // 设置音频中断处理回调
-    this.audioInterruptCallback = (event: InterruptEvent) => {
-      this.handleAudioInterrupt(event);
-    };
-    this.mIjkMediaPlayer.on('audioInterrupt', this.audioInterruptCallback);
+    // 音频中断处理现在由 UnifiedPlayerService 统一管理
+    // 这里不再设置音频中断监听器
     
     // 设置准备完成回调
     const onPreparedListener: OnPreparedListener = {
@@ -194,17 +190,8 @@ export class PlayerManager implements IPlayerManager {
     LogUtils.getInstance().LOGI('PlayerManager callbacks configured');
   }
 
-  handleAudioInterrupt(event: InterruptEvent): void {
-    LogUtils.getInstance().LOGI(`PlayerManager audio interrupt: ${JSON.stringify(event)}`);
-    
-    if (event.hintType === InterruptHintType.INTERRUPT_HINT_PAUSE) {
-      this.pausePlayback();
-    } else if (event.hintType === InterruptHintType.INTERRUPT_HINT_RESUME) {
-      this.startPlayOrResumePlay();
-    } else if (event.hintType === InterruptHintType.INTERRUPT_HINT_STOP) {
-      this.stopPlayback();
-    }
-  }
+  // 音频中断处理已移至 UnifiedPlayerService
+  // handleAudioInterrupt 方法已移除
 
   async startPlayOrResumePlay(): Promise<void> {
     try {

+ 2 - 1
entry/src/main/ets/common/service/PlayerStateModel.ets

@@ -51,7 +51,8 @@ export enum PlayerErrorType {
   NETWORK_ERROR = 'network_error',
   FILE_NOT_FOUND = 'file_not_found',
   AUDIO_FOCUS_ERROR = 'audio_focus_error',
-  STATE_SYNC_ERROR = 'state_sync_error'
+  STATE_SYNC_ERROR = 'state_sync_error',
+  AUDIO_INTERRUPT_ERROR = 'audio_interrupt_error'
 }
 
 /**

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

@@ -3,7 +3,7 @@ import { PlayerManager, IPlayerManager, PlayerStateCallback } from './PlayerMana
 import { PlayerStateModel, PlayerState, PlayerStateListener, PlayMode, PlayerError, PlayerErrorType } from './PlayerStateModel';
 import { PlaylistModel } from './PlaylistModel';
 import { PlayProgress, WidgetData, WidgetSize, WidgetTheme } from '../widget/WidgetTypes';
-import { IjkMediaPlayer, LogUtils } from '@ohos/ijkplayer';
+import { IjkMediaPlayer, LogUtils, InterruptEvent, InterruptHintType } from '@ohos/ijkplayer';
 import { common } from '@kit.AbilityKit';
 import { PreferencesUtil, StrUtil } from '@pura/harmony-utils';
 import { DataPersistenceService, PlaylistSyncService, PlaylistSyncListener, IDataPersistenceService, PlaylistData,
@@ -148,6 +148,12 @@ export interface IPlayerService {
    * @returns
    */
   isAllServicesReady(): boolean;
+
+  /**
+   * 处理音频中断事件
+   * @param event 音频中断事件
+   */
+  handleAudioInterrupt(event: InterruptEvent): Promise<void>;
   /**
    * 等待服务就绪
    * @param maxWaitMs 最大等待时间(毫秒),默认为-1(无限等待)
@@ -311,6 +317,10 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
       // 初始化PlaylistModel的MediaTable
       this.playlistModel.initializeMediaTable(context);
 
+      // 设置音频中断监听
+      // 音频中断处理已移至LocalMusic中,响应更快
+      // this.setupAudioInterruptListener();
+
       // 设置同步监听器
       this.playlistSync.addSyncListener(this);
       this.stateSync.subscribeToStateChanges(this);
@@ -2264,6 +2274,75 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
 
   // ==================== 私有辅助方法 ====================
 
+  /**
+   * 设置音频中断监听器
+   */
+  private setupAudioInterruptListener(): void {
+    try {
+      const ijkPlayer = this.playerManager.getIjkPlayer();
+      if (ijkPlayer) {
+        ijkPlayer.on('audioInterrupt', (event: InterruptEvent) => {
+          this.handleAudioInterrupt(event);
+        });
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt listener set up successfully');
+      } else {
+        LogUtils.getInstance().LOGI('UnifiedPlayerService: Failed to set up audio interrupt listener - no player instance');
+      }
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error setting up audio interrupt listener: ${error.message}`);
+    }
+  }
+
+  /**
+   * 处理音频中断事件
+   */
+  async handleAudioInterrupt(event: InterruptEvent): Promise<void> {
+    try {
+      LogUtils.getInstance().LOGI(`onecold 与其他应用音频冲突 被截断点event: ${JSON.stringify(event)}`);
+      
+      // 首先保存当前播放位置
+      await this.savePlaybackPosition();
+
+      switch (event.hintType) {
+        case InterruptHintType.INTERRUPT_HINT_PAUSE:
+          LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt - pausing playback');
+          await this.pause();
+          break;
+
+        case InterruptHintType.INTERRUPT_HINT_RESUME:
+          LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt - resuming playback');
+          await this.startPlayOrResumePlay();
+          break;
+
+        case InterruptHintType.INTERRUPT_HINT_STOP:
+          LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt - stopping playback');
+          await this.stop();
+          break;
+
+        case InterruptHintType.INTERRUPT_HINT_DUCK:
+          LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt - ducking (lowering volume)');
+          // 可以实现音量降低逻辑
+          break;
+
+        case InterruptHintType.INTERRUPT_HINT_UNDUCK:
+          LogUtils.getInstance().LOGI('UnifiedPlayerService: Audio interrupt - unducking (restoring volume)');
+          // 可以实现音量恢复逻辑
+          break;
+
+        default:
+          LogUtils.getInstance().LOGI(`UnifiedPlayerService: Unknown audio interrupt hint type: ${event.hintType}`);
+          break;
+      }
+
+      // 通知状态变化
+      await this.updatePlaylistStateInModel();
+      await this.broadcastCurrentState();
+
+    } catch (error) {
+      LogUtils.getInstance().LOGI(`UnifiedPlayerService: Error handling audio interrupt: ${error.message}`);
+      await this.handlePlaybackError(error as Error, PlayerErrorType.AUDIO_INTERRUPT_ERROR);
+    }
+  }
   /**
    * 更新状态模型中的播放列表状态
    */

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

@@ -734,8 +734,8 @@ export struct LocalMusic {
       }
 
     }
-    // 音频中断处理现在由UnifiedPlayerService统一管理
-    // this.mIjkMediaPlayer.on('audioInterrupt', event); // 已移除,使用UnifiedPlayerService
+    // 直接在LocalMusic中处理音频中断,响应更快
+    this.unifiedPlayerService.getIjkPlayer()?.on('audioInterrupt', event);
     // 音频设备断连回调处理
     // let deviceChangeEvent: Callback<InterruptEvent> = (event) => {
     //   LogUtils.getInstance().LOGI(`Heanup deviceChange event: ${JSON.stringify(event)}`);
@@ -1104,8 +1104,8 @@ export struct LocalMusic {
     if (this.CONTROL_PlayStatus != PlayStatus.INIT) {
       this.stop();
     }
-    // 音频中断处理现在由UnifiedPlayerService统一管理
-    // this.mIjkMediaPlayer.off('audioInterrupt'); // 已移除,使用UnifiedPlayerService
+    // 移除音频中断监听器
+    this.unifiedPlayerService.getIjkPlayer()?.off('audioInterrupt');
     if (workerInstance) {
       workerInstance.terminate();
     }