import commonEventManager from '@ohos.commonEventManager'; import Want from '@ohos.app.ability.Want'; import common from '@ohos.app.ability.common'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { WidgetData, WidgetCommand, EventData, RequestData, WidgetControlParams } from './WidgetTypes'; import { WIDGET_CONTROL_EVENT, WIDGET_REQUEST_STATE_EVENT, PLAYER_STATE_CHANGED_EVENT, PLAYER_SONG_CHANGED_EVENT, PLAYER_PROGRESS_CHANGED_EVENT, APP_BUNDLE_NAME, APP_ABILITY_NAME } from './WidgetEventConstants'; const TAG = 'PlayerControlService'; /** * 播放器控制服务 * 负责与主应用的播放器进行通信和状态同步 */ export class PlayerControlService { private stateListeners: Array<(data: WidgetData) => void> = []; private isListenerRegistered: boolean = false; constructor() { this.initializeEventListener(); } /** * 初始化事件监听器 */ private async initializeEventListener(): Promise { if (this.isListenerRegistered) { return; } try { // 监听播放状态变化事件 const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = { events: [ PLAYER_STATE_CHANGED_EVENT, PLAYER_SONG_CHANGED_EVENT, PLAYER_PROGRESS_CHANGED_EVENT ] }; const subscriber = await commonEventManager.createSubscriber(subscribeInfo); await commonEventManager.subscribe(subscriber, (err, data: commonEventManager.CommonEventData) => { if (!err) { this.handlePlayerStateChange(data); } }); this.isListenerRegistered = true; hilog.info(0x0000, TAG, 'Event listener initialized successfully'); } catch (error) { hilog.error(0x0000, TAG, `Failed to initialize event listener: ${error}`); } } /** * 发送控制命令到主应用 */ async sendControlCommand(command: WidgetCommand, params?: WidgetControlParams): Promise { try { const defaultParams: WidgetControlParams = {}; const eventData: EventData = { command: command, params: params || defaultParams, timestamp: Date.now(), source: 'widget' }; // 发送CommonEvent到主应用 const publishInfo: commonEventManager.CommonEventPublishData = { data: JSON.stringify(eventData) }; await commonEventManager.publish(WIDGET_CONTROL_EVENT, publishInfo, (err) => { if (err) { hilog.error(0x0000, TAG, `Failed to publish event: ${err}`); } }); hilog.info(0x0000, TAG, `Control command sent: ${command}`); return true; } catch (error) { hilog.error(0x0000, TAG, `Failed to send control command: ${error}`); return false; } } /** * 获取当前播放状态 */ async getCurrentPlayState(): Promise { try { // 请求当前状态 const requestData: RequestData = { timestamp: Date.now() }; const requestInfo: commonEventManager.CommonEventPublishData = { data: JSON.stringify(requestData) }; await commonEventManager.publish(WIDGET_REQUEST_STATE_EVENT, requestInfo, (err) => { if (err) { hilog.error(0x0000, TAG, `Failed to publish request state event: ${err}`); } }); // 返回默认状态,实际状态会通过事件监听器更新 return this.getDefaultWidgetData(); } catch (error) { hilog.error(0x0000, TAG, `Failed to get current play state: ${error}`); return this.getDefaultWidgetData(); } } /** * 注册状态变化监听器 */ registerStateListener(callback: (data: WidgetData) => void): void { this.stateListeners.push(callback); hilog.info(0x0000, TAG, 'State listener registered'); } /** * 启动主应用 */ async launchMainApp(page?: string): Promise { try { const want: Want = { bundleName: APP_BUNDLE_NAME, abilityName: APP_ABILITY_NAME, parameters: { page: page || 'main', source: 'widget', // 标识来源是卡片 timestamp: Date.now().toString() } }; const context = getContext() as common.UIAbilityContext; await context.startAbility(want); hilog.info(0x0000, TAG, `Main app launched with page: ${page}`); return true; } catch (error) { hilog.error(0x0000, TAG, `Failed to launch main app: ${error}`); // 如果启动失败,尝试启动到默认页面 try { const fallbackWant: Want = { bundleName: APP_BUNDLE_NAME, abilityName: APP_ABILITY_NAME }; const context = getContext() as common.UIAbilityContext; await context.startAbility(fallbackWant); hilog.info(0x0000, TAG, 'Main app launched with fallback method'); return true; } catch (fallbackError) { hilog.error(0x0000, TAG, `Fallback launch also failed: ${fallbackError}`); return false; } } } /** * 处理播放器状态变化 */ private handlePlayerStateChange(eventData: commonEventManager.CommonEventData): void { try { const data = JSON.parse(eventData.data || '{}') as Object; const widgetData = this.convertToWidgetData(data); // 通知所有监听器 this.stateListeners.forEach((listener: (data: WidgetData) => void) => { try { listener(widgetData); } catch (error) { hilog.error(0x0000, TAG, `Error in state listener: ${error}`); } }); hilog.info(0x0000, TAG, 'Player state change handled'); } catch (error) { hilog.error(0x0000, TAG, `Failed to handle player state change: ${error}`); } } /** * 转换播放器数据为卡片数据格式 */ private convertToWidgetData(playerData: Object): WidgetData { // 返回默认的卡片数据,避免索引访问 return this.getDefaultWidgetData(); } /** * 获取默认卡片数据 */ private getDefaultWidgetData(): WidgetData { return { playState: { isPlaying: false, isPaused: true, isLoading: false }, currentSong: { id: '', title: '暂无播放', artist: '未知艺术家', album: '未知专辑', coverImagePath: '', duration: 0 }, progress: { currentPosition: 0, duration: 0, percentage: 0, currentTimeText: '00:00', totalTimeText: '00:00' }, playlist: { hasNext: false, hasPrevious: false, currentIndex: 0, totalCount: 0 }, config: { size: 'medium', theme: 'auto', showProgress: true, showCover: true } }; } /** * 计算播放进度百分比 */ private calculatePercentage(current: number, total: number): number { if (total <= 0) return 0; return Math.min(100, Math.max(0, (current / total) * 100)); } /** * 格式化时间显示 */ private formatTime(seconds: number): string { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; } }