import { BusinessError, pasteboard } from '@kit.BasicServicesKit'; import { AppUtil, ArrayUtil, Base64Util, DateUtil, FileUtil, ImageUtil, LogUtil, MD5, PreferencesUtil, RandomUtil, StrUtil, ToastUtil } from '@pura/harmony-utils'; import { media } from '@kit.MediaKit'; import fs from '@ohos.file.fs'; import { image } from '@kit.ImageKit'; import fileIo from '@ohos.file.fs'; import { VideoItem } from '../../viewmodel/VideoItem'; import { photoAccessHelper } from '@kit.MediaLibraryKit'; import { dataSharePredicates, uniformTypeDescriptor } from '@kit.ArkData'; import { systemShare } from '@kit.ShareKit'; import { fileUri } from '@kit.CoreFileKit'; import { common, UIAbility, Want } from '@kit.AbilityKit'; import { CommonConstants } from '../constants/CommonConstants'; import { window } from '@kit.ArkUI'; import { bundleManager } from '@kit.AbilityKit' import { VipPage } from '../../pages/VipPage'; import NetAxiosUtil from './NetAxiosUtil'; // import userFileManager from '@ohos.filemanagement.userFileManager'; export class Utility { private constructor() {} static isOpenTime():boolean{ const currentDate = new Date(); const targetDate = new Date(CommonConstants.OPEN_DATE); if (currentDate > targetDate) { return true } return false } //是否赞助 static isNoble():boolean{ if(!Utility.isOpenTime())//提交审核的审核,刚刚开始可以全部是赞助用户。 return true return PreferencesUtil.getBooleanSync('isNoble',false) } //判断用户安装app是否超过2天,超过2天(2800分钟)才展示广告 显示广告 24*60=1440 1440*2=2800 static isPassInstallTime(day:number):boolean{ //获取当前时间 let currentTime = new Date().getTime(); // 尝试从存储中获取安装时间 let installTime = getInstallTime(); if (installTime===0||installTime === null|| installTime===undefined) { // 如果没有存储安装时间,则存储当前时间为安装时间 setInstallTime(currentTime); return false } else { // 计算时间差(以分钟为单位) const timeDifference = (currentTime - installTime) / (1000 * 60); LogUtil.debug("onecold timeDifference=" + timeDifference) // 如果超过5分钟,显示广告 24*60=1440 1440*2=2800 if (timeDifference > 24*60*day) { return true }else{ return false } } } static optimizedFormat(speed: number): string { if (speed) { const str = speed.toFixed(2); let end = str.length; while (end > 0 && (str[end - 1] === '0' || str[end - 1] === '.')) { end--; if (str[end] === '.') { break; } } return str.slice(0, end || 1) + 'x'; } else { return '1x' } } static isHaoOpenTime():boolean{ const currentDate = new Date(); const targetDate = new Date('2025-04-20'); if (currentDate < targetDate) { return true } return false } static setNoble(expireDate:string){ let isNoble = false if(StrUtil.isNotEmpty(expireDate)){ if(expireDate===VipPage.FOEVEER_DATE){ isNoble = true }else{ const currentDate = new Date(); const targetDate = DateUtil.getFormatDate(expireDate) if (currentDate > targetDate) { isNoble = false }else{ isNoble = true } } } PreferencesUtil.putSync('isNoble',isNoble) } static addDays(date: Date, days: number): Date { const result = new Date(date); result.setDate(result.getDate() + days); return result; } static convertToKHz(sampleRateHz: string|undefined): string { if(StrUtil.isEmpty(sampleRateHz) || sampleRateHz === undefined || sampleRateHz === "0") { return '未知'; } try { const sampleRateNum = Number(sampleRateHz); if (isNaN(sampleRateNum) || sampleRateNum <= 0) { return '未知'; } const sampleRateKHz = sampleRateNum / 1000; return `${sampleRateKHz.toFixed(1)} KHz`; } catch (err) { console.error(`转换采样率出错: ${err}`); return '未知'; } } /** * 格式化媒体格式类型显示 * @param mimeType 媒体格式类型字符串 * @return 格式化后的显示字符串 */ static formatMimeType(mimeType: string|undefined): string { if(StrUtil.isEmpty(mimeType) || mimeType === undefined) { return '未知'; } // 从MIME类型中提取格式部分,例如 "audio/mp3" -> "MP3" try { const parts = mimeType.split('/'); if (parts.length > 1) { return parts[1].toUpperCase(); } else { return mimeType.toUpperCase(); } } catch (err) { console.error(`格式化媒体类型出错: ${err}`); return '未知'; } } /** * 格式化媒体格式类型显示 * @param mimeType 媒体格式类型字符串 * @return 格式化后的显示字符串 */ static formatMimeType(mimeType: string | undefined): string { if (StrUtil.isEmpty(mimeType) || mimeType === undefined) { return 'unknown'; } // 从MIME类型中提取格式部分,例如 "audio/mp3" -> "MP3" try { const parts = mimeType.split('/'); if (parts.length > 1) { return parts[1].toUpperCase(); } else { return mimeType.toUpperCase(); } } catch (err) { console.error(`格式化媒体类型出错: ${err}`); return 'unknown'; } } //根据字节获取大小 static formatFileSize(bytes:number) { const units = ['Bytes', 'Kbps', 'Mbps']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } if(size > 1024&&unitIndex==2){ size = size*0.1 } if(size > 1024&&unitIndex==2){ size = size*0.1 } if(size > 480&&unitIndex==2){ size = size*0.5 } // 保留两位小数, 四舍五入 size = Math.round(size * 10) / 10; return size + units[unitIndex] } //根据字节获取大小无单位 static formatFileSizeWithout(bytes:number) { const units = ['Bytes', 'Kbps', 'Mbps']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } if(size > 1024&&unitIndex==2){ size = size*0.1 } if(size > 1024&&unitIndex==2){ size = size*0.1 } if(size > 480&&unitIndex==2){ size = size*0.5 } // 保留两位小数, 四舍五入 size = Math.round(size * 10) / 10; return size } static copyText(text:string):boolean{ const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN,text) const systemPasteboard = pasteboard.getSystemPasteboard() systemPasteboard.setData(pasteboardData) systemPasteboard.getData().then((data)=>{ return data }) return false } static getDbm(rssi:number):number{ return Math.round((rssi / 2) + 100) } //根据数字形式的IP地址获取字符串形式的IP地址 static getIpAddrFromNum(ipNum: number): string { return (ipNum >>> 24) + '.' + (ipNum >> 16 & 0xFF) + '.' + (ipNum >> 8 & 0xFF) + '.' + (ipNum & 0xFF); } static resolveIP(ip:number) { let address: string = ip.toString() if (address === '0') { return '00:00:000:000' } address.substring(0, 2) return `${address.substring(0, 2)}:${address.substring(2, 4)}:${address.substring(4, 7)}:${address.substring(7, 10)}` } static isFreeTime():boolean{ if(DateUtil.isWeekend()){ return true } let str = DateUtil.getFormatDateStr(new Date(), 'HH') let a = Number(str); if(isNaN(a)) return false // ToastUtil.showToast('a='+a) if (a >= 7 && a <13) {//白天 return false; } if (a >= 13 && a <20) {//白天 return false; } if (a >= 0 && a < 7) {//凌晨 return true; } if (a >= 20 && a <= 24) {//晚上 return true; } return false } //判断是否是音乐文件 static isMusicByExtension(filename:string) { const extensions = CommonConstants.REAL_MUSIC_FORMAT const lastIndex = filename.lastIndexOf('.'); if (lastIndex!== -1) { const fileExtension = filename.slice(lastIndex).toLowerCase(); return extensions.includes(fileExtension); } return false; } //判断是否是媒体文件 音乐和视频都可以 static isMeidaByExtension(filename:string) { const extensions = CommonConstants.MEDIA_FORMAT const lastIndex = filename.lastIndexOf('.'); if (lastIndex!== -1) { const fileExtension = filename.slice(lastIndex).toLowerCase(); return extensions.includes(fileExtension); } return false; } //判断是否是视频文件 static isVideoByExtension(filename:string) { const extensions = CommonConstants.VIDEO_FORMAT const lastIndex = filename.lastIndexOf('.'); if (lastIndex!== -1) { const fileExtension = filename.slice(lastIndex).toLowerCase(); return extensions.includes(fileExtension); } return false; } // 获取缩略图 static async getFetchFrameByTime(filePath: string) { if(Utility.isMusicByExtension(filePath)){ return undefined } let pixelMap:image.PixelMap|undefined =undefined; try{ // 创建AVImageGenerator对象 let avImageGenerator: media.AVImageGenerator = await media.createAVImageGenerator() let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY); let avFileDescriptor: media.AVFileDescriptor = { fd: file.fd }; avImageGenerator.fdSrc = avFileDescriptor; // 初始化入参 let timeUs = 0 let queryOption = media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC let param: media.PixelMapParams = { width : 300, height : 400, } // 获取缩略图(promise模式) pixelMap = await avImageGenerator.fetchFrameByTime(timeUs, queryOption, param) // 释放资源(promise模式) avImageGenerator.release() console.info(`release success.`) fs.closeSync(file); }catch (error) { console.error('uriGetAssets failed with err: ' + JSON.stringify(error)); } return pixelMap } // 获取fd文件路径 static async getFdDir(path:string){ let fdPath = 'fd://'; let file = await fileIo.open(path) fdPath = fdPath + '' + file.fd; return fdPath } // 根据uri获取文件名称 static getMediaNameByUri(myUri: string) { let myFileName = (myUri.split('/').pop()) as string; return decodeURIComponent(myFileName) } static msToStandardTime(ms:string):string{ let date = new Date(ms); let hours = date.getHours(); let minutes = date.getMinutes(); let seconds = date.getSeconds(); return hours + ':' + minutes + ':' + seconds; } //获取资源的属性值 static async uriGetAssets(context:Context,uri:string,type:number): Promise { let isFromFileMan:boolean = false if(uri.startsWith('file://media')){//图库的视频 isFromFileMan = false }else{//从文件管理器 isFromFileMan = true } if(isFromFileMan){ return await Utility.uriGetAssetsFromFile(context,uri,type); } try { let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates(); // 配置查询条件,使用PhotoViewPicker选择图片返回的uri进行查询 predicates.equalTo('uri', uri); let fetchOption: photoAccessHelper.FetchOptions = { fetchColumns: [photoAccessHelper.PhotoKeys.WIDTH, photoAccessHelper.PhotoKeys.HEIGHT, photoAccessHelper.PhotoKeys.TITLE, photoAccessHelper.PhotoKeys.SIZE, photoAccessHelper.PhotoKeys.DURATION], predicates: predicates }; let fetchResult: photoAccessHelper.FetchResult = await phAccessHelper.getAssets(fetchOption); // 得到uri对应的PhotoAsset对象,读取文件的部分信息 const asset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject(); let fd = await Utility.getFdDir(uri) let videoSize = asset.get(photoAccessHelper.PhotoKeys.SIZE).toString() let videoTime = asset.get(photoAccessHelper.PhotoKeys.DATE_ADDED_MS).toString() let fileSize = Utility.formatFSize(Number(videoSize)) let cTime = Utility.getFormatDateStr(videoTime,'yyyy-MM-dd HH:mm') // let modifyDate = asset.get(photoAccessHelper.PhotoKeys.DATE_MODIFIED_MS).toString() let item:VideoItem = new VideoItem( asset.displayName, fd,uri,type,Number(videoSize),cTime, await Utility.getFetchFrameByTime(uri),fileSize) console.info('asset displayName: ', asset.displayName); console.info('asset uri: ', asset.uri); console.info('asset photoType: ', asset.photoType); console.info('asset width: ', asset.get(photoAccessHelper.PhotoKeys.WIDTH)); console.info('asset height: ', asset.get(photoAccessHelper.PhotoKeys.HEIGHT)); console.info('asset SIZE: ' + asset.get(photoAccessHelper.PhotoKeys.SIZE)); console.info('asset DURATION: ' + asset.get(photoAccessHelper.PhotoKeys.DURATION)); // 获取缩略图 // asset.getThumbnail((err, pixelMap) => { // if (err == undefined) { // console.info('getThumbnail successful ' + JSON.stringify(pixelMap)); // } else { // console.error('getThumbnail fail', err); // } // }); return item } catch (error) { console.error('uriGetAssets failed with err: ' + JSON.stringify(error)); return new VideoItem('','','',0,0,'') } } static getTimestampFromDateStr(dateStr: string, format: string = 'yyyy-MM-dd HH:mm'): number { // 定义正则表达式以匹配日期字符串中的各部分 const regex = format .replace('yyyy', '(\\d{4})') .replace('MM', '(\\d{2})') .replace('dd', '(\\d{2})') .replace('HH', '(\\d{2})') .replace('mm', '(\\d{2})'); const match = new RegExp(regex).exec(dateStr); if (!match) { throw new Error('Invalid date string or format'); } // 解析匹配结果 const year = Number(match[1]); const month = Number(match[2]); const day = Number(match[3]); const hours = Number(match[4]); const minutes = Number(match[5]); // 创建 Date 对象 const dateObj = new Date(year, month - 1, day, hours, minutes); // 返回时间戳(以秒为单位) return Math.floor(dateObj.getTime() / 1000); } static getFormatDateStr(date: number | string | Date, format: string = 'yyyy-MM-dd HH:mm:ss'): string { // 将输入转换为 Date 对象 let dateObj: Date; if (typeof date === 'number') { // 如果是十位时间戳,转换为毫秒数 dateObj = new Date(date.toString().length === 10 ? date * 1000 : date); } else if (typeof date === 'string') { // 如果是字符串,尝试解析为 Date 对象 dateObj = new Date(date); } else { // 如果是 Date 对象,直接使用 dateObj = date; } // 定义替换规则 const replacements = new Map([ ['yyyy', String(dateObj.getFullYear())], ['MM', String(dateObj.getMonth() + 1).padStart(2, '0')], ['dd', String(dateObj.getDate()).padStart(2, '0')], ['HH', String(dateObj.getHours()).padStart(2, '0')], ['mm', String(dateObj.getMinutes()).padStart(2, '0')], ['ss', String(dateObj.getSeconds()).padStart(2, '0')] ]); // 替换格式字符串中的占位符 replacements.forEach((value, key) => { format = format.replace(new RegExp(key, 'g'), value); }); return format; } //获取从文件管理器获得的视频资源的属性值 static async uriGetAssetsFromFile(context:Context,uri:string,type:number,isLoadPixelMap?:boolean): Promise { let item:VideoItem = new VideoItem('',uri,uri,type,0,'') try { console.info('asset file.uri: ', uri); let file = fs.openSync(uri, fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE) console.info("file.fd " + file.fd); let fdfd = 'fd://' + file.fd //3、通过fs.stat方法获取stat对象 console.info('asset file.name: ', file.name); console.info('asset file.uri: ', uri); console.info('asset file.fd: ', file.fd); console.info('asset file.path: ', file.path); item = new VideoItem(file.name,uri,uri,type,0,'') await fs.stat(file.fd).then(async (stat: fs.Stat) => { console.info("get file info succeed, the size of file is " + stat.size); let videoSize = stat.size // let videoTime = stat.ctime let fileSize = Utility.formatFSize(videoSize) let cTime = Utility.getFormatDateStr(stat.mtime,'yyyy-MM-dd HH:mm') // console.info('asset stat.ino: ', stat.ino); // console.info('asset stat.mode: ', stat.mode); // console.info('asset stat.uid: ', stat.uid); // console.info('asset stat.ino: ', stat.gid); // console.info('asset stat.size: ', stat.size); console.info('asset stat.ctime: ', stat.ctime); // console.info('asset stat.mtime: ', stat.mtime); // console.info('asset stat.duration: ', duration); let pixelMap:image.PixelMap|undefined = undefined if(isLoadPixelMap){ //获取缩略图 if(Utility.isVideoByExtension(uri)){ pixelMap = await Utility.getFetchFrameByTime(uri) }else{ pixelMap = await Utility.getFetchMetadataFromFdSrcByPromise(uri) } } item = new VideoItem( file.name,uri ,uri,type,videoSize,cTime,pixelMap,fileSize, await ImageUtil.pixelMapToBase64Str(pixelMap)) }) } catch (error) { console.error('uriGetAssetsFromFile failed with err: ' + JSON.stringify(error)); } return item } static async getFilePixelMapBig(uri:string){ let pixelMap:image.PixelMap|undefined = undefined if(Utility.isMusicByExtension(uri)){ pixelMap = await Utility.getFetchMetadataFromFdSrcByPromise(uri) }else{ pixelMap = await Utility.getFetchFrameByTime(uri) } return ImageUtil.pixelMapToBase64StrBig(pixelMap) } static async getFilePixelMap(uri:string){ let pixelMap:image.PixelMap|undefined = undefined if(Utility.isMusicByExtension(uri)){ pixelMap = await Utility.getFetchMetadataFromFdSrcByPromise(uri) }else{ pixelMap = await Utility.getFetchFrameByTime(uri) } return ImageUtil.pixelMapToBase64Str(pixelMap) } //根据filePathe获取对应的播放Index static getIndexFromList(localList:Array,filePath:string){ let list: Array = []; for(let i=0;i { let cover: image.PixelMap | undefined = undefined; if (canIUse("SystemCapability.Multimedia.Media.AVMetadataExtractor")) { try { // 创建AVMetadataExtractor对象 const avMetadataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor(); // 设置fdSrc const fd = await fs.openSync(uri, fs.OpenMode.READ_ONLY); avMetadataExtractor.fdSrc = fd; // 获取元数据(promise模式) const metadata = await avMetadataExtractor.fetchMetadata(); metadata.author console.info(`get meta data, hasAudio: ${metadata.hasAudio}`); // 获取专辑封面(promise模式) cover = await avMetadataExtractor.fetchAlbumCover(); // 释放资源(promise模式) await avMetadataExtractor.release(); console.info('release success.'); } catch (error) { console.error('Error during metadata extraction:', error); } } else { console.warn('AVMetadataExtractor capability is not supported.'); } return cover; } static formatTimestamp(timestamp: number): string { // 将时间戳转换为 Date 对象 const date = new Date(timestamp); // 获取各个部分 const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,需要加1 const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); // 拼接成所需的格式 return `${year}-${month}-${day} ${hours}:${minutes}`; } //获取音乐资源的属性值, static async uriGetMusicAssetsFromFile(context:Context,uri:string,type:number,isLoadPixelMap?:boolean): Promise { let item:VideoItem = new VideoItem('',uri,uri,type,0,'') try { console.info('asset file.uri: ', uri); let file = fs.openSync(uri, fs.OpenMode.READ_ONLY | fs.OpenMode.CREATE) console.info("file.fd " + file.fd); let fdfd = 'fd://' + file.fd //3、通过fs.stat方法获取stat对象 console.info('asset file.name: ', file.name); console.info('asset file.uri: ', uri); console.info('asset file.fd: ', file.fd); console.info('asset file.path: ', file.path); item = new VideoItem(file.name,uri,uri,type,0,'') await fs.stat(file.fd).then(async (stat: fs.Stat) => { console.info("get file info succeed, the size of file is " + stat.size); let videoSize = stat.size // let videoTime = stat.ctime let fileSize = Utility.formatFSize(videoSize) //按照添加时间 let addTime = Utility.getFormatDateStr(new Date(),'yyyy-MM-dd HH:mm'); // console.info('onecold asset addTime: ', addTime); // let cTime = Utility.getFormatDateStr(stat.mtime,'yyyy-MM-dd HH:mm') // console.info('asset stat.ctime: ', stat.ctime); let musicName:string | undefined = file.name let artist:string | undefined = '' let album:string | undefined = '' let pixelMap:image.PixelMap|undefined|null = undefined let imagePath = '' let duration:string | undefined = '' let mimeType:string | undefined = '' let trackCount:string | undefined = ''//轨道数量 let sampleRate:string | undefined = ''//音频的采样率单位为Hz if (canIUse("SystemCapability.Multimedia.Media.AVMetadataExtractor")) { try { // 创建AVMetadataExtractor对象 const avMetadataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor(); // 设置fdSrc const fd = await fs.openSync(uri, fs.OpenMode.READ_ONLY); avMetadataExtractor.fdSrc = fd; // 获取元数据(promise模式) const metadata = await avMetadataExtractor.fetchMetadata(); if(StrUtil.isNotEmpty(metadata.title)){ musicName = metadata.title } if(musicName==undefined) musicName = file.name if(StrUtil.isNotEmpty(metadata.artist)){ artist = metadata.artist } if(artist==undefined) artist = '' if(StrUtil.isNotEmpty(metadata.album)){ album = metadata.album } if(StrUtil.isNotEmpty(metadata.duration)){ if(metadata.duration) duration = convertSecondsToTime(metadata.duration.toString()) } if(StrUtil.isNotEmpty(metadata.mimeType)){ mimeType = metadata.mimeType } if(StrUtil.isNotEmpty(metadata.trackCount)){ trackCount = metadata.trackCount } if(StrUtil.isNotEmpty(metadata.sampleRate)){ sampleRate = metadata.sampleRate } let name = await MD5.digestSync(uri) if(isLoadPixelMap){ // 获取专辑封面(promise模式) // pixelMap = await avMetadataExtractor.fetchAlbumCover(); // // 释放资源(promise模式) // await avMetadataExtractor.release(); pixelMap = await fetchAlbumCover(avMetadataExtractor) // console.info('onecold release success. name= '+musicName); if(pixelMap!==undefined&&pixelMap!==null){ console.info('onecold pixelMap is not empty= '+musicName); imagePath = await ImageUtil.savePixelMap(pixelMap,context.filesDir,name) imagePath = fileUri.getUriFromPath(imagePath) }else{ console.info('onecold pixelMap is empty= '+musicName); imagePath = '' // if(StrUtil.isNotEmpty(artist)) // imagePath = await NetAxiosUtil.getLyricCover(musicName,artist) } }else{ imagePath = context.filesDir + FileUtil.separator + name imagePath = fileUri.getUriFromPath(imagePath) } console.info('onecold release success. imagePath= '+imagePath); } catch (error) { console.error('Error during metadata extraction:', error); } } else { console.warn('AVMetadataExtractor capability is not supported.'); } if(musicName==undefined) musicName = file.name item = new VideoItem(musicName,uri ,uri,type,videoSize,addTime,undefined,fileSize, imagePath,artist,album,file.name) item.duration = duration+''; item.mimeType = mimeType; item.trackCount = trackCount; item.sampleRate = sampleRate; item.isFav = 0; item.playCount = 0; }) } catch (error) { console.error('uriGetAssetsFromFile failed with err: ' + JSON.stringify(error)); } return item } private completionNum(num: number): string | number { if (num < 10) { return '0' + num; } else { return num; } } //根据字节获取大小 static formatFSize(bytes:number):string { const units = ['Bytes', 'K', 'M', 'G']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } // 保留两位小数, 四舍五入 size = Math.round(size * 10) / 10; return size + units[unitIndex] } static gotoMarket(context:common.UIAbilityContext,bundleName:string) { const want: Want = { uri: `store://appgallery.huawei.com/app/detail?id=${bundleName}` }; context.startAbility(want).then(()=>{ //拉起成功 }).catch(()=>{ // 拉起失败 }); } static async doShare(item:VideoItem,context:common.UIAbilityContext){ // 生成视频封面图 const imagePackerApi: image.ImagePacker = image.createImagePacker(); const buffer: ArrayBuffer = await (imagePackerApi.packing(await Utility.getFetchFrameByTime(item.filePath), { format: 'image/jpeg', quality: 30 }) as Promise); // 构造ShareData,需配置一条有效数据信息 let shareData: systemShare.SharedData = new systemShare.SharedData({ utd: uniformTypeDescriptor.UniformDataType.MEDIA, uri: fileUri.getUriFromPath(item.filePath), title: item.name, // 不传title字段时,显示视频文件名 // description: '好听的音乐', // 不传description字段时,显示视频大小 thumbnail: new Uint8Array(buffer), // 优先使用传递的缩略图做预览 不传则默认使用视频第一帧画面做预览图 }); // 进行分享面板显示 let controller: systemShare.ShareController = new systemShare.ShareController(shareData); // let context = getContext(this) as common.UIAbilityContext; controller.show(context, { selectionMode: systemShare.SelectionMode.SINGLE, previewMode: systemShare.SharePreviewMode.DETAIL, }).then(() => { console.info('ShareController show success.'); }).catch((error: BusinessError) => { console.error(`ShareController show error. code: ${error.code}, message: ${error.message}`); }); } //分享索引index的视频 static async doShareMusic(item:VideoItem,context:common.UIAbilityContext){ // 构造ShareData,需配置一条有效数据信息 let shareData: systemShare.SharedData = new systemShare.SharedData({ utd: uniformTypeDescriptor.UniformDataType.AUDIO, uri: fileUri.getUriFromPath(item.filePath), title: item.name, // 不传title字段时,显示视频文件名 description: '好听的音乐', // 不传description字段时,显示视频大小 }); // 进行分享面板显示 let controller: systemShare.ShareController = new systemShare.ShareController(shareData); // let context = getContext(this) as common.UIAbilityContext; controller.show(context, { selectionMode: systemShare.SelectionMode.SINGLE, previewMode: systemShare.SharePreviewMode.DETAIL, }).then(() => { console.info('ShareController show success.'); }).catch((error: BusinessError) => { console.error(`ShareController show error. code: ${error.code}, message: ${error.message}`); }); } static getNameList(localList:Array){ let list: Array = []; for(let i=0;i,type:number){ let list: Array = []; for(let i=0;i,type:number){ let list: Array = []; for(let i=0;i,filePath:string){ let index: number = 0; for(let i=0;i,item:VideoItem|undefined){ if(ArrayUtil.isEmpty(favList)){ return false } if(item===undefined){ return false } for(let i=0;i,item:VideoItem|undefined){ if(ArrayUtil.isEmpty(facList)){ return false } if(item===undefined){ return false } for(let i=0;i,type:number){ let list: Array = []; for(let i=0;i { try { // 1. 同步化BundleInfo获取 const bundleInfo = await bundleManager.getBundleInfoForSelf( bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION ); // 2. 安全获取labelId(新增空值校验) const labelId = bundleInfo.appInfo?.labelId; if (!labelId || labelId <= 0) { throw new Error("Invalid labelId: " + labelId); } // 3. 异步资源解析(替换危险的getStringSync) return await context.resourceManager.getStringValue(labelId); } catch (err) { console.error(`[${new Date().toISOString()}] AppName Error: CODE=${err.code}, MSG=${err.message}`); // 4. 多级降级策略 return AppUtil.getBundleName() // 最终兜底 } } //按名称升序 static doSortListAscending( list:Array){ let options: Intl.CollatorOptions = { localeMatcher: "lookup", usage: "sort", sensitivity: "case" // 区分大小写 }; const collator = new Intl.Collator("zh-CN", options); list.sort((a, b) => { const typeOrder = getTypeOrder(a.type) - getTypeOrder(b.type); if (typeOrder !== 0) { return typeOrder; } const partsA = extractParts(a.name); const partsB = extractParts(b.name); const nonNumericComparison = collator.compare(partsA.nonNumeric, partsB.nonNumeric); if (nonNumericComparison !== 0) { return nonNumericComparison; } return partsA.numeric - partsB.numeric; }); } //按名称降序 static doSortListDescending(list:Array){ const options: Intl.CollatorOptions = { localeMatcher: "lookup", usage: "sort", sensitivity: "case" // 区分大小写 }; const collator = new Intl.Collator("zh-CN", options); list.sort((a, b) => { const typeOrder = getTypeOrder(a.type) - getTypeOrder(b.type); if (typeOrder !== 0) { return typeOrder; } const partsA = extractParts(a.name); const partsB = extractParts(b.name); const nonNumericComparison = collator.compare(partsB.nonNumeric, partsA.nonNumeric); if (nonNumericComparison !== 0) { return nonNumericComparison; } return partsB.numeric - partsA.numeric; }); } } interface PathStat { path: string; isDirectory: boolean; } async function isDirectory(filePath: string): Promise { try { const stat = await fs.stat(filePath); return stat.isDirectory(); } catch (error) { console.error('Error getting file stat:', error); return false; } } //排序模式参数 interface VideoNameParts { nonNumeric: string; numeric: number; } function extractParts(name: string): VideoNameParts { const match = name.match(/^(\D*)(\d*)/); return { nonNumeric: match?.[1] || '', numeric: parseInt(match?.[2] || '0', 10) }; } function getInstallTime(): number | null { // 从本地存储中获取安装时间 return PreferencesUtil.getNumberSync('installTime') } function setInstallTime(time: number) { // 将安装时间存储到本地存储中 PreferencesUtil.putSync('installTime',time) } function fetchAlbumCover(avMetadataExtractor: media.AVMetadataExtractor): Promise { return new Promise((resolve, reject) => { avMetadataExtractor.fetchAlbumCover((error: BusinessError, pixelMap: image.PixelMap) => { if (error) { console.error(`Failed to fetch AlbumCover, error = ${JSON.stringify(error)}`); resolve(null); } else { resolve(pixelMap); } avMetadataExtractor.release(); }); }); } //排序类型 function getTypeOrder(type: number) { switch (type) { case CommonConstants.TYPE_IS_DIR: return 1; // First case CommonConstants.TYPE_IS_CSJAD: return 2; // Middle case CommonConstants.TYPE_LOCAL: return 3; // Last default: return 4; // Unknown types, if any, go last } } function convertSecondsToTime(secondsStr: string): string { if (!secondsStr || isNaN(Number(secondsStr))) { return "00:00"; } let seconds = parseInt(secondsStr, 10); seconds = Math.floor(seconds / 1000); const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = seconds % 60; const formatNumber = (num: number) => num.toString().padStart(2, '0'); if (hours > 0) { return `${formatNumber(hours)}:${formatNumber(minutes)}:${formatNumber(secs)}`; } else { return `${formatNumber(minutes)}:${formatNumber(secs)}`; } }