1/* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { Log } from '../utils/Log'; 17import userFileManager from '@ohos.filemanagement.userFileManager'; 18import { Constants } from '../model/common/Constants'; 19import { TraceControllerUtils } from '../utils/TraceControllerUtils'; 20import dataSharePredicates from '@ohos.data.dataSharePredicates'; 21import { UiUtil } from '../utils/UiUtil'; 22import { AlbumDefine } from '../model/browser/AlbumDefine'; 23 24const TAG: string = 'common_UserFileManagerAccess'; 25 26export type UserFileManager = userFileManager.UserFileManager; 27 28export type FileType = userFileManager.FileType; 29 30export type FetchOptions = userFileManager.FetchOptions; 31 32export type FileAsset = userFileManager.FileAsset; 33 34export type MediaPeerInfo = userFileManager.PeerInfo; 35 36export type Album = userFileManager.Album; 37 38export type ImageVideoKey = userFileManager.ImageVideoKey; 39 40export type AlbumKey = userFileManager.AlbumKey; 41 42export type AlbumType = userFileManager.AlbumType; 43 44export type AlbumSubType = userFileManager.AlbumSubType; 45 46export type DefaultChangeUri = userFileManager.DefaultChangeUri; 47 48export type ChangeData = userFileManager.ChangeData; 49 50export type FileAssetEx = { 51 count: number; 52 obj: FileAsset; 53}; 54 55export class UserFileManagerAccess { 56 static readonly REGISTER_TYPE_IMAGE_CHANGE = 'imageChange'; 57 static readonly REGISTER_TYPE_VIDEO_CHANGE = 'videoChange'; 58 static readonly REGISTER_TYPE_DEVICE_CHANGE = 'deviceChange'; 59 static readonly REGISTER_TYPE_ALBUM_CHANGE = 'albumChange'; 60 static readonly REGISTER_TYPE_REMOTE_FILE_CHANGE = 'remoteFileChange'; 61 static readonly MEDIA_TYPE_IMAGE = userFileManager.FileType.IMAGE; 62 static readonly MEDIA_TYPE_VIDEO = userFileManager.FileType.VIDEO; 63 static readonly FILE_KEY_MEDIA_TYPE = userFileManager.ImageVideoKey.FILE_TYPE; 64 static readonly FILE_KEY_DISPLAY_NAME = userFileManager.ImageVideoKey.DISPLAY_NAME; 65 static readonly FILE_KEY_DATE_TAKEN = userFileManager.ImageVideoKey.DATE_ADDED; 66 static readonly FILE_KEY_DATE_TRASHED = userFileManager.ImageVideoKey.DATE_TRASHED; 67 static readonly FILE_KEY_TITLE = userFileManager.ImageVideoKey.TITLE; 68 69 static readonly REGISTER_TYPE_ALL_PHOTOS = "file://media/Photo"; 70 static readonly REGISTER_TYPE_ALL_ALBUMS = "file://media/PhotoAlbum"; 71 static readonly NOTIFY_ADD = userFileManager.NotifyType.NOTIFY_ADD; 72 static readonly NOTIFY_UPDATE = userFileManager.NotifyType.NOTIFY_UPDATE; 73 static readonly NOTIFY_REMOVE = userFileManager.NotifyType.NOTIFY_REMOVE; 74 static readonly NOTIFY_ALBUM_ADD_ASSET = userFileManager.NotifyType.NOTIFY_ALBUM_ADD_ASSET; 75 static readonly NOTIFY_ALBUM_REMOVE_ASSET = userFileManager.NotifyType.NOTIFY_ALBUM_REMOVE_ASSET; 76 77 static readonly ALL_IMAGE_VIDEO_FETCH_COLUMNS: Array<string> = [ 78 userFileManager.ImageVideoKey.URI.toString(), 79 userFileManager.ImageVideoKey.FILE_TYPE.toString(), 80 userFileManager.ImageVideoKey.DISPLAY_NAME.toString(), 81 userFileManager.ImageVideoKey.DATE_ADDED.toString(), 82 userFileManager.ImageVideoKey.DATE_MODIFIED.toString(), 83 userFileManager.ImageVideoKey.TITLE.toString(), 84 userFileManager.ImageVideoKey.DURATION.toString(), 85 userFileManager.ImageVideoKey.WIDTH.toString(), 86 userFileManager.ImageVideoKey.HEIGHT.toString(), 87 userFileManager.ImageVideoKey.DATE_TAKEN.toString(), 88 userFileManager.ImageVideoKey.ORIENTATION.toString(), 89 userFileManager.ImageVideoKey.FAVORITE.toString(), 90 userFileManager.ImageVideoKey.POSITION.toString(), 91 userFileManager.ImageVideoKey.DATE_TRASHED.toString(), 92 userFileManager.ImageVideoKey.HIDDEN.toString(), 93 "size" // TODO 等媒体库枚举字段上库 94 ] 95 96 static readonly GROUP_BY_KEY: string = 'count(*)'; 97 98 static readonly IMAGE_ALBUM_SUB_TYPE: AlbumSubType = 1031; // TODO 等媒体库枚举字段上库 99 static readonly CAMERA_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.CAMERA; 100 static readonly FAVORITE_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.FAVORITE; 101 static readonly VIDEO_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.VIDEO; 102 static readonly TRASH_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.TRASH; 103 static readonly SCREENSHOT_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.SCREENSHOT; 104 static readonly HIDDEN_ALBUM_SUB_TYPE: AlbumSubType = userFileManager.AlbumSubType.HIDDEN; 105 106 static readonly ALL_SYSTEM_ALBUM_LIST: Array<AlbumSubType> = [ 107 UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE, 108 UserFileManagerAccess.VIDEO_ALBUM_SUB_TYPE, 109 UserFileManagerAccess.SCREENSHOT_ALBUM_SUB_TYPE, 110 UserFileManagerAccess.FAVORITE_ALBUM_SUB_TYPE, 111 UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE, 112 UserFileManagerAccess.HIDDEN_ALBUM_SUB_TYPE, 113 UserFileManagerAccess.FAVORITE_ALBUM_SUB_TYPE, 114 ] 115 116 static readonly SYSTEM_BEFORE_USER_ALBUM_LIST: Array<AlbumSubType> = [ 117 UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE, 118 UserFileManagerAccess.VIDEO_ALBUM_SUB_TYPE, 119 UserFileManagerAccess.SCREENSHOT_ALBUM_SUB_TYPE, 120 UserFileManagerAccess.FAVORITE_ALBUM_SUB_TYPE 121 ] 122 123 static readonly SYSTEM_AFTER_USER_ALBUM_LIST: Array<AlbumSubType> = [ 124 UserFileManagerAccess.HIDDEN_ALBUM_SUB_TYPE, 125 UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE 126 ] 127 128 private media: userFileManager.UserFileManager = null; 129 private requestTime: number; 130 131 private systemAlbumUriMap: Map<AlbumSubType, string> = new Map<AlbumSubType, string>(); 132 133 constructor() { 134 this.requestTime = Date.now(); 135 } 136 137 public static getInstance(): UserFileManagerAccess { 138 if (AppStorage.Get(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS) == null) { 139 AppStorage.SetOrCreate(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS, new UserFileManagerAccess()); 140 } 141 return AppStorage.Get(Constants.APP_KEY_INSTANCE_MEDIA_LIBRARY_ACCESS); 142 } 143 144 onCreate(context) { 145 Log.debug(TAG, `Photos_UserFileManagerAccess onCreate ${context}`); 146 if (this.media) { 147 Log.debug(TAG, `Photos_UserFileManagerAccess onCreate already`); 148 return; 149 } 150 this.media = userFileManager.getUserFileMgr(context); 151 Log.debug(TAG, 'Photos_UserFileManagerAccess onCreate end'); 152 if (!this.media) { 153 Log.error(TAG, 'get media library instance failed!'); 154 } 155 Log.info(TAG, 'onCreate done'); 156 } 157 158 onDestroy() { 159 try { 160 this.media && this.media.release(); 161 this.media = null; 162 Log.info(TAG, 'onDestroy done'); 163 } catch (err) { 164 Log.error(TAG, `onDestroy error: ${err}`); 165 } 166 } 167 168 getMediaLibrary(): userFileManager.UserFileManager { 169 return this.media; 170 } 171 172 getSystemAlbumUriMap() { 173 return this.systemAlbumUriMap; 174 } 175 176 async getAllObject(fetchOpt: FetchOptions): Promise<Array<FileAsset>> { 177 Log.info(TAG, `getAllObject: ${JSON.stringify(fetchOpt)}`); 178 if (!this.media) { 179 Log.error(TAG, '[getAllObject] media resource is null!'); 180 return []; 181 } 182 try { 183 TraceControllerUtils.startTraceWithTaskId('getAllObject', this.requestTime); 184 let dataList = await this.media.getPhotoAssets(fetchOpt); 185 if (!dataList) { 186 Log.warn(TAG, 'get all Object Data with empty dataList'); 187 return []; 188 } 189 Log.debug(TAG, `get all Object Data raw data size: ${dataList.getCount()}`); 190 if (dataList.getCount() <= 0) { 191 dataList.close(); 192 return []; 193 } 194 195 let result = await dataList.getAllObject(); 196 dataList.close(); 197 TraceControllerUtils.finishTraceWithTaskId('getAllObject', this.requestTime); 198 return result; 199 } catch (error) { 200 Log.error(TAG, `getAllObject error: ${error}`); 201 return []; 202 } 203 } 204 205 async deleteAlbumByUri(uri: string): Promise<void> { 206 if (!this.media) { 207 Log.error(TAG, '[deleteAlbum] media resource is null!'); 208 return; 209 } 210 try { 211 Log.debug(TAG, `deleteAlbumByUri uri is ` + uri); 212 let album = await this.getAlbumByUri(uri); 213 await this.media.deleteAlbums([album]); // TODO 接口支持批量删除,传参后续整改 214 } catch (error) { 215 Log.error(TAG, `deleteAlbumByUri error: ${error}`); 216 return; 217 } 218 } 219 220 async getCount(fetchOpt: FetchOptions): Promise<number> { 221 Log.info(TAG, `getCount: ${JSON.stringify(fetchOpt)}`); 222 if (!this.media) { 223 Log.error(TAG, '[getCount] media resource is null!'); 224 return 0; 225 } 226 try { 227 TraceControllerUtils.startTraceWithTaskId('getCount', this.requestTime); 228 let dataList = await this.media.getPhotoAssets(fetchOpt); 229 if (!dataList) { 230 Log.warn(TAG, 'get count dataList is 0'); 231 return 0; 232 } 233 Log.debug(TAG, `get count raw data size: ${dataList.getCount()}`); 234 let result = dataList.getCount(); 235 dataList.close(); 236 TraceControllerUtils.finishTraceWithTaskId('getCount', this.requestTime); 237 return result; 238 } catch (error) { 239 Log.error(TAG, `get Count error: ${error}`); 240 return 0; 241 } 242 } 243 244 async getObject(fetchOpt: FetchOptions): Promise<FileAsset> { 245 Log.info(TAG, `getObject: ${JSON.stringify(fetchOpt)}`); 246 if (!this.media) { 247 Log.error(TAG, '[getObject] media resource is null!'); 248 return undefined; 249 } 250 try { 251 TraceControllerUtils.startTraceWithTaskId('getObject', this.requestTime); 252 let fileResult = await this.media.getPhotoAssets(fetchOpt); 253 if (fileResult) { 254 Log.info(TAG, `getObject count is ${fileResult.getCount()}`); 255 if (fileResult.getCount() <= 0) { 256 fileResult.close(); 257 return undefined; 258 } 259 let file = await fileResult.getFirstObject(); 260 fileResult.close(); 261 if (file) { 262 return file; 263 } else { 264 Log.error(TAG, 'Failed getObject'); 265 } 266 } 267 TraceControllerUtils.finishTraceWithTaskId('getObject', this.requestTime); 268 return undefined; 269 } catch (error) { 270 Log.error(TAG, `getObject loadData error: ${error}`); 271 return undefined; 272 } 273 } 274 275 async getFirstObject(fetchOpt: FetchOptions): Promise<FileAssetEx> { 276 let result = { 277 count: 0, 278 obj: null 279 } 280 Log.info(TAG, `getFirstObject: ${JSON.stringify(fetchOpt)}`); 281 if (!this.media) { 282 Log.error(TAG, '[getFirstObject] media resource is null!'); 283 return result; 284 } 285 try { 286 TraceControllerUtils.startTraceWithTaskId('getFirstObject', this.requestTime); 287 let fileResult = await this.media.getPhotoAssets(fetchOpt); 288 if (fileResult) { 289 result.count = fileResult.getCount(); 290 Log.info(TAG, `getFirstObject count is ${result.count}`); 291 if (result.count <= 0) { 292 fileResult.close(); 293 return result; 294 } 295 let file = await fileResult.getFirstObject(); 296 fileResult.close(); 297 if (file) { 298 result.obj = file; 299 return result; 300 } else { 301 Log.error(TAG, 'Failed getFirstObject'); 302 } 303 } 304 TraceControllerUtils.finishTraceWithTaskId('getFirstObject', this.requestTime); 305 return result; 306 } catch (error) { 307 Log.error(TAG, `getFirstObject loadData error: ${error}`); 308 return result; 309 } 310 } 311 312 async deleteAlbumPhotos(uri: String): Promise<void> { 313 Log.debug(TAG, `deleteAsset uri: ${uri}`); 314 if (!this.media) { 315 Log.error(TAG, '[deleteAsset] media resource is null!'); 316 return; 317 } 318 319 // 获取回收站内的文件 320 let predicates = new dataSharePredicates.DataSharePredicates(); 321 let fetchOptions = { 322 fetchColumns: [], 323 predicates: predicates 324 }; 325 326 try { 327 const fetchResult = await this.media.getPhotoAssets(fetchOptions); 328 var asset = await fetchResult.getFirstObject(); 329 } catch (err) { 330 console.info('fetch failed, message =', err); 331 } 332 333 if (asset == undefined) { 334 console.error('asset not exist'); 335 return; 336 } 337 try { 338 await this.media.delete(asset.uri); 339 console.info("delete successfully"); 340 } catch (err) { 341 console.error("delete failed with error: " + err); 342 } 343 } 344 345 async createAsset(mediaType: FileType, displayName: string): Promise<FileAsset> { 346 Log.debug(TAG, 'createAsset start'); 347 if (!this.media) { 348 Log.error(TAG, '[createAsset] media resource is null!'); 349 return null; 350 } 351 Log.info(TAG, `createAsset ${mediaType} ${displayName} `); 352 let fileAsset = await this.media.createPhotoAsset(displayName); 353 Log.debug(TAG, `createAsset end. new fileAsset: ${fileAsset}`); 354 if (!fileAsset) { 355 Log.error(TAG, 'createAsset Fail'); 356 return null; 357 } 358 return fileAsset; 359 } 360 361 async openAsset(mode: string, fileAsset: FileAsset): Promise<number> { 362 Log.debug(TAG, 'openAsset start'); 363 if (!fileAsset) { 364 Log.error(TAG, 'fileAsset is null'); 365 return; 366 } 367 let fd = await fileAsset.open(mode); 368 Log.info(TAG, `openAsset end. fd: ${fd}`); 369 if (fd <= 0) { 370 Log.error(TAG, 'openAsset Fail'); 371 return; 372 } 373 return fd; 374 } 375 376 async closeAsset(fd: number, fileAsset: FileAsset): Promise<void> { 377 Log.debug(TAG, 'closeAsset start'); 378 if (!fileAsset) { 379 Log.error(TAG, 'fileAsset is null'); 380 return; 381 } 382 try { 383 await fileAsset.close(fd); 384 } catch (err) { 385 Log.error(TAG, 'file asset close error: ' + JSON.stringify(err)); 386 } 387 } 388 389 async deleteToTrash(uri: string): Promise<void> { 390 Log.debug(TAG, 'trashAsset start'); 391 await this.media.delete(uri); 392 } 393 394 async deleteFromTrash(assets: Array<FileAsset>): Promise<void> { 395 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.TRASH); 396 let trashAlbum = await fetchResult.getFirstObject(); 397 await trashAlbum.deletePhotoAssets(assets); 398 fetchResult.close(); 399 } 400 401 async recoverFromTrash(assets: Array<FileAsset>): Promise<void> { 402 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.TRASH); 403 let trashAlbum = await fetchResult.getFirstObject(); 404 await trashAlbum.recoverPhotoAssets(assets); 405 fetchResult.close(); 406 } 407 408 async getTrashAssetByUri(assetUri: string): Promise<FileAsset> { 409 Log.info(TAG, "getTrashAssetByUri"); 410 let trashAlbumResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.TRASH); 411 let trashAlbum = await trashAlbumResult.getFirstObject(); 412 let predicates = new dataSharePredicates.DataSharePredicates(); 413 predicates.equalTo(userFileManager.ImageVideoKey.URI.toString(), assetUri); 414 let fetchOption: userFileManager.FetchOptions = { 415 predicates: predicates, 416 fetchColumns: [] 417 }; 418 fetchOption.fetchColumns = Array.prototype.slice.call(UserFileManagerAccess.ALL_IMAGE_VIDEO_FETCH_COLUMNS); 419 let fetchResult = await trashAlbum.getPhotoAssets(fetchOption); 420 let assets = await fetchResult.getFirstObject(); 421 fetchResult.close(); 422 trashAlbumResult.close(); 423 return assets; 424 } 425 426 async getFavoriteObject(fetchOpt: FetchOptions): Promise<Array<FileAsset>> { 427 if (!this.media) { 428 Log.error(TAG, '[getFavoriteObject] media resource is null!'); 429 return []; 430 } 431 try { 432 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.FAVORITE); 433 let favoriteAlbum = await fetchResult.getFirstObject(); 434 let fileFetchResult = await favoriteAlbum.getPhotoAssets(fetchOpt) 435 Log.info(TAG, `[getFavoriteObject] get smart albums length:${fileFetchResult.getCount()} name:${favoriteAlbum.albumName}`); 436 Log.debug(TAG, `[getFavoriteObject] object count :${fileFetchResult.getCount()}`); 437 let objects = await fileFetchResult.getAllObject(); 438 Log.debug(TAG, `[getFavoriteObject] objects done`); 439 fileFetchResult.close(); 440 fetchResult.close(); 441 return objects; 442 } catch (err) { 443 Log.error(TAG, `Get favorite object exception! msg: ${err}`); 444 return []; 445 } 446 } 447 448 async getTrashObject(fetchOpt: FetchOptions): Promise<Array<FileAsset>> { 449 Log.info(TAG, `Get trash object: ${JSON.stringify(fetchOpt)}`); 450 if (!this.media) { 451 Log.error(TAG, '[getTrashObject] media resource is null!'); 452 return []; 453 } 454 try { 455 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.TRASH); 456 let trashAlbum = await fetchResult.getFirstObject(); 457 let fileFetchResult = await trashAlbum.getPhotoAssets(fetchOpt) 458 Log.debug(TAG, `[getTrashObject] object count :${fileFetchResult.getCount()}`); 459 let objects = await fileFetchResult.getAllObject(); 460 Log.debug(TAG, `[getTrashObject] get objects done`); 461 fileFetchResult.close(); 462 fetchResult.close(); 463 return objects; 464 } catch (err) { 465 Log.error(TAG, `Get Trash Object exception! msg: ${err}`); 466 return []; 467 } 468 } 469 470 async getUserAlbumObject(fetchOpt: FetchOptions, fileFetchOpt: FetchOptions): Promise<Array<FileAsset>> { 471 Log.info(TAG, `getEntityAlbumObject opt${JSON.stringify(fetchOpt)} fileOpt${JSON.stringify(fileFetchOpt)}`); 472 if (!this.media) { 473 Log.error(TAG, '[getEntityAlbumObject] media resource is null!'); 474 return []; 475 } 476 try { 477 // 按照fetchOpt获取用户指定的相册---游标 478 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.USER, userFileManager.AlbumSubType.USER_GENERIC, fetchOpt); 479 480 //获取所有的相册的 481 let albums = await fetchResult.getAllObject(); 482 if (albums.length === 0) { 483 return []; 484 } 485 let objects = []; 486 for (let i = 0; i < albums.length; i++) { 487 let album = albums[i]; 488 Log.debug(TAG, `[getEntityAlbumObject]Albums name:${album.albumName} index: ${i}`); 489 // 返回一个游标 490 let fileResult = await album.getPhotoAssets(fileFetchOpt); 491 Log.debug(TAG, `[getEntityAlbumObject]objects count :${fileResult.getCount()}`); 492 if (fileResult.getCount() <= 0) { 493 fileResult.close(); 494 continue; 495 } 496 //获取该album游标下的所有资源 497 objects = await fileResult.getAllObject(); 498 Log.debug(TAG, `[getEntityAlbumObject]Get objects done`); 499 fileResult.close(); 500 } 501 fetchResult.close(); 502 return objects; 503 } catch (err) { 504 Log.error(TAG, `Get Entity Album Object exception! msg: ${err}`); 505 return []; 506 } 507 } 508 509 async getFavoriteCount(favoriteFetchOpt: FetchOptions): Promise<number> { 510 Log.info(TAG, `[getFavoriteCount] FetchOptions: ${JSON.stringify(favoriteFetchOpt)}`); 511 return await this.getSystemAlbumCount(favoriteFetchOpt, userFileManager.AlbumSubType.FAVORITE); 512 } 513 514 async getTrashCount(trashFetchOpt: FetchOptions): Promise<number> { 515 Log.info(TAG, `[getTrashCount] FetchOptions: ${JSON.stringify(trashFetchOpt)}`); 516 return await this.getSystemAlbumCount(trashFetchOpt, userFileManager.AlbumSubType.TRASH); 517 } 518 519 async getSystemAlbumCount(fetchOpt: FetchOptions, albumSubType: userFileManager.AlbumSubType): Promise<number> { 520 Log.info(TAG, `[getTrashCount] FetchOptions: ${JSON.stringify(fetchOpt)}`); 521 if (!this.media) { 522 Log.error(TAG, '[getTrashCount] media resource is null!'); 523 return 0; 524 } 525 try { 526 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, albumSubType); 527 let systemAlbum = await fetchResult.getFirstObject(); 528 let fileFetchResult = await systemAlbum.getPhotoAssets(fetchOpt) 529 let count = fileFetchResult.getCount(); 530 fileFetchResult.close(); 531 fetchResult.close(); 532 return count; 533 } catch (err) { 534 Log.error(TAG, `Get Trash count exception! msg: ${err}`); 535 return 0; 536 } 537 } 538 539 async getAlbumFirstObject(album: Album): Promise<FileAsset> { 540 Log.info(TAG, `[getAlbumFirstObject]`); 541 if (!this.media) { 542 Log.error(TAG, '[getAlbumFirstObject] media resource is null!'); 543 return undefined; 544 } 545 try { 546 let opt = AlbumDefine.getFileFetchOpt(0, 1); 547 let fetchResult = await album.getPhotoAssets(opt); 548 if (!fetchResult) { 549 Log.error(TAG, 'fetchResult is null'); 550 } 551 let fileAsset = await fetchResult.getFirstObject(); 552 fetchResult.close(); 553 Log.info(TAG, `cover uri ${fileAsset.uri}`); 554 return fileAsset; 555 } catch (err) { 556 Log.error(TAG, `Get album first obj exception! msg: ${err}`); 557 return undefined; 558 } 559 } 560 561 async getUserAlbumCount(albumFetchOpt: FetchOptions, fileFetchOpt?: FetchOptions): Promise<number> { 562 Log.info(TAG, `getUSerAlbumCount FetchOptions: ${JSON.stringify(albumFetchOpt)}`); 563 if (!this.media) { 564 Log.error(TAG, '[getTrashCount] media resource is null!'); 565 return 0; 566 } 567 try { 568 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.USER, userFileManager.AlbumSubType.USER_GENERIC, albumFetchOpt); 569 let userAlbum = await fetchResult.getFirstObject(); 570 let fileFetchResult = await userAlbum.getPhotoAssets(fileFetchOpt); 571 let count = fileFetchResult.getCount(); 572 fileFetchResult.close(); 573 fetchResult.close(); 574 return count; 575 } catch (err) { 576 Log.error(TAG, `Get Trash count exception! msg: ${err}`); 577 return 0; 578 } 579 } 580 581 async getUserAlbums(fetchOpt?: FetchOptions): Promise<Array<Album>> { 582 Log.info(TAG, `getUserAlbums start}`); 583 if (!this.media) { 584 Log.error(TAG, '[getUserAlbums] media resource is null!'); 585 return []; 586 } 587 try { 588 let fetchResult; 589 if (fetchOpt) { 590 fetchResult = await this.media.getAlbums(userFileManager.AlbumType.USER, userFileManager.AlbumSubType.USER_GENERIC, fetchOpt); 591 } else { 592 fetchResult = await this.media.getAlbums(userFileManager.AlbumType.USER, userFileManager.AlbumSubType.USER_GENERIC); 593 } 594 let userAlbums = await fetchResult.getAllObject(); 595 Log.info(TAG, `[getUserAlbums]length :${userAlbums.length}`); 596 fetchResult.close(); 597 return userAlbums; 598 } catch (err) { 599 Log.error(TAG, `Get User Album exception! msg: ${err}`); 600 return []; 601 } 602 } 603 604 async prepareSystemAlbums(): Promise<void> { 605 if (!this.media) { 606 Log.error(TAG, 'prepareSystemAlbums media resource is null!'); 607 return; 608 } 609 try { 610 for (let i = 0; i < UserFileManagerAccess.SYSTEM_BEFORE_USER_ALBUM_LIST.length; i++) { 611 let albumSubType = UserFileManagerAccess.SYSTEM_BEFORE_USER_ALBUM_LIST[i]; 612 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, albumSubType); 613 let systemAlbum = await fetchResult.getFirstObject(); 614 this.systemAlbumUriMap.set(albumSubType, systemAlbum.albumUri); 615 Log.info(TAG, `prepareSystemAlbums before :${systemAlbum.albumUri}, ${albumSubType}`); 616 fetchResult.close(); 617 } 618 for (let i = 0; i < UserFileManagerAccess.SYSTEM_AFTER_USER_ALBUM_LIST.length; i++) { 619 let albumSubType = UserFileManagerAccess.SYSTEM_AFTER_USER_ALBUM_LIST[i]; 620 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, albumSubType); 621 let systemAlbum = await fetchResult.getFirstObject(); 622 this.systemAlbumUriMap.set(albumSubType, systemAlbum.albumUri); 623 Log.info(TAG, `prepareSystemAlbums after :${systemAlbum.albumUri}, ${albumSubType}`); 624 fetchResult.close(); 625 } 626 return; 627 } catch (err) { 628 Log.error(TAG, `prepareSystemAlbums Get System Album exception! msg: ${err}`); 629 return; 630 } 631 } 632 633 async getSystemAlbums(): Promise<Array<Album>> { 634 if (!this.media) { 635 Log.error(TAG, 'getSystemAlbums media resource is null!'); 636 return undefined; 637 } 638 try { 639 let systemAlbumList: Array<Album> = []; 640 for (let i = 0; i < UserFileManagerAccess.SYSTEM_BEFORE_USER_ALBUM_LIST.length; i++) { 641 let albumSubType = UserFileManagerAccess.SYSTEM_BEFORE_USER_ALBUM_LIST[i]; 642 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, albumSubType); 643 let systemAlbum = await fetchResult.getFirstObject(); 644 this.systemAlbumUriMap.set(albumSubType, systemAlbum.albumUri); 645 systemAlbumList.push(systemAlbum); 646 Log.info(TAG, `getSystemAlbums :${systemAlbum.albumUri}`); 647 fetchResult.close(); 648 } 649 return systemAlbumList; 650 } catch (err) { 651 Log.error(TAG, `getSystemAlbums Get System Album exception! msg: ${err}`); 652 return undefined; 653 } 654 } 655 656 async getTrashAlbum(): Promise<Album> { 657 if (!this.media) { 658 Log.error(TAG, 'getTrashAlbum media resource is null!'); 659 return undefined; 660 } 661 try { 662 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.TRASH); 663 let trashAlbum: Album = await fetchResult.getFirstObject(); 664 this.systemAlbumUriMap.set(UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE, trashAlbum.albumUri); 665 Log.info(TAG, `getTrashAlbum : ${trashAlbum.albumUri}`); 666 fetchResult.close(); 667 return trashAlbum; 668 } catch (err) { 669 Log.error(TAG, `getTrashAlbum Get Trash Album exception! msg: ${err}`); 670 return undefined; 671 } 672 } 673 674 async getHiddenAlbum(): Promise<Album> { 675 if (!this.media) { 676 Log.error(TAG, 'getHiddenAlbum media resource is null!'); 677 return undefined; 678 } 679 try { 680 let fetchResult = await this.media.getAlbums(userFileManager.AlbumType.SYSTEM, userFileManager.AlbumSubType.HIDDEN); 681 let hiddenAlbum: Album = await fetchResult.getFirstObject(); 682 Log.info(TAG, `getHiddenAlbum : ${hiddenAlbum.albumUri}`); 683 fetchResult.close(); 684 return hiddenAlbum; 685 } catch (err) { 686 Log.error(TAG, `getHiddenAlbum Get Hidden Album exception! msg: ${err}`); 687 return undefined; 688 } 689 } 690 691 async addFileToAlbum(albumUri: string, sourceAsset: FileAsset) { 692 if (!this.media) { 693 Log.error(TAG, '[getHiddenAlbum] media resource is null!'); 694 return undefined; 695 } 696 Log.debug(TAG, `addFileToAlbum albumUri is ` + albumUri + ` sourceAsset is ` + sourceAsset); 697 let album = await this.getAlbumByUri(albumUri); 698 await album.addPhotoAssets([sourceAsset]); // TODO 媒体库支持批量添加,传参后续整改 699 } 700 701 isImage(fileAsset: FileAsset): boolean { 702 return fileAsset.fileType === userFileManager.FileType.IMAGE; 703 } 704 705 isSystemAlbum(album: Album): boolean { 706 return album.albumType === userFileManager.AlbumType.SYSTEM; 707 } 708 709 isTrashAlbum(album: Album): boolean { 710 return album.albumSubType === userFileManager.AlbumSubType.TRASH; 711 } 712 713 isScreenShotAlbum(album: Album): boolean { 714 return album.albumSubType === userFileManager.AlbumSubType.SCREENSHOT; 715 } 716 717 isPhotoAlbum(album: Album): boolean { 718 return album.albumSubType === UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE; 719 } 720 721 isVideoAlbum(album: Album): boolean { 722 return album.albumSubType === userFileManager.AlbumSubType.VIDEO; 723 } 724 725 isFavorAlbum(album: Album): boolean { 726 return album.albumSubType === userFileManager.AlbumSubType.FAVORITE; 727 } 728 729 async getAlbumName(album: Album): Promise<string> { 730 if (this.isSystemAlbum(album)) { 731 // 系统相册,图库自己命名 732 switch (album.albumSubType) { 733 case UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE: 734 return await UiUtil.getResourceString($r('app.string.album_photos')); 735 case UserFileManagerAccess.FAVORITE_ALBUM_SUB_TYPE: 736 return await UiUtil.getResourceString($r('app.string.album_favor')); 737 case UserFileManagerAccess.VIDEO_ALBUM_SUB_TYPE: 738 return await UiUtil.getResourceString($r('app.string.album_video')); 739 case UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE: 740 return await UiUtil.getResourceString($r('app.string.album_recycle')); 741 case UserFileManagerAccess.SCREENSHOT_ALBUM_SUB_TYPE: 742 return await UiUtil.getResourceString($r('app.string.album_screen_shot')); 743 default: 744 return ''; 745 } 746 } 747 // 用户相册,直接返回 748 return album.albumName; 749 } 750 751 getAlbumDateModified(album: Album): number { 752 return album.dateModified; 753 } 754 755 /** 756 * 根据Uri获取相册,不区分系统相册和用户相册 757 * @param albumUri 相册Uri 758 * @returns 目标相册 759 */ 760 async getAlbumByUri(albumUri: string): Promise<Album> { 761 Log.debug(TAG, 'getAlbumByUri albumUri is ' + albumUri); 762 if (!this.media) { 763 Log.error(TAG, 'getAlbumByUri media resource is null!'); 764 return undefined; 765 } 766 try { 767 let albumFetchOpt = AlbumDefine.getAlbumFetchOptByUri(albumUri); 768 // @ts-ignore // TODO 支持不传入type时删掉 ts-ignore 769 let fetchResult = await this.media.getAlbums(albumFetchOpt); 770 if (!fetchResult) { 771 Log.warn(TAG, 'getAlbumByUri return null'); 772 return undefined; 773 } 774 Log.debug(TAG, `getAlbumByUri return raw data size: ${fetchResult.getCount()}`); 775 if (fetchResult.getCount() <= 0) { 776 fetchResult.close(); 777 return undefined; 778 } 779 let album = await fetchResult.getFirstObject(); 780 if (!album) { 781 Log.warn(TAG, `getAlbumByUri result is null`); 782 } 783 fetchResult.close(); 784 return album; 785 } catch (err) { 786 Log.error(TAG, `getAlbumByUri Get Album by uri exception! msg: ${err}`); 787 return undefined; 788 } 789 } 790 791 async getAlbumByName(albumName: string): Promise<Album> { 792 if (!this.media) { 793 Log.error(TAG, 'getAlbumByName media resource is null!'); 794 return undefined; 795 } 796 try { 797 Log.info(TAG, `getAlbumByName name: ${albumName}`); 798 let albumFetchOpt = AlbumDefine.getAlbumFetchOptByName(albumName); 799 // @ts-ignore // TODO 需要媒体库新开接口,支持仅传入fetchOpt 800 let fetchResult = await this.media.getAlbums(albumFetchOpt); 801 if (!fetchResult) { 802 Log.error(TAG, 'getAlbumByName fetchResult undefined') 803 return undefined; 804 } 805 if (fetchResult.getCount() <= 0) { 806 fetchResult.close(); 807 return undefined; 808 } 809 let album = await fetchResult.getFirstObject(); 810 if (!album) { 811 Log.error(TAG, 'getAlbumByName album undefined') 812 return undefined; 813 } 814 Log.info(TAG, `getAlbumByName get album success ${JSON.stringify(album)}`) 815 fetchResult.close(); 816 return album; 817 } catch (err) { 818 Log.error(TAG, `getAlbumByName exception! msg: ${err}`); 819 return undefined; 820 } 821 } 822 823 getSystemAlbumUri(subType: userFileManager.AlbumSubType): string { 824 Log.debug(TAG, `getSystemAlbumUri subType: ${subType}`); 825 let uri = this.systemAlbumUriMap.get(subType); 826 Log.debug(TAG, `getSystemAlbumUri uri: ${uri}`); 827 return uri; 828 } 829 830 async createUserAlbum(albumName: string): Promise<Album> { 831 let album: Album = undefined; 832 try { 833 album = await this.media.createAlbum(albumName); 834 } catch (error) { 835 Log.error(TAG, `deleteAlbumByUri error: ${error}`); 836 } 837 return album; 838 } 839 840 async renameAlbum(album: Album, name: string): Promise<void> { 841 if (!this.media) { 842 Log.error(TAG, '[renameAlbum] media resource is null!'); 843 return; 844 } 845 try { 846 album.albumName = name; 847 album.commitModify(); 848 } catch (err) { 849 Log.error(TAG, `Rename Album exception! msg: ${err}`); 850 return; 851 } 852 } 853 854 // 判断当前图库是否有相同名字的系统相册,跟随多语言变化 855 async isAlbumNameExistInSystemAlbums(name: string): Promise<boolean> { 856 for (let i = 0; i < UserFileManagerAccess.ALL_SYSTEM_ALBUM_LIST.length; i++) { 857 let systemAlbumName: string; 858 switch (UserFileManagerAccess.ALL_SYSTEM_ALBUM_LIST[i]) { 859 case UserFileManagerAccess.IMAGE_ALBUM_SUB_TYPE: 860 systemAlbumName = await UiUtil.getResourceString($r('app.string.album_photos')); 861 break; 862 case UserFileManagerAccess.FAVORITE_ALBUM_SUB_TYPE: 863 systemAlbumName = await UiUtil.getResourceString($r('app.string.album_favor')); 864 break; 865 case UserFileManagerAccess.VIDEO_ALBUM_SUB_TYPE: 866 systemAlbumName = await UiUtil.getResourceString($r('app.string.album_video')); 867 break; 868 case UserFileManagerAccess.TRASH_ALBUM_SUB_TYPE: 869 systemAlbumName = await UiUtil.getResourceString($r('app.string.album_recycle')); 870 break; 871 case UserFileManagerAccess.SCREENSHOT_ALBUM_SUB_TYPE: 872 systemAlbumName = await UiUtil.getResourceString($r('app.string.album_screen_shot')); 873 break; 874 default: 875 break; 876 } 877 if (systemAlbumName === name) { 878 return true; 879 } 880 } 881 return false; 882 } 883} 884 885/** 886 * 文件fetchOption 887 */ 888export class FileFetchOptionBuilder { 889 private fetchOption: userFileManager.FetchOptions = { 890 predicates: new dataSharePredicates.DataSharePredicates(), 891 fetchColumns: [] 892 }; 893 894 constructor(fetchOpt?) { 895 if (fetchOpt) { 896 this.fetchOption = fetchOpt; 897 } 898 this.fetchOption.fetchColumns = Array.prototype.slice.call(UserFileManagerAccess.ALL_IMAGE_VIDEO_FETCH_COLUMNS) // 暂时获取所有columns 899 } 900 901 build(): FetchOptions { 902 return this.fetchOption; 903 } 904 905 // 用于timeline分组查询 906 groupBy(): FileFetchOptionBuilder { 907 this.fetchOption.fetchColumns.push(UserFileManagerAccess.GROUP_BY_KEY); 908 return this; 909 } 910 911 media(mediaType: string): FileFetchOptionBuilder { 912 this.fetchOption.predicates.equalTo(userFileManager.ImageVideoKey.FILE_TYPE.toString(), mediaType) 913 return this; 914 } 915 916 uri(uri: string): FileFetchOptionBuilder { 917 this.fetchOption.predicates.equalTo(userFileManager.ImageVideoKey.URI.toString(), uri) 918 return this; 919 } 920 921 order(key: string, isAsc = true): FileFetchOptionBuilder { 922 if (isAsc) { 923 //升序 924 this.fetchOption.predicates.orderByAsc(key); 925 } else { 926 //降序 927 this.fetchOption.predicates.orderByDesc(key); 928 } 929 return this; 930 } 931 932 logicalAnd(): FileFetchOptionBuilder { 933 this.fetchOption.predicates.and(); 934 return this; 935 } 936 937 select(start: number, count: number): FileFetchOptionBuilder { 938 this.fetchOption.predicates.limit(count, start); 939 return this; 940 } 941 942 displayName(name: string): FileFetchOptionBuilder { 943 this.fetchOption.predicates.equalTo(userFileManager.ImageVideoKey.DISPLAY_NAME.toString(), name); 944 return this; 945 } 946 947 fetchColumns(columns: Array<string>): FileFetchOptionBuilder { 948 this.fetchOption.fetchColumns = columns; 949 return this; 950 } 951} 952 953/** 954 * 相册fetchOption 955 */ 956export class AlbumFetchOptionBuilder { 957 private fetchOption: userFileManager.FetchOptions = { 958 predicates: new dataSharePredicates.DataSharePredicates(), 959 fetchColumns: [] 960 }; 961 962 constructor(fetchOpt?) { 963 if (fetchOpt) { 964 this.fetchOption = fetchOpt; 965 } 966 } 967 968 build(): FetchOptions { 969 return this.fetchOption; 970 } 971 972 media(mediaType: string): AlbumFetchOptionBuilder { 973 this.fetchOption.predicates.equalTo(userFileManager.AlbumKey.FILE_TYPE.toString(), mediaType) 974 return this; 975 } 976 977 logicalAnd(): AlbumFetchOptionBuilder { 978 this.fetchOption.predicates.and(); 979 return this; 980 } 981 982 albumName(name: string): AlbumFetchOptionBuilder { 983 this.fetchOption.predicates.equalTo(userFileManager.AlbumKey.ALBUM_NAME.toString(), name); 984 return this; 985 } 986 987 albumUri(uri: string): AlbumFetchOptionBuilder { 988 this.fetchOption.predicates.equalTo(userFileManager.AlbumKey.URI.toString(), uri); 989 return this; 990 } 991}