|
@@ -1,4 +1,3 @@
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 应用主Ability入口文件
|
|
* 应用主Ability入口文件
|
|
|
* 功能:
|
|
* 功能:
|
|
@@ -21,76 +20,80 @@ import { systemShare } from '@kit.ShareKit';
|
|
|
import { CustomCrashHandler } from '../common/utils/CustomCrashHandler';
|
|
import { CustomCrashHandler } from '../common/utils/CustomCrashHandler';
|
|
|
import { smartMobilityCommon } from '@kit.CarKit';
|
|
import { smartMobilityCommon } from '@kit.CarKit';
|
|
|
import { display } from '@kit.ArkUI';
|
|
import { display } from '@kit.ArkUI';
|
|
|
-import {PreferencesUtil} from '../common/utils/PreferencesUtil'
|
|
|
|
|
|
|
+import { PreferencesUtil } from '../common/utils/PreferencesUtil'
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 播放状态广播数据接口
|
|
* 播放状态广播数据接口
|
|
|
*/
|
|
*/
|
|
|
interface PlayStateBroadcast {
|
|
interface PlayStateBroadcast {
|
|
|
- isPlaying: boolean;
|
|
|
|
|
- isPaused: boolean;
|
|
|
|
|
- isLoading: boolean;
|
|
|
|
|
|
|
+ isPlaying: boolean;
|
|
|
|
|
+ isPaused: boolean;
|
|
|
|
|
+ isLoading: boolean;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface SongBroadcast {
|
|
interface SongBroadcast {
|
|
|
- id: string;
|
|
|
|
|
- title: string;
|
|
|
|
|
- artist: string;
|
|
|
|
|
- album: string;
|
|
|
|
|
- coverImagePath: string;
|
|
|
|
|
- duration: number;
|
|
|
|
|
|
|
+ id: string;
|
|
|
|
|
+ title: string;
|
|
|
|
|
+ artist: string;
|
|
|
|
|
+ album: string;
|
|
|
|
|
+ coverImagePath: string;
|
|
|
|
|
+ duration: number;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface ProgressBroadcast {
|
|
interface ProgressBroadcast {
|
|
|
- currentPosition: number;
|
|
|
|
|
- duration: number;
|
|
|
|
|
- percentage: number;
|
|
|
|
|
- currentTimeText: string;
|
|
|
|
|
- totalTimeText: string;
|
|
|
|
|
|
|
+ currentPosition: number;
|
|
|
|
|
+ duration: number;
|
|
|
|
|
+ percentage: number;
|
|
|
|
|
+ currentTimeText: string;
|
|
|
|
|
+ totalTimeText: string;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface PlaylistBroadcast {
|
|
interface PlaylistBroadcast {
|
|
|
- hasNext: boolean;
|
|
|
|
|
- hasPrevious: boolean;
|
|
|
|
|
- currentIndex: number;
|
|
|
|
|
- totalCount: number;
|
|
|
|
|
|
|
+ hasNext: boolean;
|
|
|
|
|
+ hasPrevious: boolean;
|
|
|
|
|
+ currentIndex: number;
|
|
|
|
|
+ totalCount: number;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface BroadcastData {
|
|
interface BroadcastData {
|
|
|
- playState: PlayStateBroadcast;
|
|
|
|
|
- currentSong: SongBroadcast;
|
|
|
|
|
- progress: ProgressBroadcast;
|
|
|
|
|
- playlist: PlaylistBroadcast;
|
|
|
|
|
|
|
+ playState: PlayStateBroadcast;
|
|
|
|
|
+ currentSong: SongBroadcast;
|
|
|
|
|
+ progress: ProgressBroadcast;
|
|
|
|
|
+ playlist: PlaylistBroadcast;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface PublishInfo {
|
|
interface PublishInfo {
|
|
|
- data: string;
|
|
|
|
|
|
|
+ data: string;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
interface EventDataWrapper {
|
|
interface EventDataWrapper {
|
|
|
- data: BroadcastData;
|
|
|
|
|
|
|
+ data: BroadcastData;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* RPC通信返回类型的实现,用于RPC通信数据序列化和反序列化
|
|
* RPC通信返回类型的实现,用于RPC通信数据序列化和反序列化
|
|
|
*/
|
|
*/
|
|
|
class MyParcelable implements rpc.Parcelable {
|
|
class MyParcelable implements rpc.Parcelable {
|
|
|
- num: number;
|
|
|
|
|
- str: string;
|
|
|
|
|
- constructor(num: number, str: string) {
|
|
|
|
|
- this.num = num;
|
|
|
|
|
- this.str = str;
|
|
|
|
|
- }
|
|
|
|
|
- marshalling(messageSequence: rpc.MessageSequence): boolean {
|
|
|
|
|
- messageSequence.writeInt(this.num);
|
|
|
|
|
- messageSequence.writeString(this.str);
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- unmarshalling(messageSequence: rpc.MessageSequence): boolean {
|
|
|
|
|
- this.num = messageSequence.readInt();
|
|
|
|
|
- this.str = messageSequence.readString();
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ num: number;
|
|
|
|
|
+ str: string;
|
|
|
|
|
+
|
|
|
|
|
+ constructor(num: number, str: string) {
|
|
|
|
|
+ this.num = num;
|
|
|
|
|
+ this.str = str;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ marshalling(messageSequence: rpc.MessageSequence): boolean {
|
|
|
|
|
+ messageSequence.writeInt(this.num);
|
|
|
|
|
+ messageSequence.writeString(this.str);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ unmarshalling(messageSequence: rpc.MessageSequence): boolean {
|
|
|
|
|
+ this.num = messageSequence.readInt();
|
|
|
|
|
+ this.str = messageSequence.readString();
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -101,767 +104,752 @@ class MyParcelable implements rpc.Parcelable {
|
|
|
* - 事件分发
|
|
* - 事件分发
|
|
|
*/
|
|
*/
|
|
|
export default class EntryAbility extends UIAbility {
|
|
export default class EntryAbility extends UIAbility {
|
|
|
- // UI上下文对象,用于获取窗口信息
|
|
|
|
|
- private uiContext?: UIContext;
|
|
|
|
|
- // private awareness: smartMobilityCommon.SmartMobilityAwareness = smartMobilityCommon.getSmartMobilityAwareness();
|
|
|
|
|
- private awareness: smartMobilityCommon.SmartMobilityAwareness|undefined = canIUse("SystemCapability.SmartOptimizer.SmartMobility")?smartMobilityCommon.getSmartMobilityAwareness():undefined;
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 窗口尺寸变化回调函数
|
|
|
|
|
- * @param windowSize 新的窗口尺寸对象
|
|
|
|
|
- * 功能:
|
|
|
|
|
- * 1. 获取最新的窗口断点尺寸
|
|
|
|
|
- * 2. 更新AppStorage中的尺寸状态
|
|
|
|
|
- * 3. 记录尺寸变化日志
|
|
|
|
|
- */
|
|
|
|
|
- private onWindowSizeChange: (windowSize: window.Size) => void = async (windowSize: window.Size) => {
|
|
|
|
|
- // 获取宽度断点并更新全局状态
|
|
|
|
|
- let widthBp = this.uiContext!.getWindowWidthBreakpoint();
|
|
|
|
|
- AppStorage.setOrCreate('currentWidthBreakpoint', widthBp);
|
|
|
|
|
-
|
|
|
|
|
- // 获取高度断点并更新全局状态
|
|
|
|
|
- let heightBp = this.uiContext!.getWindowHeightBreakpoint();
|
|
|
|
|
- AppStorage.setOrCreate('currentHeightBreakpoint', heightBp);
|
|
|
|
|
- // 记录尺寸变化日志
|
|
|
|
|
- // LogUtil.info('pura onWindowSizeChange currentHeightBreakpoint= '+heightBp);
|
|
|
|
|
- // LogUtil.info( 'pura onWindowSizeChange currentWidthBreakpoint= '+widthBp);
|
|
|
|
|
- AppStorage.setOrCreate('windowWidth', windowSize.width);
|
|
|
|
|
- AppStorage.setOrCreate('windowHeight', windowSize.height);
|
|
|
|
|
- if(windowSize.width > windowSize.height){
|
|
|
|
|
- AppStorage.setOrCreate('isLandscape', true);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('isLandscape', false);
|
|
|
|
|
- }
|
|
|
|
|
- // LogUtil.info('hicar onWindowSizeChange width= '+windowSize.width);
|
|
|
|
|
- // LogUtil.info( 'hicar onWindowSizeChange height= '+windowSize.height);
|
|
|
|
|
-
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+ // UI上下文对象,用于获取窗口信息
|
|
|
|
|
+ private uiContext?: UIContext;
|
|
|
|
|
+ // private awareness: smartMobilityCommon.SmartMobilityAwareness = smartMobilityCommon.getSmartMobilityAwareness();
|
|
|
|
|
+ private awareness: smartMobilityCommon.SmartMobilityAwareness | undefined =
|
|
|
|
|
+ canIUse("SystemCapability.SmartOptimizer.SmartMobility") ? smartMobilityCommon.getSmartMobilityAwareness() :
|
|
|
|
|
+ undefined;
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 窗口尺寸变化回调函数
|
|
|
|
|
+ * @param windowSize 新的窗口尺寸对象
|
|
|
|
|
+ * 功能:
|
|
|
|
|
+ * 1. 获取最新的窗口断点尺寸
|
|
|
|
|
+ * 2. 更新AppStorage中的尺寸状态
|
|
|
|
|
+ * 3. 记录尺寸变化日志
|
|
|
|
|
+ */
|
|
|
|
|
+ private onWindowSizeChange: (windowSize: window.Size) => void = async (windowSize: window.Size) => {
|
|
|
|
|
+ // 获取宽度断点并更新全局状态
|
|
|
|
|
+ let widthBp = this.uiContext!.getWindowWidthBreakpoint();
|
|
|
|
|
+ AppStorage.setOrCreate('currentWidthBreakpoint', widthBp);
|
|
|
|
|
+
|
|
|
|
|
+ // 获取高度断点并更新全局状态
|
|
|
|
|
+ let heightBp = this.uiContext!.getWindowHeightBreakpoint();
|
|
|
|
|
+ AppStorage.setOrCreate('currentHeightBreakpoint', heightBp);
|
|
|
|
|
+ // 记录尺寸变化日志
|
|
|
|
|
+ // LogUtil.info('pura onWindowSizeChange currentHeightBreakpoint= '+heightBp);
|
|
|
|
|
+ // LogUtil.info( 'pura onWindowSizeChange currentWidthBreakpoint= '+widthBp);
|
|
|
|
|
+ AppStorage.setOrCreate('windowWidth', windowSize.width);
|
|
|
|
|
+ AppStorage.setOrCreate('windowHeight', windowSize.height);
|
|
|
|
|
+ if (windowSize.width > windowSize.height) {
|
|
|
|
|
+ AppStorage.setOrCreate('isLandscape', true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('isLandscape', false);
|
|
|
|
|
+ }
|
|
|
|
|
+ // LogUtil.info('hicar onWindowSizeChange width= '+windowSize.width);
|
|
|
|
|
+ // LogUtil.info( 'hicar onWindowSizeChange height= '+windowSize.height);
|
|
|
|
|
+
|
|
|
|
|
+ };
|
|
|
|
|
+ onAvoidAreaChange = (data: window.AvoidAreaOptions) => {
|
|
|
|
|
+ if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
|
|
|
|
|
+ let topRectHeight = px2vp(data.area.topRect.height);
|
|
|
|
|
+ AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
+ } else if (data.type === window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
|
|
|
|
|
+ let bottomRectHeight = px2vp(data.area.bottomRect.height);
|
|
|
|
|
+ AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- onAvoidAreaChange = (data: window.AvoidAreaOptions) => {
|
|
|
|
|
- if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {
|
|
|
|
|
- let topRectHeight = px2vp(data.area.topRect.height);
|
|
|
|
|
- AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
- } else if (data.type === window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {
|
|
|
|
|
- let bottomRectHeight = px2vp(data.area.bottomRect.height);
|
|
|
|
|
- AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
|
|
|
|
+ AppUtil.init(this.context);
|
|
|
|
|
+ AppStorage.setOrCreate('context', this.context);
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onCreate');
|
|
|
|
|
|
|
|
- async onCreate(want:Want, launchParam:AbilityConstant.LaunchParam) {
|
|
|
|
|
- AppUtil.init(this.context);
|
|
|
|
|
- AppStorage.setOrCreate('context', this.context);
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onCreate');
|
|
|
|
|
|
|
+ // 注册卡片call事件监听器
|
|
|
|
|
+ this.registerWidgetCallListeners();
|
|
|
|
|
|
|
|
- // 注册卡片call事件监听器
|
|
|
|
|
- this.registerWidgetCallListeners();
|
|
|
|
|
|
|
+ // 异步初始化统一播放器服务,避免阻塞生命周期
|
|
|
|
|
+ this.initializePlayerServiceAsync();
|
|
|
|
|
|
|
|
- // 异步初始化统一播放器服务,避免阻塞生命周期
|
|
|
|
|
- this.initializePlayerServiceAsync();
|
|
|
|
|
|
|
+ // 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
+ this.handleWantAsync(want);
|
|
|
|
|
|
|
|
- // 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
- this.handleWantAsync(want);
|
|
|
|
|
|
|
+ this.handleWeChatCallIfNeed(want)
|
|
|
|
|
|
|
|
- this.handleWeChatCallIfNeed(want)
|
|
|
|
|
|
|
+ this.getHiCarStatus()
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- this.getHiCarStatus()
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ async onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `onNewWant, want=${JSON.stringify(want)}`);
|
|
|
|
|
+ super.onNewWant(want, launchParam);
|
|
|
|
|
|
|
|
- async onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `onNewWant, want=${JSON.stringify(want)}`);
|
|
|
|
|
- super.onNewWant(want, launchParam);
|
|
|
|
|
|
|
+ // 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
+ this.handleWantAsync(want);
|
|
|
|
|
+ this.handleWeChatCallIfNeed(want)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
- this.handleWantAsync(want);
|
|
|
|
|
- this.handleWeChatCallIfNeed(want)
|
|
|
|
|
|
|
+ //处理其他app点击其他应用打开播放器播放视频或者音频
|
|
|
|
|
+ loadDoWant(want: Want) {
|
|
|
|
|
+ // console.info('onecold KnockController 碰一碰 want ='+JSON.stringify(want));
|
|
|
|
|
+ let uri = want.uri;
|
|
|
|
|
+ if (uri == null || uri == undefined || StrUtil.isEmpty(uri)) {
|
|
|
|
|
+ console.info('uri is invalid');
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `onCreate or onNewWant, uri=${uri}`);
|
|
|
|
|
|
|
|
- private handleWeChatCallIfNeed(want: Want) {
|
|
|
|
|
- WXApi.handleWant(want, WXEventHandler)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ this.doSendEmit(uri)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- //处理其他app点击其他应用打开播放器播放视频或者音频
|
|
|
|
|
- loadDoWant(want: Want){
|
|
|
|
|
- // console.info('onecold KnockController 碰一碰 want ='+JSON.stringify(want));
|
|
|
|
|
- let uri = want.uri;
|
|
|
|
|
- if (uri == null || uri == undefined|| StrUtil.isEmpty(uri)) {
|
|
|
|
|
- console.info('uri is invalid');
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ //广播通知打开播放器播放视频或者音频
|
|
|
|
|
+ doSendEmit(uri: string) {
|
|
|
|
|
+ setTimeout(async () => {
|
|
|
|
|
+ let eventData: emitter.EventData = {
|
|
|
|
|
+ data: {
|
|
|
|
|
+ message: uri
|
|
|
}
|
|
}
|
|
|
- hilog.info(0x0000, 'Heanup2', `onCreate or onNewWant, uri=${uri}`);
|
|
|
|
|
-
|
|
|
|
|
- this.doSendEmit(uri)
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+ if (Utility.isMediaByExtension(uri)) {
|
|
|
|
|
+ emitter.emit({ eventId: 2 }, eventData); // 发送音频打开广播事件
|
|
|
|
|
+ } else {
|
|
|
|
|
+ emitter.emit({ eventId: 1 }, eventData); // 发送视频打开广播事件
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 300)
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 改造 handleParam 为异步函数,让其返回 Promise
|
|
|
|
|
+ async handleParam(want: Want) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 通过 await 等待异步操作完成
|
|
|
|
|
+ const data = await systemShare.getSharedData(want);
|
|
|
|
|
+ const records = data.getRecords();
|
|
|
|
|
+ let uri = want.uri;
|
|
|
|
|
+ for (const record of records) {
|
|
|
|
|
+ if (record.uri) {
|
|
|
|
|
+ uri = record.uri;
|
|
|
|
|
+ this.doSendEmit(uri)
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ const businessError = error as BusinessError;
|
|
|
|
|
+ console.error(`Failed: Code ${businessError.code}, ${businessError.message}`);
|
|
|
}
|
|
}
|
|
|
- //广播通知打开播放器播放视频或者音频
|
|
|
|
|
- doSendEmit(uri:string){
|
|
|
|
|
- setTimeout(async ()=>{
|
|
|
|
|
- let eventData: emitter.EventData = {
|
|
|
|
|
- data: {
|
|
|
|
|
- message: uri
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
- if(Utility.isMediaByExtension(uri)){
|
|
|
|
|
- emitter.emit({ eventId: 2 }, eventData); // 发送音频打开广播事件
|
|
|
|
|
- }else{
|
|
|
|
|
- emitter.emit({ eventId: 1 }, eventData); // 发送视频打开广播事件
|
|
|
|
|
- }
|
|
|
|
|
- },300)
|
|
|
|
|
-
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 华为分享拉起接收 处理分享数据
|
|
|
|
|
+
|
|
|
|
|
+ onDestroy() {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onDestroy');
|
|
|
|
|
+
|
|
|
|
|
+ // 关键修复:在APP销毁时保存播放器状态
|
|
|
|
|
+ try {
|
|
|
|
|
+ const unifiedPlayerService = UnifiedPlayerService.getInstance();
|
|
|
|
|
+ if (unifiedPlayerService) {
|
|
|
|
|
+ // 确保在APP被杀掉时保存当前播放状态
|
|
|
|
|
+ unifiedPlayerService.release();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', 'UnifiedPlayerService released and state saved on app destroy');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `Failed to release UnifiedPlayerService: ${error}`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 华为分享拉起接收 处理分享数据
|
|
|
|
|
- // 1. 改造 handleParam 为异步函数,让其返回 Promise
|
|
|
|
|
- async handleParam(want: Want) {
|
|
|
|
|
- try {
|
|
|
|
|
- // 通过 await 等待异步操作完成
|
|
|
|
|
- const data = await systemShare.getSharedData(want);
|
|
|
|
|
- const records = data.getRecords();
|
|
|
|
|
- let uri = want.uri;
|
|
|
|
|
- for (const record of records) {
|
|
|
|
|
- if (record.uri) {
|
|
|
|
|
- uri = record.uri;
|
|
|
|
|
- this.doSendEmit(uri)
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- const businessError = error as BusinessError;
|
|
|
|
|
- console.error(`Failed: Code ${businessError.code}, ${businessError.message}`);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 清理所有Form ID(应用卸载时)
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.clearAllFormIds();
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `Failed to clear form IDs: ${error}`);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- onDestroy() {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onDestroy');
|
|
|
|
|
-
|
|
|
|
|
- // 关键修复:在APP销毁时保存播放器状态
|
|
|
|
|
- try {
|
|
|
|
|
- const unifiedPlayerService = UnifiedPlayerService.getInstance();
|
|
|
|
|
- if (unifiedPlayerService) {
|
|
|
|
|
- // 确保在APP被杀掉时保存当前播放状态
|
|
|
|
|
- unifiedPlayerService.release();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', 'UnifiedPlayerService released and state saved on app destroy');
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `Failed to release UnifiedPlayerService: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 清理所有Form ID(应用卸载时)
|
|
|
|
|
- try {
|
|
|
|
|
- this.clearAllFormIds();
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `Failed to clear form IDs: ${error}`);
|
|
|
|
|
|
|
+ // 注销卡片call事件监听器
|
|
|
|
|
+ this.unregisterWidgetCallListeners();
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
|
|
|
|
+ if (this.awareness) {
|
|
|
|
|
+ let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.CAR_HOP];
|
|
|
|
|
+ // 出行连接状态回调函数
|
|
|
|
|
+ const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
|
|
|
|
|
+ hilog.info(0x0000, 'Received smart mobility info: ', JSON.stringify(info));
|
|
|
|
|
+ };
|
|
|
|
|
+ // 解注册智慧出行连接状态的监听 示例2
|
|
|
|
|
+ this.awareness.off('smartMobilityStatus', types, callBack);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onWindowStageCreate(windowStage: window.WindowStage) {
|
|
|
|
|
+ // Main window is created, set main page for this ability
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageCreate');
|
|
|
|
|
+
|
|
|
|
|
+ // 使用自定义崩溃处理器替代 SpiderMan.init()
|
|
|
|
|
+ // SpiderMan.init();
|
|
|
|
|
+ CustomCrashHandler.init();
|
|
|
|
|
+
|
|
|
|
|
+ AppUtil.init(this.context);
|
|
|
|
|
+
|
|
|
|
|
+ //1.获取应用主窗口。
|
|
|
|
|
+ let windowClass: window.Window | null = null;
|
|
|
|
|
+ windowStage.getMainWindow((err: BusinessError, data) => {
|
|
|
|
|
+
|
|
|
|
|
+ windowClass = data;
|
|
|
|
|
+ // LogUtil.info( 'getMainWindow = ');
|
|
|
|
|
+ GlobalContext.getContext().setObject('windowClass', data); // 使用GlobalContext替代globalThis
|
|
|
|
|
+
|
|
|
|
|
+ let curDisplay = display.getDisplayByIdSync(windowClass.getWindowProperties().displayId);
|
|
|
|
|
+ console.info('twocold curDisplay = ' + curDisplay.name);
|
|
|
|
|
+ if (curDisplay.name == 'HiCar' || curDisplay.name == 'SuperLauncher') {
|
|
|
|
|
+ AppStorage.setOrCreate('curDisplayIsHiCar', true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('curDisplayIsHiCar', false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ windowClass.setWindowLayoutFullScreen(true).then(() => {
|
|
|
|
|
+ console.info('Succeeded in setting the window layout to full-screen mode.');
|
|
|
|
|
+ }).catch((e: BusinessError) => {
|
|
|
|
|
+ console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(e));
|
|
|
|
|
+ })
|
|
|
|
|
+ // let avoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
|
|
|
|
|
+ // let topRectHeight = px2vp(avoidArea.topRect.height);
|
|
|
|
|
+ // AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
+
|
|
|
|
|
+ let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
|
|
|
|
|
+ let avoidArea = windowClass.getWindowAvoidArea(type);
|
|
|
|
|
+ let bottomRectHeight = px2vp(avoidArea.bottomRect.height); // 获取到导航条区域的高度
|
|
|
|
|
+ AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
|
|
|
|
|
+
|
|
|
|
|
+ type = window.AvoidAreaType.TYPE_SYSTEM; // 以状态栏避让为例
|
|
|
|
|
+ avoidArea = windowClass.getWindowAvoidArea(type);
|
|
|
|
|
+ let topRectHeight = px2vp(avoidArea.topRect.height) // 获取状态栏区域高度
|
|
|
|
|
+ AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
+
|
|
|
|
|
+ LogUtil.info('onecold topRectHeight = ' + topRectHeight);
|
|
|
|
|
+ windowClass.on('avoidAreaChange', this.onAvoidAreaChange)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ AppStorage.setOrCreate('windowStage', windowStage);
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageCreate');
|
|
|
|
|
+
|
|
|
|
|
+ windowStage.loadContent('pages/SplashIndex', (err, data) => {
|
|
|
|
|
+ if (err.code) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ //一多断点开发
|
|
|
|
|
+ windowStage.getMainWindow().then((data: window.Window) => {
|
|
|
|
|
+ this.uiContext = data.getUIContext();
|
|
|
|
|
+ let widthBp = this.uiContext.getWindowWidthBreakpoint();
|
|
|
|
|
+ let heightBp = this.uiContext.getWindowHeightBreakpoint();
|
|
|
|
|
+ AppStorage.setOrCreate('currentWidthBreakpoint', widthBp);
|
|
|
|
|
+ AppStorage.setOrCreate('currentHeightBreakpoint', heightBp);
|
|
|
|
|
+ LogUtil.info('getMainWindow currentHeightBreakpoint= ' + heightBp);
|
|
|
|
|
+ LogUtil.info('getMainWindow currentWidthBreakpoint= ' + widthBp);
|
|
|
|
|
+ data.on('windowSizeChange', this.onWindowSizeChange);
|
|
|
|
|
+
|
|
|
|
|
+ AppStorage.setOrCreate('windowWidth', data.getWindowProperties().windowRect.width);
|
|
|
|
|
+ AppStorage.setOrCreate('windowHeight', data.getWindowProperties().windowRect.height);
|
|
|
|
|
+ if (data.getWindowProperties().windowRect.width > data.getWindowProperties().windowRect.height) {
|
|
|
|
|
+ AppStorage.setOrCreate('isLandscape', true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('isLandscape', false);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 注销卡片call事件监听器
|
|
|
|
|
- this.unregisterWidgetCallListeners();
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
|
|
|
|
- if(this.awareness){
|
|
|
|
|
- let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.CAR_HOP];
|
|
|
|
|
- // 出行连接状态回调函数
|
|
|
|
|
- const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
|
|
|
|
|
- hilog.info(0x0000, 'Received smart mobility info: ', JSON.stringify(info));
|
|
|
|
|
- };
|
|
|
|
|
- // 解注册智慧出行连接状态的监听 示例2
|
|
|
|
|
- this.awareness.off('smartMobilityStatus', types, callBack);
|
|
|
|
|
|
|
+ // LogUtil.info('hicar getMainWindow width= '+data.getWindowProperties().windowRect.width);
|
|
|
|
|
+ // LogUtil.info( 'hicar getMainWindow height= '+data.getWindowProperties().windowRect.height);
|
|
|
|
|
+ }).catch((err: BusinessError) => {
|
|
|
|
|
+ console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onWindowStageDestroy() {
|
|
|
|
|
+ // Main window is destroyed, release UI related resources
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageDestroy');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onForeground() {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ onBackground() {
|
|
|
|
|
+ // Ability has back to background
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground start');
|
|
|
|
|
+
|
|
|
|
|
+ // 异步处理后台逻辑,避免阻塞生命周期
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.handleBackgroundAsync();
|
|
|
|
|
+ }, 10);
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground end');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getHiCarStatus() {
|
|
|
|
|
+ if (this.awareness) {
|
|
|
|
|
+ // this.awareness = smartMobilityCommon.getSmartMobilityAwareness();
|
|
|
|
|
+
|
|
|
|
|
+ // 业务类型
|
|
|
|
|
+ let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.HICAR];
|
|
|
|
|
+ // 获取出行业务连接状态
|
|
|
|
|
+ let info = this.awareness.getSmartMobilityStatus(types[0]);
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'getHiCarStatus info: ', JSON.stringify(info));
|
|
|
|
|
+ if (info && info.status == 1) {
|
|
|
|
|
+ AppStorage.setOrCreate('isHiCarStatus', true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 出行连接状态回调函数
|
|
|
|
|
+ const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
|
|
|
|
|
+ hilog.info(0x0000, 'getHiCarStatus Received smart mobility info: ', JSON.stringify(info));
|
|
|
|
|
+ if (info && info.status == 1) {
|
|
|
|
|
+ AppStorage.setOrCreate('isHiCarStatus', true);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
}
|
|
}
|
|
|
|
|
+ this.sendChangeEvent()
|
|
|
|
|
+ };
|
|
|
|
|
+ // 注册智慧出行连接状态的监听
|
|
|
|
|
+ this.awareness.on('smartMobilityStatus', types, callBack);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
- onWindowStageCreate(windowStage: window.WindowStage) {
|
|
|
|
|
- // Main window is created, set main page for this ability
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageCreate');
|
|
|
|
|
-
|
|
|
|
|
- // 使用自定义崩溃处理器替代 SpiderMan.init()
|
|
|
|
|
- // SpiderMan.init();
|
|
|
|
|
- CustomCrashHandler.init();
|
|
|
|
|
-
|
|
|
|
|
- AppUtil.init(this.context);
|
|
|
|
|
-
|
|
|
|
|
- //1.获取应用主窗口。
|
|
|
|
|
- let windowClass: window.Window | null = null;
|
|
|
|
|
- windowStage.getMainWindow((err: BusinessError, data) => {
|
|
|
|
|
-
|
|
|
|
|
- windowClass = data;
|
|
|
|
|
- // LogUtil.info( 'getMainWindow = ');
|
|
|
|
|
- GlobalContext.getContext().setObject('windowClass', data); // 使用GlobalContext替代globalThis
|
|
|
|
|
-
|
|
|
|
|
- let curDisplay = display.getDisplayByIdSync(windowClass.getWindowProperties().displayId);
|
|
|
|
|
- console.info('twocold curDisplay = '+curDisplay.name);
|
|
|
|
|
- if(curDisplay.name =='HiCar'||curDisplay.name =='SuperLauncher'){
|
|
|
|
|
- AppStorage.setOrCreate('curDisplayIsHiCar', true);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('curDisplayIsHiCar', false);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- windowClass.setWindowLayoutFullScreen(true).then(() => {
|
|
|
|
|
- console.info('Succeeded in setting the window layout to full-screen mode.');
|
|
|
|
|
- }).catch((e: BusinessError) => {
|
|
|
|
|
- console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(e));
|
|
|
|
|
- })
|
|
|
|
|
- // let avoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
|
|
|
|
|
- // let topRectHeight = px2vp(avoidArea.topRect.height);
|
|
|
|
|
- // AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
-
|
|
|
|
|
- let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
|
|
|
|
|
- let avoidArea = windowClass.getWindowAvoidArea(type);
|
|
|
|
|
- let bottomRectHeight = px2vp(avoidArea.bottomRect.height); // 获取到导航条区域的高度
|
|
|
|
|
- AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight);
|
|
|
|
|
-
|
|
|
|
|
- type = window.AvoidAreaType.TYPE_SYSTEM; // 以状态栏避让为例
|
|
|
|
|
- avoidArea = windowClass.getWindowAvoidArea(type);
|
|
|
|
|
- let topRectHeight = px2vp(avoidArea.topRect.height) // 获取状态栏区域高度
|
|
|
|
|
- AppStorage.setOrCreate('topRectHeight', topRectHeight);
|
|
|
|
|
-
|
|
|
|
|
- LogUtil.info('onecold topRectHeight = '+topRectHeight);
|
|
|
|
|
- windowClass.on('avoidAreaChange', this.onAvoidAreaChange)
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- AppStorage.setOrCreate('windowStage',windowStage);
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageCreate');
|
|
|
|
|
-
|
|
|
|
|
- windowStage.loadContent('pages/SplashIndex', (err, data) => {
|
|
|
|
|
- if (err.code) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- //一多断点开发
|
|
|
|
|
- windowStage.getMainWindow().then((data: window.Window) => {
|
|
|
|
|
- this.uiContext = data.getUIContext();
|
|
|
|
|
- let widthBp = this.uiContext.getWindowWidthBreakpoint();
|
|
|
|
|
- let heightBp = this.uiContext.getWindowHeightBreakpoint();
|
|
|
|
|
- AppStorage.setOrCreate('currentWidthBreakpoint', widthBp);
|
|
|
|
|
- AppStorage.setOrCreate('currentHeightBreakpoint', heightBp);
|
|
|
|
|
- LogUtil.info( 'getMainWindow currentHeightBreakpoint= '+heightBp);
|
|
|
|
|
- LogUtil.info( 'getMainWindow currentWidthBreakpoint= '+widthBp);
|
|
|
|
|
- data.on('windowSizeChange', this.onWindowSizeChange);
|
|
|
|
|
-
|
|
|
|
|
- AppStorage.setOrCreate('windowWidth', data.getWindowProperties().windowRect.width);
|
|
|
|
|
- AppStorage.setOrCreate('windowHeight', data.getWindowProperties().windowRect.height);
|
|
|
|
|
- if(data.getWindowProperties().windowRect.width > data.getWindowProperties().windowRect.height){
|
|
|
|
|
- AppStorage.setOrCreate('isLandscape', true);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('isLandscape', false);
|
|
|
|
|
- }
|
|
|
|
|
- // LogUtil.info('hicar getMainWindow width= '+data.getWindowProperties().windowRect.width);
|
|
|
|
|
- // LogUtil.info( 'hicar getMainWindow height= '+data.getWindowProperties().windowRect.height);
|
|
|
|
|
- }).catch((err: BusinessError) => {
|
|
|
|
|
- console.error(`Failed to obtain the main window. Cause code: ${err.code}, message: ${err.message}`);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- onWindowStageDestroy() {
|
|
|
|
|
- // Main window is destroyed, release UI related resources
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onWindowStageDestroy');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ //发送广播通知更新UI
|
|
|
|
|
+ sendChangeEvent() {
|
|
|
|
|
+ const eventData: emitter.EventData = {};
|
|
|
|
|
+ emitter.emit({ eventId: 333 }, eventData); // 发送广播通知更新doSwipBack
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- onForeground() {
|
|
|
|
|
|
|
+ private handleWeChatCallIfNeed(want: Want) {
|
|
|
|
|
+ WXApi.handleWant(want, WXEventHandler)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- onBackground() {
|
|
|
|
|
- // Ability has back to background
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground start');
|
|
|
|
|
-
|
|
|
|
|
- // 异步处理后台逻辑,避免阻塞生命周期
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- this.handleBackgroundAsync();
|
|
|
|
|
- }, 10);
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '%{public}s', 'Ability onBackground end');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 注册卡片call事件监听器(增强版本:服务就绪检查)
|
|
|
|
|
+ */
|
|
|
|
|
+ private registerWidgetCallListeners(): void {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 监听播放/暂停事件
|
|
|
|
|
+ this.callee.on('playPause', (data: rpc.MessageSequence) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 Widget call: playPause received`);
|
|
|
|
|
|
|
|
|
|
+ // 异步发送播放/暂停事件到主应用(包含服务就绪检查)
|
|
|
|
|
+ this.sendWidgetControlEvent('PLAY_PAUSE', params).catch((error: Error) => {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ playPause async error: ${error}`);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- getHiCarStatus(){
|
|
|
|
|
- if(this.awareness){
|
|
|
|
|
- // this.awareness = smartMobilityCommon.getSmartMobilityAwareness();
|
|
|
|
|
-
|
|
|
|
|
- // 业务类型
|
|
|
|
|
- let types: smartMobilityCommon.SmartMobilityType[] = [smartMobilityCommon.SmartMobilityType.HICAR];
|
|
|
|
|
- // 获取出行业务连接状态
|
|
|
|
|
- let info = this.awareness.getSmartMobilityStatus(types[0]);
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'getHiCarStatus info: ', JSON.stringify(info));
|
|
|
|
|
- if(info&&info.status==1){
|
|
|
|
|
- AppStorage.setOrCreate('isHiCarStatus', true);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 出行连接状态回调函数
|
|
|
|
|
- const callBack = (info: smartMobilityCommon.SmartMobilityInfo) => {
|
|
|
|
|
- hilog.info(0x0000, 'getHiCarStatus Received smart mobility info: ', JSON.stringify(info));
|
|
|
|
|
- if(info&&info.status==1){
|
|
|
|
|
- AppStorage.setOrCreate('isHiCarStatus', true);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
|
|
- }
|
|
|
|
|
- this.sendChangeEvent()
|
|
|
|
|
- };
|
|
|
|
|
- // 注册智慧出行连接状态的监听
|
|
|
|
|
- this.awareness.on('smartMobilityStatus', types, callBack);
|
|
|
|
|
- }else{
|
|
|
|
|
- AppStorage.setOrCreate('isHiCarStatus', false);
|
|
|
|
|
|
|
+ return new MyParcelable(1, 'playPause_success');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ playPause handler error: ${error}`);
|
|
|
|
|
+ return new MyParcelable(-1, 'playPause_error');
|
|
|
}
|
|
}
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
|
|
+ // 监听下一首事件
|
|
|
|
|
+ this.callee.on('nextSong', (data: rpc.MessageSequence) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 Widget call: nextSong received`);
|
|
|
|
|
+ const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `Widget nextSong params: ${JSON.stringify(params)}`);
|
|
|
|
|
|
|
|
|
|
+ // 异步发送下一首事件到主应用(包含服务就绪检查)
|
|
|
|
|
+ this.sendWidgetControlEvent('NEXT_SONG', params).catch((error: Error) => {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ nextSong async error: ${error}`);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //发送广播通知更新UI
|
|
|
|
|
- sendChangeEvent() {
|
|
|
|
|
- const eventData: emitter.EventData = {};
|
|
|
|
|
- emitter.emit({ eventId: 333 }, eventData); // 发送广播通知更新doSwipBack
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 注册卡片call事件监听器(增强版本:服务就绪检查)
|
|
|
|
|
- */
|
|
|
|
|
- private registerWidgetCallListeners(): void {
|
|
|
|
|
- try {
|
|
|
|
|
- // 监听播放/暂停事件
|
|
|
|
|
- this.callee.on('playPause', (data: rpc.MessageSequence) => {
|
|
|
|
|
- try {
|
|
|
|
|
- const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🎵 Widget call: playPause received`);
|
|
|
|
|
-
|
|
|
|
|
- // 异步发送播放/暂停事件到主应用(包含服务就绪检查)
|
|
|
|
|
- this.sendWidgetControlEvent('PLAY_PAUSE', params).catch((error: Error) => {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ playPause async error: ${error}`);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- return new MyParcelable(1, 'playPause_success');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ playPause handler error: ${error}`);
|
|
|
|
|
- return new MyParcelable(-1, 'playPause_error');
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 监听下一首事件
|
|
|
|
|
- this.callee.on('nextSong', (data: rpc.MessageSequence) => {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🎵 Widget call: nextSong received`);
|
|
|
|
|
- const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `Widget nextSong params: ${JSON.stringify(params)}`);
|
|
|
|
|
-
|
|
|
|
|
- // 异步发送下一首事件到主应用(包含服务就绪检查)
|
|
|
|
|
- this.sendWidgetControlEvent('NEXT_SONG', params).catch((error: Error) => {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ nextSong async error: ${error}`);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- return new MyParcelable(2, 'nextSong_success');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ nextSong handler error: ${error}`);
|
|
|
|
|
- return new MyParcelable(-2, 'nextSong_error');
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 监听上一首事件
|
|
|
|
|
- this.callee.on('prevSong', (data: rpc.MessageSequence) => {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🎵 Widget call: prevSong received`);
|
|
|
|
|
- const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `Widget prevSong params: ${JSON.stringify(params)}`);
|
|
|
|
|
-
|
|
|
|
|
- // 异步发送上一首事件到主应用(包含服务就绪检查)
|
|
|
|
|
- this.sendWidgetControlEvent('PREV_SONG', params).catch((error: Error) => {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ prevSong async error: ${error}`);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- return new MyParcelable(3, 'prevSong_success');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ prevSong handler error: ${error}`);
|
|
|
|
|
- return new MyParcelable(-3, 'prevSong_error');
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 监听打开应用事件
|
|
|
|
|
- this.callee.on('openApp', (data: rpc.MessageSequence) => {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🎵 Widget call: openApp received`);
|
|
|
|
|
- const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `Widget openApp params: ${JSON.stringify(params)}`);
|
|
|
|
|
-
|
|
|
|
|
- // 异步发送打开应用事件到主应用
|
|
|
|
|
- this.sendWidgetControlEvent('OPEN_APP', params).catch((error: Error) => {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ openApp async error: ${error}`);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- return new MyParcelable(4, 'openApp_success');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ openApp handler error: ${error}`);
|
|
|
|
|
- return new MyParcelable(-4, 'openApp_error');
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- this.callee.on("toggleFavorite",(data:rpc.MessageSequence)=>{
|
|
|
|
|
- const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `toggleFavorite handler`);
|
|
|
|
|
- this.sendWidgetControlEvent('toggleFavorite', params).catch((error: Error) => {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ toggleFavorite async error: ${error}`);
|
|
|
|
|
- });
|
|
|
|
|
- return new MyParcelable(-5, 'toggleFavorite');
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🎵 Widget call listeners registered successfully (Enhanced)');
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ Failed to register widget call listeners: ${JSON.stringify(err as BusinessError)}`);
|
|
|
|
|
|
|
+ return new MyParcelable(2, 'nextSong_success');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ nextSong handler error: ${error}`);
|
|
|
|
|
+ return new MyParcelable(-2, 'nextSong_error');
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 注销卡片call事件监听器
|
|
|
|
|
- */
|
|
|
|
|
- private unregisterWidgetCallListeners(): void {
|
|
|
|
|
|
|
+ // 监听上一首事件
|
|
|
|
|
+ this.callee.on('prevSong', (data: rpc.MessageSequence) => {
|
|
|
try {
|
|
try {
|
|
|
- this.callee.off('playPause');
|
|
|
|
|
- this.callee.off('nextSong');
|
|
|
|
|
- this.callee.off('prevSong');
|
|
|
|
|
- this.callee.off('toggleFavorite');
|
|
|
|
|
- // this.callee.off('openApp');
|
|
|
|
|
- // this.callee.off('playByAction');
|
|
|
|
|
- // this.callee.off('collectAction');
|
|
|
|
|
- // this.callee.off('requestUpdatePlayCard');
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', 'Widget call listeners unregistered successfully');
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `Failed to unregister widget call listeners: ${JSON.stringify(err as BusinessError)}`);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 Widget call: prevSong received`);
|
|
|
|
|
+ const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `Widget prevSong params: ${JSON.stringify(params)}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 异步发送上一首事件到主应用(包含服务就绪检查)
|
|
|
|
|
+ this.sendWidgetControlEvent('PREV_SONG', params).catch((error: Error) => {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ prevSong async error: ${error}`);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
|
|
+ return new MyParcelable(3, 'prevSong_success');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ prevSong handler error: ${error}`);
|
|
|
|
|
+ return new MyParcelable(-3, 'prevSong_error');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 发送卡片控制事件到主应用(增强版本,确保服务已初始化)
|
|
|
|
|
- */
|
|
|
|
|
- private async sendWidgetControlEvent(command: string, params: Record<string, Object>): Promise<void> {
|
|
|
|
|
|
|
+ // 监听打开应用事件
|
|
|
|
|
+ this.callee.on('openApp', (data: rpc.MessageSequence) => {
|
|
|
try {
|
|
try {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 Widget call: openApp received`);
|
|
|
|
|
+ const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `Widget openApp params: ${JSON.stringify(params)}`);
|
|
|
|
|
|
|
|
- // 获取UnifiedPlayerService实例
|
|
|
|
|
- const unifiedService = UnifiedPlayerService.getInstance();
|
|
|
|
|
-
|
|
|
|
|
- // 确保服务已经初始化
|
|
|
|
|
- if (!unifiedService) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', '❌ UnifiedPlayerService 未初始化');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 获取详细的服务就绪状态信息
|
|
|
|
|
- const readinessInfo = unifiedService.getServiceReadinessInfo();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🔍 Service readiness: ${JSON.stringify(readinessInfo.details)}`);
|
|
|
|
|
-
|
|
|
|
|
- // 智能等待服务完全就绪(多级检查)
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 检查服务就绪状态...');
|
|
|
|
|
- let ready = await this.waitForServiceReady(unifiedService);
|
|
|
|
|
-
|
|
|
|
|
- if (ready) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService 已就绪');
|
|
|
|
|
- } else {
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', '⚠️ UnifiedPlayerService 未完全就绪,尝试执行基础操作');
|
|
|
|
|
-
|
|
|
|
|
- // 检查是否至少可以进行基础操作
|
|
|
|
|
- if (!unifiedService.isAllServicesReady()) {
|
|
|
|
|
- const finalReadinessInfo = unifiedService.getServiceReadinessInfo();
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 基础服务未就绪,无法执行操作: ${JSON.stringify(finalReadinessInfo.details)}`);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查初始化状态
|
|
|
|
|
- const currentState = unifiedService.getCurrentState();
|
|
|
|
|
- const playlist = unifiedService.getPlaylist();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🎵 Widget command - Service state: isPlaying=${currentState.isPlaying}, currentIndex=${currentState.currentIndex}, playlistSize=${playlist.length}`);
|
|
|
|
|
-
|
|
|
|
|
- // 对于播放控制操作,检查是否有可播放内容
|
|
|
|
|
- if ((command === 'PLAY_PAUSE' || command === 'NEXT_SONG' || command === 'PREV_SONG') && playlist.length === 0) {
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', '⚠️ 播放列表为空,尝试强制数据恢复');
|
|
|
|
|
-
|
|
|
|
|
- // 强制触发数据恢复
|
|
|
|
|
- await this.forceDataRestoration(unifiedService);
|
|
|
|
|
-
|
|
|
|
|
- // 重新检查播放列表
|
|
|
|
|
- const updatedPlaylist = unifiedService.getPlaylist();
|
|
|
|
|
- if (updatedPlaylist.length === 0) {
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', '⚠️ 强制数据恢复后播放列表仍为空,无法执行播放控制操作');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- 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();
|
|
|
|
|
-
|
|
|
|
|
- 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', '⚠️ 使用向后兼容模式(基于服务状态)');
|
|
|
|
|
- if (latestState.isPlaying) {
|
|
|
|
|
- await unifiedService.pause();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 兼容模式:暂停播放');
|
|
|
|
|
- } else {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 兼容模式:开始播放');
|
|
|
|
|
- await unifiedService.startPlayOrResumePlay();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 兼容模式:开始播放');
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'NEXT_SONG':
|
|
|
|
|
- await unifiedService.playNext();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ Widget command: Next song');
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'PREV_SONG':
|
|
|
|
|
- await unifiedService.playPrevious();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ Widget command: Previous song');
|
|
|
|
|
- break;
|
|
|
|
|
-
|
|
|
|
|
- case 'OPEN_APP':
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ Widget command: Open app (handled by UI)');
|
|
|
|
|
- break;
|
|
|
|
|
- case 'OPEN_APP':
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ Widget command: Open app (handled by UI)');
|
|
|
|
|
- break;
|
|
|
|
|
- case "toggleFavorite":
|
|
|
|
|
- await unifiedService.toggleFavorite();
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', `❓ Unknown widget command: ${command}`);
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 操作完成后,广播最新状态给主应用UI和桌面卡片
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '📡 桌面卡片操作后广播状态更新');
|
|
|
|
|
-
|
|
|
|
|
- // 同时触发UnifiedPlayerService的状态广播,确保所有监听器都能收到更新
|
|
|
|
|
- try {
|
|
|
|
|
- unifiedService.broadcastCurrentState();
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 触发服务状态广播失败: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
- }, 100); // 短延迟,确保操作完全完成
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `✅ Widget control command processed: ${command}`);
|
|
|
|
|
|
|
+ // 异步发送打开应用事件到主应用
|
|
|
|
|
+ this.sendWidgetControlEvent('OPEN_APP', params).catch((error: Error) => {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ openApp async error: ${error}`);
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
|
|
+ return new MyParcelable(4, 'openApp_success');
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ Failed to process widget control command: ${error}`);
|
|
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ openApp handler error: ${error}`);
|
|
|
|
|
+ return new MyParcelable(-4, 'openApp_error');
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ this.callee.on("toggleFavorite", (data: rpc.MessageSequence) => {
|
|
|
|
|
+ const params: Record<string, Object> = JSON.parse(data.readString()) as Record<string, Object>;
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `toggleFavorite handler`);
|
|
|
|
|
+ this.sendWidgetControlEvent('toggleFavorite', params).catch((error: Error) => {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ toggleFavorite async error: ${error}`);
|
|
|
|
|
+ });
|
|
|
|
|
+ return new MyParcelable(-5, 'toggleFavorite');
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 强制数据恢复(用于桌面卡片冷启动场景)
|
|
|
|
|
- */
|
|
|
|
|
- private async forceDataRestoration(unifiedService: UnifiedPlayerService): Promise<void> {
|
|
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '🎵 Widget call listeners registered successfully (Enhanced)');
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2',
|
|
|
|
|
+ `❌ Failed to register widget call listeners: ${JSON.stringify(err as BusinessError)}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 注销卡片call事件监听器
|
|
|
|
|
+ */
|
|
|
|
|
+ private unregisterWidgetCallListeners(): void {
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.callee.off('playPause');
|
|
|
|
|
+ this.callee.off('nextSong');
|
|
|
|
|
+ this.callee.off('prevSong');
|
|
|
|
|
+ this.callee.off('toggleFavorite');
|
|
|
|
|
+ // this.callee.off('openApp');
|
|
|
|
|
+ // this.callee.off('playByAction');
|
|
|
|
|
+ // this.callee.off('collectAction');
|
|
|
|
|
+ // this.callee.off('requestUpdatePlayCard');
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', 'Widget call listeners unregistered successfully');
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2',
|
|
|
|
|
+ `Failed to unregister widget call listeners: ${JSON.stringify(err as BusinessError)}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送卡片控制事件到主应用(增强版本,确保服务已初始化)
|
|
|
|
|
+ */
|
|
|
|
|
+ private async sendWidgetControlEvent(command: string, params: Record<string, Object>): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+
|
|
|
|
|
+ // 获取UnifiedPlayerService实例
|
|
|
|
|
+ const unifiedService = UnifiedPlayerService.getInstance();
|
|
|
|
|
+
|
|
|
|
|
+ // 确保服务已经初始化
|
|
|
|
|
+ if (!unifiedService) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', '❌ UnifiedPlayerService 未初始化');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取详细的服务就绪状态信息
|
|
|
|
|
+ const readinessInfo = unifiedService.getServiceReadinessInfo();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🔍 Service readiness: ${JSON.stringify(readinessInfo.details)}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 智能等待服务完全就绪(多级检查)
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '🔄 检查服务就绪状态...');
|
|
|
|
|
+ let ready = await this.waitForServiceReady(unifiedService);
|
|
|
|
|
+
|
|
|
|
|
+ if (ready) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService 已就绪');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', '⚠️ UnifiedPlayerService 未完全就绪,尝试执行基础操作');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否至少可以进行基础操作
|
|
|
|
|
+ if (!unifiedService.isAllServicesReady()) {
|
|
|
|
|
+ const finalReadinessInfo = unifiedService.getServiceReadinessInfo();
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2',
|
|
|
|
|
+ `❌ 基础服务未就绪,无法执行操作: ${JSON.stringify(finalReadinessInfo.details)}`);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查初始化状态
|
|
|
|
|
+ const currentState = unifiedService.getCurrentState();
|
|
|
|
|
+ const playlist = unifiedService.getPlaylist();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2',
|
|
|
|
|
+ `🎵 Widget command - Service state: isPlaying=${currentState.isPlaying}, currentIndex=${currentState.currentIndex}, playlistSize=${playlist.length}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 对于播放控制操作,检查是否有可播放内容
|
|
|
|
|
+ if ((command === 'PLAY_PAUSE' || command === 'NEXT_SONG' || command === 'PREV_SONG') && playlist.length === 0) {
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', '⚠️ 播放列表为空,尝试强制数据恢复');
|
|
|
|
|
+
|
|
|
|
|
+ // 强制触发数据恢复
|
|
|
|
|
+ await this.forceDataRestoration(unifiedService);
|
|
|
|
|
+
|
|
|
|
|
+ // 重新检查播放列表
|
|
|
|
|
+ const updatedPlaylist = unifiedService.getPlaylist();
|
|
|
|
|
+ if (updatedPlaylist.length === 0) {
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', '⚠️ 强制数据恢复后播放列表仍为空,无法执行播放控制操作');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ 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();
|
|
|
|
|
+
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 卡片显示状态: isPlaying=${widgetIsPlaying} (有效: ${hasWidgetState})`);
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `🎵 服务内部状态: isPlaying=${latestState.isPlaying}`);
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+
|
|
|
|
|
+ case 'NEXT_SONG':
|
|
|
|
|
+ await unifiedService.playNext();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ Widget command: Next song');
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'PREV_SONG':
|
|
|
|
|
+ await unifiedService.playPrevious();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ Widget command: Previous song');
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 'OPEN_APP':
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ Widget command: Open app (handled by UI)');
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'OPEN_APP':
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ Widget command: Open app (handled by UI)');
|
|
|
|
|
+ break;
|
|
|
|
|
+ case "toggleFavorite":
|
|
|
|
|
+ await unifiedService.toggleFavorite();
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', `❓ Unknown widget command: ${command}`);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 操作完成后,广播最新状态给主应用UI和桌面卡片
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '📡 桌面卡片操作后广播状态更新');
|
|
|
|
|
+
|
|
|
|
|
+ // 同时触发UnifiedPlayerService的状态广播,确保所有监听器都能收到更新
|
|
|
try {
|
|
try {
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 开始强制数据恢复...');
|
|
|
|
|
-
|
|
|
|
|
- // 检查是否已经有数据恢复完成
|
|
|
|
|
- if (unifiedService.isDataRestorationCompleted()) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 数据已恢复,无需强制恢复');
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ unifiedService.broadcastCurrentState();
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ 触发服务状态广播失败: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 100); // 短延迟,确保操作完全完成
|
|
|
|
|
|
|
|
- // 调用UnifiedPlayerService的强制数据恢复方法
|
|
|
|
|
- const restored = await unifiedService.forceDataRestoration();
|
|
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `✅ Widget control command processed: ${command}`);
|
|
|
|
|
|
|
|
- if (restored) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 强制数据恢复成功');
|
|
|
|
|
- } else {
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', '⚠️ 强制数据恢复失败,尝试等待');
|
|
|
|
|
- // 如果强制恢复失败,再等待一段时间
|
|
|
|
|
- await unifiedService.waitForDataRestoration(2000);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ Failed to process widget control command: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 强制数据恢复(用于桌面卡片冷启动场景)
|
|
|
|
|
+ */
|
|
|
|
|
+ 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}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 智能等待服务就绪(增强版本)
|
|
|
|
|
+ */
|
|
|
|
|
+ private async waitForServiceReady(unifiedService: UnifiedPlayerService): Promise<boolean> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '🔄 开始等待UnifiedPlayerService完全就绪');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否是刚启动的应用(数据还没恢复)
|
|
|
|
|
+ const currentPlaylist = unifiedService.getPlaylist();
|
|
|
|
|
+ const isJustStarted = currentPlaylist.length === 0;
|
|
|
|
|
+ const isDataRestored = unifiedService.isDataRestorationCompleted();
|
|
|
|
|
+
|
|
|
|
|
+ if (isJustStarted || !isDataRestored) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2',
|
|
|
|
|
+ `🔄 检测到冷启动状态 - 播放列表为空: ${isJustStarted}, 数据未恢复: ${!isDataRestored}`);
|
|
|
|
|
+
|
|
|
|
|
+ // 对于冷启动,给予更长的等待时间,并强制检查数据恢复
|
|
|
|
|
+ const isReady = await unifiedService.waitForAllServicesReady(10000, true);
|
|
|
|
|
+
|
|
|
|
|
+ if (isReady) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService完全就绪(冷启动)');
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 额外等待一小段时间,确保播放列表数据完全加载
|
|
|
|
|
- await new Promise<void>(resolve => setTimeout(resolve, 300));
|
|
|
|
|
|
|
+ // 如果仍未就绪,尝试强制触发数据恢复
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', '⚠️ 冷启动等待超时,尝试强制数据恢复');
|
|
|
|
|
+ await this.forceDataRestoration(unifiedService);
|
|
|
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 强制数据恢复失败: ${error}`);
|
|
|
|
|
|
|
+ // 再次检查服务状态
|
|
|
|
|
+ const retryReady = await unifiedService.waitForAllServicesReady(3000, false);
|
|
|
|
|
+ if (retryReady) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ 强制恢复后服务就绪');
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 对于已经有数据的情况,使用正常的等待时间
|
|
|
|
|
+ const isReady = await unifiedService.waitForAllServicesReady(5000, true);
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 智能等待服务就绪(增强版本)
|
|
|
|
|
- */
|
|
|
|
|
- private async waitForServiceReady(unifiedService: UnifiedPlayerService): Promise<boolean> {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 开始等待UnifiedPlayerService完全就绪');
|
|
|
|
|
-
|
|
|
|
|
- // 检查是否是刚启动的应用(数据还没恢复)
|
|
|
|
|
- const currentPlaylist = unifiedService.getPlaylist();
|
|
|
|
|
- const isJustStarted = currentPlaylist.length === 0;
|
|
|
|
|
- const isDataRestored = unifiedService.isDataRestorationCompleted();
|
|
|
|
|
-
|
|
|
|
|
- if (isJustStarted || !isDataRestored) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `🔄 检测到冷启动状态 - 播放列表为空: ${isJustStarted}, 数据未恢复: ${!isDataRestored}`);
|
|
|
|
|
-
|
|
|
|
|
- // 对于冷启动,给予更长的等待时间,并强制检查数据恢复
|
|
|
|
|
- const isReady = await unifiedService.waitForAllServicesReady(10000, true);
|
|
|
|
|
-
|
|
|
|
|
- if (isReady) {
|
|
|
|
|
- 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 {
|
|
|
|
|
- // 对于已经有数据的情况,使用正常的等待时间
|
|
|
|
|
- const isReady = await unifiedService.waitForAllServicesReady(5000, true);
|
|
|
|
|
-
|
|
|
|
|
- if (isReady) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService完全就绪');
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 如果主要服务就绪但数据未恢复,再做一次宽松检查
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '⚠️ 主要检查超时,进行备用检查');
|
|
|
|
|
- const basicReady = await unifiedService.waitForAllServicesReady(2000, false);
|
|
|
|
|
-
|
|
|
|
|
- if (basicReady) {
|
|
|
|
|
- // 检查是否至少有播放数据
|
|
|
|
|
- const currentState = unifiedService.getCurrentState();
|
|
|
|
|
- const playlist = unifiedService.getPlaylist();
|
|
|
|
|
-
|
|
|
|
|
- if (playlist.length > 0 || currentState.currentIndex >= 0) {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `✅ 基础服务就绪,播放列表: ${playlist.length} 首歌曲`);
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- hilog.warn(0x0000, 'Heanup2', '⚠️ Service readiness check timeout, proceeding with limited functionality');
|
|
|
|
|
- return false;
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ Error waiting for service ready: ${error}`);
|
|
|
|
|
- return false;
|
|
|
|
|
|
|
+ if (isReady) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ UnifiedPlayerService完全就绪');
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 异步初始化播放器服务,避免阻塞生命周期
|
|
|
|
|
- */
|
|
|
|
|
- private initializePlayerServiceAsync(): void {
|
|
|
|
|
- // 使用 setTimeout 将初始化操作移到下一个事件循环
|
|
|
|
|
- setTimeout(async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 开始异步初始化 UnifiedPlayerService');
|
|
|
|
|
- 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();
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ UnifiedPlayerService 异步初始化失败: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
- }, 50); // 缩短延迟,让初始化更快开始
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 如果主要服务就绪但数据未恢复,再做一次宽松检查
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '⚠️ 主要检查超时,进行备用检查');
|
|
|
|
|
+ const basicReady = await unifiedService.waitForAllServicesReady(2000, false);
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 异步处理后台逻辑
|
|
|
|
|
- */
|
|
|
|
|
- private handleBackgroundAsync(): void {
|
|
|
|
|
- try {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '🔄 处理后台逻辑');
|
|
|
|
|
-
|
|
|
|
|
- // 关键修复:应用进入后台时保存播放器状态
|
|
|
|
|
- try {
|
|
|
|
|
- const unifiedPlayerService = UnifiedPlayerService.getInstance();
|
|
|
|
|
- if (unifiedPlayerService && unifiedPlayerService.isAllServicesReady()) {
|
|
|
|
|
- // 保存当前状态,确保即使应用被强制杀死也能保存正确状态
|
|
|
|
|
- unifiedPlayerService.saveCurrentStateExternal();
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 播放器状态已保存(后台)');
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 保存播放器状态失败: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 后台时可以执行一些清理或保存操作
|
|
|
|
|
- // 但要确保不会阻塞生命周期
|
|
|
|
|
-
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', '✅ 后台逻辑处理完成');
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 后台逻辑处理失败: ${error}`);
|
|
|
|
|
|
|
+ if (basicReady) {
|
|
|
|
|
+ // 检查是否至少有播放数据
|
|
|
|
|
+ const currentState = unifiedService.getCurrentState();
|
|
|
|
|
+ const playlist = unifiedService.getPlaylist();
|
|
|
|
|
+
|
|
|
|
|
+ if (playlist.length > 0 || currentState.currentIndex >= 0) {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `✅ 基础服务就绪,播放列表: ${playlist.length} 首歌曲`);
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
- */
|
|
|
|
|
- private handleWantAsync(want: Want): void {
|
|
|
|
|
- setTimeout(async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- this.loadDoWant(want);
|
|
|
|
|
- await this.handleParam(want);
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `❌ 处理Want参数失败: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
- }, 200);
|
|
|
|
|
|
|
+ hilog.warn(0x0000, 'Heanup2', '⚠️ Service readiness check timeout, proceeding with limited functionality');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ Error waiting for service ready: ${error}`);
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 异步初始化播放器服务,避免阻塞生命周期
|
|
|
|
|
+ */
|
|
|
|
|
+ private initializePlayerServiceAsync(): void {
|
|
|
|
|
+ // 使用 setTimeout 将初始化操作移到下一个事件循环
|
|
|
|
|
+ setTimeout(async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '🔄 开始异步初始化 UnifiedPlayerService');
|
|
|
|
|
+ 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();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ UnifiedPlayerService 异步初始化失败: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 50); // 缩短延迟,让初始化更快开始
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 异步处理后台逻辑
|
|
|
|
|
+ */
|
|
|
|
|
+ private handleBackgroundAsync(): void {
|
|
|
|
|
+ try {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '🔄 处理后台逻辑');
|
|
|
|
|
+
|
|
|
|
|
+ // 关键修复:应用进入后台时保存播放器状态
|
|
|
|
|
+ try {
|
|
|
|
|
+ const unifiedPlayerService = UnifiedPlayerService.getInstance();
|
|
|
|
|
+ if (unifiedPlayerService && unifiedPlayerService.isAllServicesReady()) {
|
|
|
|
|
+ // 保存当前状态,确保即使应用被强制杀死也能保存正确状态
|
|
|
|
|
+ unifiedPlayerService.saveCurrentStateExternal();
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ 播放器状态已保存(后台)');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ 保存播放器状态失败: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ // 后台时可以执行一些清理或保存操作
|
|
|
|
|
+ // 但要确保不会阻塞生命周期
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 清理所有Form ID
|
|
|
|
|
- * 应用销毁时调用,确保清理所有持久化的Form ID
|
|
|
|
|
- */
|
|
|
|
|
- private async clearAllFormIds(): Promise<void> {
|
|
|
|
|
- try {
|
|
|
|
|
- const preferencesUtil = PreferencesUtil.getInstance();
|
|
|
|
|
- const prefs = await preferencesUtil.getPreferences(this.context);
|
|
|
|
|
-
|
|
|
|
|
- // 获取所有Form ID
|
|
|
|
|
- const formIds = await preferencesUtil.getFormIds(prefs);
|
|
|
|
|
-
|
|
|
|
|
- if (formIds.length > 0) {
|
|
|
|
|
- // 清理所有Form ID
|
|
|
|
|
- await preferencesUtil.removeFormIds(prefs, formIds);
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', `Cleared ${formIds.length} form IDs on app destroy: ${formIds.join(', ')}`);
|
|
|
|
|
- } else {
|
|
|
|
|
- hilog.info(0x0000, 'Heanup2', 'No form IDs to clear on app destroy');
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- hilog.error(0x0000, 'Heanup2', `Failed to clear form IDs: ${error}`);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', '✅ 后台逻辑处理完成');
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ 后台逻辑处理失败: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 异步处理Want参数,避免阻塞生命周期
|
|
|
|
|
+ */
|
|
|
|
|
+ private handleWantAsync(want: Want): void {
|
|
|
|
|
+ setTimeout(async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.loadDoWant(want);
|
|
|
|
|
+ await this.handleParam(want);
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `❌ 处理Want参数失败: ${error}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 200);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 清理所有Form ID
|
|
|
|
|
+ * 应用销毁时调用,确保清理所有持久化的Form ID
|
|
|
|
|
+ */
|
|
|
|
|
+ private async clearAllFormIds(): Promise<void> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const preferencesUtil = PreferencesUtil.getInstance();
|
|
|
|
|
+ const prefs = await preferencesUtil.getPreferences(this.context);
|
|
|
|
|
+
|
|
|
|
|
+ // 获取所有Form ID
|
|
|
|
|
+ const formIds = await preferencesUtil.getFormIds(prefs);
|
|
|
|
|
+
|
|
|
|
|
+ if (formIds.length > 0) {
|
|
|
|
|
+ // 清理所有Form ID
|
|
|
|
|
+ await preferencesUtil.removeFormIds(prefs, formIds);
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', `Cleared ${formIds.length} form IDs on app destroy: ${formIds.join(', ')}`);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ hilog.info(0x0000, 'Heanup2', 'No form IDs to clear on app destroy');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ hilog.error(0x0000, 'Heanup2', `Failed to clear form IDs: ${error}`);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|