|
|
@@ -10,7 +10,7 @@ import {
|
|
|
} from './PlayerStateModel';
|
|
|
import { PlaylistModel } from './PlaylistModel';
|
|
|
import { IjkMediaPlayer, LogUtils, InterruptEvent, InterruptHintType } from '@ohos/ijkplayer';
|
|
|
-import { common } from '@kit.AbilityKit';
|
|
|
+import { common, Context } from '@kit.AbilityKit';
|
|
|
import { PreferencesUtil as PuraPreferencesUtil, StrUtil } from '@pura/harmony-utils';
|
|
|
import {
|
|
|
DataPersistenceService,
|
|
|
@@ -39,6 +39,21 @@ import { FormRdbHelper } from '../../database/FormRdbHelper';
|
|
|
import { FormInfo } from '../../viewmodel/FormInfo';
|
|
|
import { WidgetDataRdbHelper } from '../../database/WidgetDataRdbHelper';
|
|
|
import { WidgetDataInfo } from '../../viewmodel/WidgetDataInfo';
|
|
|
+import { PreferencesUtil, IWidgetData } from '../utils/PreferencesUtil';
|
|
|
+
|
|
|
+/**
|
|
|
+ * 存储方式枚举
|
|
|
+ */
|
|
|
+enum WidgetDataStorageType {
|
|
|
+ DATABASE = 'database', // 使用数据库存储
|
|
|
+ PREFERENCES = 'preferences' // 使用Preferences存储
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 控制WidgetData存储方式的配置
|
|
|
+ * 可以通过修改这个值来切换存储方式
|
|
|
+ */
|
|
|
+const WIDGET_DATA_STORAGE_TYPE: WidgetDataStorageType = WidgetDataStorageType.DATABASE;
|
|
|
|
|
|
/**
|
|
|
* 服务就绪状态详情接口
|
|
|
@@ -153,19 +168,6 @@ interface CachedWidgetData {
|
|
|
finalImagePath: string | null;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * 多歌曲缓存管理器
|
|
|
- * 缓存当前歌曲及其上下首歌曲的卡片数据
|
|
|
- */
|
|
|
-interface MultiSongWidgetCache {
|
|
|
- // 当前歌曲的文件路径,用于标识缓存是否有效
|
|
|
- currentSongPath: string;
|
|
|
- // 缓存的歌曲数据,key为文件路径
|
|
|
- songDataCache: Map<string, CachedWidgetData>;
|
|
|
- // 预缓存任务状态,避免重复预缓存
|
|
|
- preloadingPaths: Set<string>;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* 统一播放器服务接口
|
|
|
* 提供统一的播放控制接口,替代LocalMusic中的播放器逻辑
|
|
|
@@ -482,7 +484,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
|
|
|
// 卡片数据缓存
|
|
|
private widgetDataCache: CachedWidgetData | null = null;
|
|
|
- private multiSongCache: MultiSongWidgetCache | null = null;
|
|
|
|
|
|
private constructor() {
|
|
|
this.playerManager = PlayerManager.getInstance();
|
|
|
@@ -1069,11 +1070,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
await this.updateAvSessionMetadata(newSong)
|
|
|
}
|
|
|
|
|
|
- // 触发预缓存相邻歌曲的卡片数据
|
|
|
- this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload after track change failed: ${error}`);
|
|
|
- });
|
|
|
-
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: Widget state updated after track change');
|
|
|
} catch (error) {
|
|
|
LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to update widgets after track change: ${error}`);
|
|
|
@@ -1125,14 +1121,9 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
this.stateModel.updateCurrentSong(newCurrentSong);
|
|
|
}
|
|
|
|
|
|
- // 同步更新所有桌面卡片状态
|
|
|
- await this.updateAllForms();
|
|
|
-
|
|
|
// 异步预缓存相邻歌曲的卡片数据
|
|
|
setTimeout(() => {
|
|
|
- this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload after song selection failed: ${error}`);
|
|
|
- });
|
|
|
+ this.updateAllForms();
|
|
|
}, 0);
|
|
|
|
|
|
} catch (error) {
|
|
|
@@ -1171,36 +1162,6 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
return this.playlistModel.getCurrentSong();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 获取上一首歌曲信息
|
|
|
- */
|
|
|
- getPreviousSong(): VideoItem | null {
|
|
|
- const playlist = this.getPlaylist();
|
|
|
- const currentIndex = this.getCurrentIndex();
|
|
|
-
|
|
|
- if (playlist.length === 0 || currentIndex < 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- const previousIndex = (currentIndex - 1 + playlist.length) % playlist.length;
|
|
|
- return playlist[previousIndex] || null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取下一首歌曲信息
|
|
|
- */
|
|
|
- getNextSong(): VideoItem | null {
|
|
|
- const playlist = this.getPlaylist();
|
|
|
- const currentIndex = this.getCurrentIndex();
|
|
|
-
|
|
|
- if (playlist.length === 0 || currentIndex < 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- const nextIndex = (currentIndex + 1) % playlist.length;
|
|
|
- return playlist[nextIndex] || null;
|
|
|
- }
|
|
|
-
|
|
|
getFav(): Array<VideoItem> {
|
|
|
if (this.favList.length > 0) {
|
|
|
return this.favList;
|
|
|
@@ -3048,9 +3009,17 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- const formInfoList = await FormRdbHelper.getInstance(context).queryAllForms();
|
|
|
+ // 根据存储配置获取Form列表
|
|
|
+ let formInfoList: FormInfo[] = [];
|
|
|
+ if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
|
|
|
+ formInfoList = await FormRdbHelper.getInstance(context).queryAllForms();
|
|
|
+ } else {
|
|
|
+ // 从Preferences获取Form列表
|
|
|
+ formInfoList = await this.getFormInfoListFromPreferences(context);
|
|
|
+ }
|
|
|
+
|
|
|
if (formInfoList.length === 0) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: No forms found in database');
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: No forms found');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -3058,7 +3027,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
// 直接获取包含所有数据的卡片信息,包括图片。
|
|
|
// 图片加载有缓存机制,对于已加载过的歌曲,此操作很快。
|
|
|
// 这可以避免双阶段更新导致的UI闪烁问题(例如背景色先变默认再变主色调)。
|
|
|
- const widgetData = await this.getWidgetFormData(true); // true: 加载图片
|
|
|
+ const widgetData = await this.getWidgetFormData(); // true: 加载图片
|
|
|
if (!widgetData) {
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService updateAllForms: Failed to get widget data.');
|
|
|
return;
|
|
|
@@ -3150,70 +3119,54 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
return defaultData;
|
|
|
}
|
|
|
|
|
|
- // 2. 处理静态数据(优先从多歌曲缓存获取)
|
|
|
- this.initMultiSongCache();
|
|
|
-
|
|
|
- // 首先尝试从多歌曲缓存获取
|
|
|
- let cachedData = this.getCachedSongData(formData.filePath);
|
|
|
-
|
|
|
- if (cachedData) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Multi-cache hit for [${formData.name}].`);
|
|
|
- } else {
|
|
|
- // 多歌曲缓存未命中,尝试从旧的单歌曲缓存获取
|
|
|
- if (this.widgetDataCache?.filePath !== formData.filePath) {
|
|
|
- this.widgetDataCache = null;
|
|
|
- }
|
|
|
+ // 2. 处理静态数据(利用缓存)
|
|
|
+ // 如果歌曲已切换,则清空缓存
|
|
|
+ if (this.widgetDataCache?.filePath !== formData.filePath) {
|
|
|
+ this.widgetDataCache = null;
|
|
|
+ }
|
|
|
|
|
|
- if (this.widgetDataCache) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Single-cache hit for [${formData.name}].`);
|
|
|
- cachedData = this.widgetDataCache;
|
|
|
- // 将旧缓存数据迁移到新的多歌曲缓存
|
|
|
- this.multiSongCache!.songDataCache.set(formData.filePath, cachedData);
|
|
|
- } else {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Cache miss for [${formData.name}], generating static data.`);
|
|
|
- // 缓存完全未命中,生成并缓存静态数据
|
|
|
- let finalImagePath: string | null = null;
|
|
|
- if (loadImage && formData.pixelMapPath && formData.pixelMapPath.trim() !== '') {
|
|
|
- if (formData.pixelMapPath.startsWith('http')) {
|
|
|
- // 网络图片,走缓存/下载逻辑
|
|
|
- if (this.imageCacheDir) {
|
|
|
- const cacheFileName = this.generateCacheFileName(formData.pixelMapPath);
|
|
|
- const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
|
|
|
- if (await this.isCacheValid(cacheFilePath)) {
|
|
|
+ if (!this.widgetDataCache) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Cache miss for [${formData.name}], generating static data.`);
|
|
|
+ // 缓存未命中,生成并缓存静态数据
|
|
|
+ let finalImagePath: string | null = null;
|
|
|
+ if (loadImage && formData.pixelMapPath && formData.pixelMapPath.trim() !== '') {
|
|
|
+ if (formData.pixelMapPath.startsWith('http')) {
|
|
|
+ // 网络图片,走缓存/下载逻辑
|
|
|
+ if (this.imageCacheDir) {
|
|
|
+ const cacheFileName = this.generateCacheFileName(formData.pixelMapPath);
|
|
|
+ const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
|
|
|
+ if (await this.isCacheValid(cacheFilePath)) {
|
|
|
+ finalImagePath = cacheFilePath;
|
|
|
+ } else {
|
|
|
+ const downloadSuccess = await this.downloadImageToCache(formData.pixelMapPath, cacheFilePath);
|
|
|
+ if (downloadSuccess) {
|
|
|
finalImagePath = cacheFilePath;
|
|
|
- } else {
|
|
|
- const downloadSuccess = await this.downloadImageToCache(formData.pixelMapPath, cacheFilePath);
|
|
|
- if (downloadSuccess) {
|
|
|
- finalImagePath = cacheFilePath;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
- } else {
|
|
|
- // 本地图片
|
|
|
- finalImagePath = formData.pixelMapPath;
|
|
|
}
|
|
|
+ } else {
|
|
|
+ // 本地图片
|
|
|
+ finalImagePath = formData.pixelMapPath;
|
|
|
}
|
|
|
-
|
|
|
- cachedData = {
|
|
|
- id: formData.id || '',
|
|
|
- name: formData.name || '',
|
|
|
- artist: formData.artist || '',
|
|
|
- album: formData.album || '',
|
|
|
- pixelMapPath: formData.pixelMapPath || '',
|
|
|
- duration: typeof formData.duration === 'string' ? parseInt(formData.duration || '0') : (formData.duration || 0),
|
|
|
- filePath: formData.filePath || '',
|
|
|
- imageColorHex: '2A2A2A', // 默认颜色,UI侧会根据图片重新提取
|
|
|
- finalImagePath: finalImagePath
|
|
|
- };
|
|
|
-
|
|
|
- // 同时存储到新旧缓存
|
|
|
- this.widgetDataCache = cachedData;
|
|
|
- this.multiSongCache!.songDataCache.set(formData.filePath, cachedData);
|
|
|
}
|
|
|
+
|
|
|
+ this.widgetDataCache = {
|
|
|
+ id: formData.id || '',
|
|
|
+ name: formData.name || '',
|
|
|
+ artist: formData.artist || '',
|
|
|
+ album: formData.album || '',
|
|
|
+ pixelMapPath: formData.pixelMapPath || '',
|
|
|
+ duration: typeof formData.duration === 'string' ? parseInt(formData.duration || '0') : (formData.duration || 0),
|
|
|
+ filePath: formData.filePath || '',
|
|
|
+ imageColorHex: '2A2A2A', // 默认颜色,UI侧会根据图片重新提取
|
|
|
+ finalImagePath: finalImagePath
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Cache hit for [${formData.name}].`);
|
|
|
}
|
|
|
|
|
|
// 3. 组合静态和动态数据,并处理图片文件描述符
|
|
|
- // cachedData 已在上面获取
|
|
|
+ const cachedData = this.widgetDataCache;
|
|
|
|
|
|
let imgName: string = '';
|
|
|
|
|
|
@@ -3226,7 +3179,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
imgMap[imgName] = file.fd;
|
|
|
// 注意:我们不关闭这个fd,系统会在处理完卡片数据后关闭它
|
|
|
} catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to open image file [${cachedData.finalImagePath}]: ${JSON.stringify(error)}`);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Failed to open image file [${cachedData.finalImagePath}]: ${JSON.stringify(error)}`);
|
|
|
imgMap = {};
|
|
|
imgName = '';
|
|
|
}
|
|
|
@@ -3275,177 +3228,9 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
// 将widgetData存入数据库
|
|
|
this.saveWidgetDataToDatabase(widgetData, formData);
|
|
|
|
|
|
- // 4. 异步预缓存相邻歌曲的卡片数据(不阻塞当前响应)
|
|
|
- setTimeout(() => {
|
|
|
- this.preloadAdjacentSongsWidgetData().catch((error:Error) => {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Background preload failed: ${error}`);
|
|
|
- });
|
|
|
-
|
|
|
- // 清理过期缓存
|
|
|
- this.cleanupOldCache();
|
|
|
- }, 0);
|
|
|
-
|
|
|
return widgetData;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 初始化多歌曲缓存
|
|
|
- */
|
|
|
- private initMultiSongCache(): void {
|
|
|
- const currentSong = this.getCurrentSong();
|
|
|
- if (!currentSong || !currentSong.filePath) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (!this.multiSongCache || this.multiSongCache.currentSongPath !== currentSong.filePath) {
|
|
|
- this.multiSongCache = {
|
|
|
- currentSongPath: currentSong.filePath,
|
|
|
- songDataCache: new Map<string, CachedWidgetData>(),
|
|
|
- preloadingPaths: new Set<string>()
|
|
|
- };
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 从多歌曲缓存中获取歌曲数据
|
|
|
- */
|
|
|
- private getCachedSongData(filePath: string): CachedWidgetData | null {
|
|
|
- if (!this.multiSongCache) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return this.multiSongCache.songDataCache.get(filePath) || null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 异步预缓存歌曲的卡片数据
|
|
|
- */
|
|
|
- private async preloadSongWidgetData(song: VideoItem): Promise<void> {
|
|
|
- if (!song || !song.filePath) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- this.initMultiSongCache();
|
|
|
-
|
|
|
- // 避免重复预缓存
|
|
|
- if (this.multiSongCache!.preloadingPaths.has(song.filePath) ||
|
|
|
- this.multiSongCache!.songDataCache.has(song.filePath)) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- this.multiSongCache!.preloadingPaths.add(song.filePath);
|
|
|
-
|
|
|
- try {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Preloading widget data for [${song.name}]`);
|
|
|
-
|
|
|
- // 处理图片路径
|
|
|
- let finalImagePath: string | null = null;
|
|
|
- if (song.pixelMapPath && song.pixelMapPath.trim() !== '') {
|
|
|
- if (song.pixelMapPath.startsWith('http')) {
|
|
|
- // 网络图片,走缓存/下载逻辑
|
|
|
- if (this.imageCacheDir) {
|
|
|
- const cacheFileName = this.generateCacheFileName(song.pixelMapPath);
|
|
|
- const cacheFilePath = `${this.imageCacheDir}/${cacheFileName}`;
|
|
|
- if (await this.isCacheValid(cacheFilePath)) {
|
|
|
- finalImagePath = cacheFilePath;
|
|
|
- } else {
|
|
|
- const downloadSuccess = await this.downloadImageToCache(song.pixelMapPath, cacheFilePath);
|
|
|
- if (downloadSuccess) {
|
|
|
- finalImagePath = cacheFilePath;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 本地图片
|
|
|
- finalImagePath = song.pixelMapPath;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 创建缓存数据
|
|
|
- const cachedData: CachedWidgetData = {
|
|
|
- id: song.id || '',
|
|
|
- name: song.name || '',
|
|
|
- artist: song.artist || '',
|
|
|
- album: song.album || '',
|
|
|
- pixelMapPath: song.pixelMapPath || '',
|
|
|
- duration: typeof song.duration === 'string' ? parseInt(song.duration || '0') : (song.duration || 0),
|
|
|
- filePath: song.filePath || '',
|
|
|
- imageColorHex: '2A2A2A', // 默认颜色
|
|
|
- finalImagePath: finalImagePath
|
|
|
- };
|
|
|
-
|
|
|
- // 存储到缓存
|
|
|
- this.multiSongCache!.songDataCache.set(song.filePath, cachedData);
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Successfully preloaded widget data for [${song.name}]`);
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Failed to preload widget data for [${song.name}]: ${error}`);
|
|
|
- } finally {
|
|
|
- // 移除预缓存状态
|
|
|
- this.multiSongCache!.preloadingPaths.delete(song.filePath);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 预缓存当前歌曲及其上下首歌曲的卡片数据
|
|
|
- */
|
|
|
- private async preloadAdjacentSongsWidgetData(): Promise<void> {
|
|
|
- const currentSong = this.getCurrentSong();
|
|
|
- const previousSong = this.getPreviousSong();
|
|
|
- const nextSong = this.getNextSong();
|
|
|
-
|
|
|
- // 重新初始化缓存(如果当前歌曲已变化)
|
|
|
- this.initMultiSongCache();
|
|
|
-
|
|
|
- // 并行预缓存所有相关歌曲
|
|
|
- const preloadTasks: Promise<void>[] = [];
|
|
|
-
|
|
|
- if (currentSong) {
|
|
|
- preloadTasks.push(this.preloadSongWidgetData(currentSong));
|
|
|
- }
|
|
|
- if (previousSong && previousSong.filePath !== currentSong?.filePath) {
|
|
|
- preloadTasks.push(this.preloadSongWidgetData(previousSong));
|
|
|
- }
|
|
|
- if (nextSong && nextSong.filePath !== currentSong?.filePath && nextSong.filePath !== previousSong?.filePath) {
|
|
|
- preloadTasks.push(this.preloadSongWidgetData(nextSong));
|
|
|
- }
|
|
|
-
|
|
|
- // 等待所有预缓存任务完成
|
|
|
- try {
|
|
|
- await Promise.all(preloadTasks);
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Completed preloading adjacent songs widget data');
|
|
|
- } catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Error during preloading adjacent songs: ${error}`);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 清理过期的缓存数据,保持缓存大小合理
|
|
|
- */
|
|
|
- private cleanupOldCache(): void {
|
|
|
- if (!this.multiSongCache) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const currentSong = this.getCurrentSong();
|
|
|
- const previousSong = this.getPreviousSong();
|
|
|
- const nextSong = this.getNextSong();
|
|
|
-
|
|
|
- // 收集当前相关的歌曲路径
|
|
|
- const relevantPaths = new Set<string>();
|
|
|
- if (currentSong?.filePath) relevantPaths.add(currentSong.filePath);
|
|
|
- if (previousSong?.filePath) relevantPaths.add(previousSong.filePath);
|
|
|
- if (nextSong?.filePath) relevantPaths.add(nextSong.filePath);
|
|
|
-
|
|
|
- // 移除不相关的缓存
|
|
|
- const cachedPaths = Array.from(this.multiSongCache.songDataCache.keys());
|
|
|
- for (const path of cachedPaths) {
|
|
|
- if (!relevantPaths.has(path)) {
|
|
|
- this.multiSongCache.songDataCache.delete(path);
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService: Cleaned up cache for song: ${path}`);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 计算播放进度百分比
|
|
|
*/
|
|
|
@@ -3466,7 +3251,8 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 将widgetData存入数据库
|
|
|
+ * 将widgetData存入存储中
|
|
|
+ * 根据配置选择数据库或Preferences存储
|
|
|
*/
|
|
|
private async saveWidgetDataToDatabase(widgetData: widgeData, formData: VideoItem): Promise<void> {
|
|
|
try {
|
|
|
@@ -3520,14 +3306,92 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
widgetDataInfo.totalTimeText = widgetData.totalTimeText;
|
|
|
widgetDataInfo.progressPercentage = widgetData.progressPercentage;
|
|
|
|
|
|
- await WidgetDataRdbHelper.getInstance(context).insertOrUpdateWidgetData(widgetDataInfo);
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to database for song: ${formData.name}`);
|
|
|
+ // 根据配置选择存储方式
|
|
|
+ if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
|
|
|
+ await WidgetDataRdbHelper.getInstance(context).insertOrUpdateWidgetData(widgetDataInfo);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to database for song: ${formData.name}`);
|
|
|
+ } else {
|
|
|
+ await this.saveWidgetDataToPreferences(widgetDataInfo, context);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Widget data saved to preferences for song: ${formData.name}`);
|
|
|
+ }
|
|
|
|
|
|
} catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService saveWidgetDataToDatabase: Failed to save widget data to database: ${error}`);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToDatabase: Failed to save widget data to storage: ${error}`);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 将widgetData保存到Preferences
|
|
|
+ */
|
|
|
+ private async saveWidgetDataToPreferences(widgetDataInfo: WidgetDataInfo, context: Context): Promise<void> {
|
|
|
+ try {
|
|
|
+ const preferencesUtil = PreferencesUtil.getInstance();
|
|
|
+ const prefs = await preferencesUtil.getPreferences(context);
|
|
|
+
|
|
|
+ // 将WidgetDataInfo转换为IWidgetData接口格式
|
|
|
+ const widgetData: IWidgetData = {
|
|
|
+ songId: widgetDataInfo.songId,
|
|
|
+ name: widgetDataInfo.name,
|
|
|
+ artist: widgetDataInfo.artist,
|
|
|
+ album: widgetDataInfo.album,
|
|
|
+ pixelMapPath: widgetDataInfo.pixelMapPath,
|
|
|
+ duration: widgetDataInfo.duration,
|
|
|
+ filePath: widgetDataInfo.filePath,
|
|
|
+ imgName: widgetDataInfo.imgName,
|
|
|
+ imageColorHex: widgetDataInfo.imageColorHex,
|
|
|
+ isFavorite: widgetDataInfo.isFavorite,
|
|
|
+ isPlaying: widgetDataInfo.isPlaying,
|
|
|
+ isPaused: widgetDataInfo.isPaused,
|
|
|
+ isLoading: widgetDataInfo.isLoading,
|
|
|
+ currentPosition: widgetDataInfo.currentPosition,
|
|
|
+ hasNext: widgetDataInfo.hasNext,
|
|
|
+ hasPrevious: widgetDataInfo.hasPrevious,
|
|
|
+ playMode: widgetDataInfo.playMode,
|
|
|
+ currentIndex: widgetDataInfo.currentIndex,
|
|
|
+ totalCount: widgetDataInfo.totalCount,
|
|
|
+ currentTimeText: widgetDataInfo.currentTimeText,
|
|
|
+ totalTimeText: widgetDataInfo.totalTimeText,
|
|
|
+ progressPercentage: widgetDataInfo.progressPercentage,
|
|
|
+ createTime: widgetDataInfo.createTime,
|
|
|
+ updateTime: widgetDataInfo.updateTime
|
|
|
+ };
|
|
|
+
|
|
|
+ await preferencesUtil.saveWidgetData(prefs, widgetData);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToPreferences: Widget data saved to preferences for song: ${widgetDataInfo.name}`);
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService saveWidgetDataToPreferences: Failed to save widget data to preferences: ${error}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从Preferences获取FormInfo列表
|
|
|
+ */
|
|
|
+ private async getFormInfoListFromPreferences(context: Context): Promise<FormInfo[]> {
|
|
|
+ try {
|
|
|
+ const preferencesUtil = PreferencesUtil.getInstance();
|
|
|
+ const prefs = await preferencesUtil.getPreferences(context);
|
|
|
+
|
|
|
+ const formInfoDataList = await preferencesUtil.getAllFormInfos(prefs);
|
|
|
+
|
|
|
+ // 将IFormInfo转换为FormInfo类型
|
|
|
+ const formInfoList: FormInfo[] = formInfoDataList.map(data => {
|
|
|
+ const formInfo = new FormInfo();
|
|
|
+ formInfo.formId = data.formId;
|
|
|
+ formInfo.formName = data.formName;
|
|
|
+ formInfo.formDimension = data.formDimension;
|
|
|
+ formInfo.createTime = data.createTime;
|
|
|
+ formInfo.updateTime = data.updateTime;
|
|
|
+ return formInfo;
|
|
|
+ });
|
|
|
+
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Found ${formInfoList.length} forms in preferences`);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Using context: ${context ? 'Available' : 'NULL'}, Process: ${AppStorage.get('processName') || 'Unknown'}`);
|
|
|
+ return formInfoList;
|
|
|
+ } catch (error) {
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService getFormInfoListFromPreferences: Failed to get forms from preferences: ${error}`);
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 状态变化时更新卡片
|
|
|
@@ -4014,18 +3878,23 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
LogUtils.getInstance().LOGI('UnifiedPlayerService: No context for cleanup invalid form IDs');
|
|
|
return;
|
|
|
}
|
|
|
- // 从数据库读取所有Form信息
|
|
|
+ // 根据存储配置读取所有Form信息
|
|
|
let formInfoList: FormInfo[] = [];
|
|
|
try {
|
|
|
- formInfoList = await FormRdbHelper.getInstance(this.context).queryAllForms();
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in database`);
|
|
|
+ if (WIDGET_DATA_STORAGE_TYPE === WidgetDataStorageType.DATABASE) {
|
|
|
+ formInfoList = await FormRdbHelper.getInstance(this.context).queryAllForms();
|
|
|
+ LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in database`);
|
|
|
+ } else {
|
|
|
+ formInfoList = await this.getFormInfoListFromPreferences(this.context);
|
|
|
+ LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Found ${formInfoList.length} forms in preferences`);
|
|
|
+ }
|
|
|
} catch (error) {
|
|
|
- LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Failed to query forms from database: ${error}`);
|
|
|
+ LogUtils.getInstance().LOGI(`Heanup UnifiedPlayerService cleanupInvalidFormIds: Failed to query forms: ${error}`);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (formInfoList.length === 0) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService cleanupInvalidFormIds: No forms found in database');
|
|
|
+ LogUtils.getInstance().LOGI('UnifiedPlayerService cleanupInvalidFormIds: No forms found');
|
|
|
return;
|
|
|
}
|
|
|
|