| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244 |
- 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 '未知';
- }
- }
- //根据字节获取大小
- 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<VideoItem> {
- 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<photoAccessHelper.PhotoAsset> =
- 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<string, string>([
- ['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<VideoItem> {
- 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<VideoItem>,filePath:string){
- let list: Array<string> = [];
- for(let i=0;i<localList.length;i++){
- if(localList[i].filePath === filePath){
- return i
- }
- }
- return 0
- }
- // 在以下demo中,使用资源管理接口获取打包在HAP内的媒体资源文件,通过设置fdSrc属性,获取音频元数据并打印,
- // 获取音频专辑封面并通过Image控件显示在屏幕上。该demo以Promise形式进行异步接口调用
- static async getFetchMetadataFromFdSrcByPromise(uri: string): Promise<image.PixelMap | undefined> {
- 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<VideoItem> {
- 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)){
- duration = DateUtil.getFormatDateStr(metadata.duration,'HH:mm:ss')
- }
- 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
- }
- //根据字节获取大小
- 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<ArrayBuffer>);
- // 构造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<VideoItem>){
- let list: Array<string> = [];
- for(let i=0;i<localList.length;i++){
- if(StrUtil.isNotEmpty(localList[i].name))
- list.push(localList[i].name);
- }
- return list
- }
- //根据type获取对应的播放列表(CommonConstants.TYPE_LOCAL:本地,CommonConstants.TYPE_Dir:私密视频)
- static getGlobalNameList(localList:Array<VideoItem>,type:number){
- let list: Array<string> = [];
- for(let i=0;i<localList.length;i++){
- if(localList[i].type === type){
- list.push(localList[i].name);
- }
- }
- return list
- }
- //根据type获取对应的播放列表(CommonConstants.TYPE_LOCAL:本地,CommonConstants.TYPE_LOCK:私密视频)
- static getGlobalList(localList:Array<VideoItem>,type:number){
- let list: Array<VideoItem> = [];
- for(let i=0;i<localList.length;i++){
- if(localList[i].type === type){
- list.push(localList[i]);
- }
- }
- return list
- }
- //根据filePath获取当前索引index
- static getCurIndexFromGlobalList(localList:Array<VideoItem>,filePath:string){
- let index: number = 0;
- for(let i=0;i<localList.length;i++){
- if(localList[i].filePath === filePath){
- index = i
- return index
- }
- }
- return index
- }
- //新的查询是否收藏的方法
- static getIsFav(favList: Array<VideoItem>,item:VideoItem|undefined){
- if(ArrayUtil.isEmpty(favList)){
- return false
- }
- if(item===undefined){
- return false
- }
- for(let i=0;i<favList.length;i++){
- if(favList[i].filePath === item.filePath&&favList[i].isFav===1){
- return true
- }
- }
- return false
- }
- static getIsFac(facList: Array<String>,item:VideoItem|undefined){
- if(ArrayUtil.isEmpty(facList)){
- return false
- }
- if(item===undefined){
- return false
- }
- for(let i=0;i<facList.length;i++){
- if(facList[i] === item.name||facList[i]===item.fileName){
- return true
- }
- }
- return false
- }
- static resourceToString(context:Context,resource:Resource){
- if(!context||!resource)
- return ''
- return context.resourceManager.getStringSync(resource).toString()
- }
- //根据type获取对应的播放列表(CommonConstants.TYPE_LOCAL:本地,CommonConstants.TYPE_LOCK:私密视频)
- static getGlobalMusicList(localList:Array<VideoItem>,type:number){
- let list: Array<VideoItem> = [];
- for(let i=0;i<localList.length;i++){
- if(localList[i].type === type){
- list.push(localList[i]);
- }
- }
- return list
- }
- static isHaoFreeTime():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 >= 8 && a <13) {//白天
- return false;
- }
- if (a >= 13 && a <20) {//白天
- return false;
- }
- if (a >= 0 && a < 8) {//凌晨
- return true;
- }
- if (a >= 20 && a <= 24) {//晚上
- return true;
- }
- return false
- }
- static getMusisBg():Resource {
- let index = RandomUtil.randomNumber(0,9)
- LogUtil.info('getMusisBg index = '+index)
- return CommonConstants.musicBgList[index]
- }
- static getMusisBg2(index:number):Resource {
- const adjustedIndex = index % 10;
- LogUtil.info('getMusisBg adjustedIndex = '+adjustedIndex)
- return CommonConstants.musicBgList[adjustedIndex]
- }
- static getParentDirectory(filePath: string): string {
- // 使用正则表达式匹配路径分隔符(支持 Unix 和 Windows)
- const lastSlashIndex = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\'));
- if (lastSlashIndex === -1) {
- return '';
- }
- return filePath.substring(0, lastSlashIndex);
- }
- static getFileDirName(filePath: string,rootPath:string): string{
- if(filePath===rootPath){
- return '首页'
- }
- let result = FileUtil.getFileName(filePath)
- if(StrUtil.isEmpty(result))
- return ''
- if(result.startsWith('.'))
- result = result.replace(/\./g, '')
- return result
- }
- // 开启沉浸式显示模式
- static async enableFullScreen() {
- const ctx = getContext()
- const win = await window.getLastWindow(ctx)
- win.setWindowLayoutFullScreen(true)
- const top = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
- AppStorage.setOrCreate('topHeight', px2vp(top.topRect.height))
- AppStorage.setOrCreate('bottomHeight', px2vp(top.bottomRect.height))
- }
- // 关闭沉浸式显示模式
- static async disableFullScreen() {
- const ctx = getContext()
- const win = await window.getLastWindow(ctx)
- win.setWindowLayoutFullScreen(false)
- AppStorage.setOrCreate('topHeight', 0)
- AppStorage.setOrCreate('bottomHeight', 0)
- }
- // 设置状态栏文字颜色为白色
- static async setStatusBarLight() {
- const ctx = getContext()
- const win = await window.getLastWindow(ctx)
- win.setWindowSystemBarProperties({
- statusBarContentColor: '#ffffff'
- })
- }
- // 设置状态栏文字颜色为黑色
- static async setStatusBarDark() {
- const ctx = getContext()
- const win = await window.getLastWindow(ctx)
- win.setWindowSystemBarProperties({
- statusBarContentColor: '#000000'
- })
- }
- // 优化点:完全基于Promise链的异步处理
- static async getAppName(context: Context): Promise<string> {
- 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<VideoItem>){
- 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<VideoItem>){
- 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<boolean> {
- 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<image.PixelMap | null> {
- 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
- }
- }
|