• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2023-2024 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 photoAccessHelper from '@ohos.file.photoAccessHelper';
17import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
18import bundleManager from '@ohos.bundle.bundleManager';
19import dataSharePredicates from '@ohos.data.dataSharePredicates';
20import abilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry';
21import fs, { ListFileOptions } from '@ohos.file.fs';
22import fileuri from "@ohos.file.fileuri";
23
24const delegator = abilityDelegatorRegistry.getAbilityDelegator();
25const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(globalThis.abilityContext);
26const photoType = photoAccessHelper.PhotoType;
27const photoKeys = photoAccessHelper.PhotoKeys;
28const albumKeys = photoAccessHelper.AlbumKeys;
29const albumType = photoAccessHelper.AlbumType;
30const albumSubtype = photoAccessHelper.AlbumSubtype;
31const DEFAULT_SLEEP_TIME = 10;
32
33const context = globalThis.abilityContext;
34const pathDir = context.filesDir;
35
36let validImageExt = ['.jpg']
37let validVideoExt = ['.mp4']
38let validVideoMpegExt = ['.mpeg']
39let validImageGifExt = ['.gif']
40let validImagePngExt = ['.png']
41
42export async function sleep(times = DEFAULT_SLEEP_TIME) : Promise<void> {
43  await new Promise(res => setTimeout(res, times));
44};
45
46export function fetchAllOption() : photoAccessHelper.FetchOptions {
47  const predicates = new dataSharePredicates.DataSharePredicates();
48  const ops : photoAccessHelper.FetchOptions = {
49    fetchColumns: [],
50    predicates: predicates
51  };
52  return ops;
53};
54
55export function fetchOption(testNum, key, value) : photoAccessHelper.FetchOptions {
56  const predicates = new dataSharePredicates.DataSharePredicates();
57  predicates.equalTo(key, value);
58  const ops : photoAccessHelper.FetchOptions = {
59    fetchColumns: [],
60    predicates: predicates
61  };
62  console.info(`${testNum} queryOps: ${key} = ${value}`);
63  return ops;
64};
65
66export function albumFetchOption(testNum, key, value) : photoAccessHelper.FetchOptions {
67  const predicates = new dataSharePredicates.DataSharePredicates();
68  predicates.equalTo(key, value);
69  const ops : photoAccessHelper.FetchOptions = {
70    fetchColumns: [],
71    predicates: predicates
72  };
73  console.info(`${testNum} queryOps: ${key} = ${value}`);
74  return ops;
75};
76
77export function photoFetchOption(testNum, key, value) : photoAccessHelper.FetchOptions {
78  const predicates = new dataSharePredicates.DataSharePredicates();
79  predicates.equalTo(key, value);
80  const ops : photoAccessHelper.FetchOptions = {
81    fetchColumns: [
82      photoKeys.URI,
83      photoKeys.PHOTO_TYPE,
84      photoKeys.DISPLAY_NAME,
85      photoKeys.DATE_ADDED,
86      photoKeys.DATE_MODIFIED,
87      photoKeys.DURATION,
88      photoKeys.WIDTH,
89      photoKeys.HEIGHT,
90      photoKeys.DATE_TAKEN,
91      photoKeys.ORIENTATION,
92      photoKeys.FAVORITE,
93      photoKeys.SIZE,
94      photoKeys.TITLE,
95      photoKeys.POSITION,
96      photoKeys.DATE_TRASHED,
97      photoKeys.HIDDEN,
98      photoKeys.CAMERA_SHOT_KEY,
99      photoKeys.USER_COMMENT,
100      photoKeys.DATE_ADDED_MS,
101      photoKeys.DATE_MODIFIED_MS,
102      photoKeys.DYNAMIC_RANGE_TYPE,
103      photoKeys.COVER_POSITION,
104      photoKeys.BURST_KEY,
105      photoKeys.LCD_SIZE,
106      photoKeys.THM_SIZE,
107      photoKeys.DETAIL_TIME,
108      photoKeys.DATE_TAKEN_MS,
109      'all_exif',
110    ],
111    predicates: predicates
112  };
113  console.info(`${testNum} queryOps: ${key} = ${value}`);
114  return ops;
115};
116
117export async function getPermission(name = 'ohos.acts.multimedia.photoaccess') : Promise<void> {
118  try {
119    console.info('getPermission start', name);
120    let permissionState = new Map();
121    const permissions: Array<Permissions> = [
122      'ohos.permission.MEDIA_LOCATION',
123      'ohos.permission.READ_IMAGEVIDEO',
124      'ohos.permission.WRITE_IMAGEVIDEO',
125    ];
126
127    const atManager = abilityAccessCtrl.createAtManager();
128    const appFlags = bundleManager.ApplicationFlag.GET_APPLICATION_INFO_DEFAULT;
129    const userId = 100;
130    const appInfo = await bundleManager.getApplicationInfo(name, appFlags, userId);
131    const tokenID = appInfo.accessTokenId;
132    for (const permission of permissions) {
133      console.info('getPermission permission: ' + permission);
134      try {
135        await atManager.grantUserGrantedPermission(tokenID, permission, 1);
136      } catch (error) {
137        console.error(`getPermission ${permission} failed`);
138      }
139      permissionState.set(permission, await atManager.verifyAccessToken(tokenID, permission));
140    }
141    permissionState.forEach((value, key, map) => {
142      if (value !== 0) {
143        console.info(`getPermission failed; permission: ${key}, state: ${value}`);
144      }
145    });
146    console.info('getPermission end');
147  } catch (error) {
148    console.error(`getPermission failed, error: ${error}`);
149  }
150};
151
152export function isNum(value) : boolean {
153  return typeof value === 'number' && !isNaN(value);
154};
155
156export function getAssetId(uri) : string {
157  const tag = 'Photo/';
158  const index = uri.indexOf(tag);
159  let str = uri.substring(index + tag.length);
160  console.info(`getAssetId str: ${str}`);
161  return str;
162}
163
164export function getAlbumId(uri) : string {
165  const index = uri.lastIndexOf('/');
166  let str = uri.substring(index + 1);
167  console.info(`getAlbumId str: ${str}`);
168  return str;
169}
170
171export function genRadomStr(len: number) : string {
172  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
173  let randomStr = '';
174  for (let i = 0; i < len; i++) {
175    randomStr += chars.charAt(Math.floor(Math.random() * chars.length));
176  }
177  return randomStr;
178}
179
180export async function createUserAlbum(testNum, albumName) : Promise<photoAccessHelper.Album> {
181  console.info(`${testNum} createUserAlbum albumName: ${albumName}`);
182  let album: photoAccessHelper.Album;
183  try {
184    const helper = photoAccessHelper.getPhotoAccessHelper(globalThis.abilityContext);
185    album = await helper.createAlbum(albumName);
186    console.info(`${testNum} createUserAlbum suc`);
187  } catch (error) {
188    console.error(`Failed to createUserAlbum! error: ${error}`);
189    throw error;
190  }
191
192  return new Promise((resolve, reject) => {
193    resolve(album);
194  });
195}
196
197export async function getFileAsset(testNum, fetchOps) : Promise<photoAccessHelper.PhotoAsset> {
198  let asset: photoAccessHelper.PhotoAsset;
199  try {
200    const helper = photoAccessHelper.getPhotoAccessHelper(globalThis.abilityContext);
201    let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset>;
202    fetchResult = await helper.getAssets(fetchOps);
203    console.info(`${testNum} getFileAsset fetchResult: ${fetchResult.getCount()}`);
204    asset = await fetchResult.getFirstObject();
205    fetchResult.close();
206  } catch (error) {
207    console.error(`${testNum} getFileAsset error: ${error}`);
208    throw error;
209  }
210
211  return new Promise((resolve, reject) => {
212    resolve(asset);
213  });
214}
215
216export function getFileAssetFetchResult() : photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> {
217  let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset>;
218  return fetchResult;
219}
220
221export function getAlbumFetchResult() : photoAccessHelper.FetchResult<photoAccessHelper.Album> {
222  let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.Album>;
223  return fetchResult;
224}
225
226export function checkUserAlbum(expect, testNum, album, expectedName, expectedCover) : void {
227  console.info(`${testNum} checkUserAlbum album.albumName: ${album.albumName}, expectedName: ${expectedName}`);
228  expect(album.albumType).assertEqual(albumType.USER);
229  expect(album.albumSubtype).assertEqual(albumSubtype.USER_GENERIC);
230  expect(album.albumName).assertEqual(expectedName);
231  if (expectedCover === '') {
232    expect(album.coverUri).assertEqual('');
233  } else {
234    expect(album.coverUri).assertEqual(expectedCover);
235  }
236  expect(album.albumUri !== '').assertEqual(true);
237  expect(album.count).assertEqual(0);
238}
239
240export function checkSystemAlbum(expect, testNum, album, expectedSubType) : void {
241  try {
242    console.info(`${testNum} checkSystemAlbum expectedSubType: ${expectedSubType}`);
243    expect(album.albumType).assertEqual(albumType.SYSTEM);
244    expect(album.albumSubtype).assertEqual(expectedSubType);
245    expect(album.albumName).assertEqual('');
246    expect(album.albumUri !== '').assertEqual(true);
247  } catch (error) {
248    console.error(`Failed to delete all user albums! error: ${error}`);
249    throw error;
250  }
251}
252
253export async function startAbility(bundleName: string, abilityName: string) : Promise<void> {
254  await delegator.executeShellCommand(`aa start -b ${bundleName} -a ${abilityName}`).then(result => {
255    console.info(`[picker] start abilityFinished: ${result}`);
256  }).catch(err => {
257    console.error(`[picker] start abilityFailed: ${err}`);
258  });
259}
260
261export async function stopAbility(bundleName: string) : Promise<void> {
262  await delegator.executeShellCommand(`aa force-stop ${bundleName}`).then(result => {
263    console.info(`[picker] stop abilityFinished: ${result}`);
264  }).catch(err => {
265    console.error(`[picker] stop abilityFailed: ${err}`);
266  });
267}
268
269export async function getFileNameArray() {
270  try{
271    let listFileOption: ListFileOptions = {
272      recursion: true,
273      listNum: 0,
274      filter: {
275        suffix: [],
276      }
277    }
278    listFileOption.filter.suffix = validImageExt.concat(validVideoExt);
279    let nameArray = await fs.listFile(pathDir, listFileOption)
280    return nameArray;
281  } catch (err) {
282    console.error('getFileNameArray failed: ' + err);
283  }
284}
285
286export async function getAllFileNameArray() {
287  try{
288    let listFileOption: ListFileOptions = {
289      recursion: true,
290      listNum: 0,
291      filter: {
292        suffix: [],
293      }
294    }
295    listFileOption.filter.suffix = validImageExt.concat(validVideoExt).concat(validVideoMpegExt).concat(validImageGifExt).concat(validImagePngExt);
296    let nameArray = await fs.listFile(pathDir, listFileOption)
297    return nameArray;
298  } catch (err) {
299    console.error('getFileNameArray failed: ' + err);
300  }
301}
302
303export async function pushCreateAsset(names: Array<string>){
304  console.info('pushCreateAsset start')
305  let successNum = 0;
306  try{
307    console.info('pushCreateAsset name: ' + names)
308    let photoType: photoAccessHelper.PhotoType;
309    let resourceType: photoAccessHelper.ResourceType;
310    let fileNames: string[] = await getFileNameArray();
311    console.info('pushCreateAsset rawFiles number: ' + fileNames.length);
312    for(let i = 0; i < fileNames.length; i++) {
313      let fileName = fileNames[i];
314      let filePath = pathDir + '/' + fileName;
315      let fileUri = fileuri.getUriFromPath(filePath);
316      let rawExtension: string = fileName.split('.')[1];
317      for (let j = 0; j < names.length; j++) {
318        let name = names[j];
319        if (fileName.includes('error')) continue
320        let extension: string = name.split('.')[1];
321        if (rawExtension === extension) {
322          let options: photoAccessHelper.CreateOptions = {
323            title: name.split('.')[0]
324          }
325          if (validImageExt.includes(('.' + extension))) {
326            photoType = photoAccessHelper.PhotoType.IMAGE;
327            resourceType = photoAccessHelper.ResourceType.IMAGE_RESOURCE;
328          } else {
329            photoType = photoAccessHelper.PhotoType.VIDEO;
330            resourceType = photoAccessHelper.ResourceType.VIDEO_RESOURCE;
331          }
332          let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(globalThis.abilityContext, photoType, extension, options);
333          assetChangeRequest.addResource(resourceType, fileUri);
334          await phAccessHelper.applyChanges(assetChangeRequest);
335          console.info(`pushCreateAsset ${name} create success`)
336          successNum++;
337        }
338      }
339    }
340    console.info('Push_createAsset successfully fileNumber: ' + successNum);
341  }catch(err){
342    console.error('Push_createAsset push resource failed: ' + err)
343    return;
344  }
345}
346
347export async function pushCreateAssetSingle(names: Array<string>){
348  console.info('pushCreateAssetSingle start')
349  let successNum = 0;
350  try{
351    console.info('pushCreateAssetSingle name: ' + names)
352    let photoType: photoAccessHelper.PhotoType;
353    let resourceType: photoAccessHelper.ResourceType;
354    let fileNames: string[] = await getAllFileNameArray();
355    for (let i = 0; i < fileNames.length; i++) {
356      let fileName = fileNames[i];
357      let filePath = pathDir + '/' + fileName;
358      let fileUri = fileuri.getUriFromPath(filePath);
359      let rawExtension: string = fileName.split('.')[1];
360      for (let j = 0; j < names.length; j++) {
361        let name = names[j];
362        if(fileName == '/01.jpg' || fileName == '/01.mp4') continue
363        let extension: string = name.split('.')[1];
364        if (rawExtension === extension) {
365          let options: photoAccessHelper.CreateOptions = {
366            title: name.split('.')[0]
367          }
368          if (validImageExt.concat(validImageGifExt).concat(validImagePngExt).includes(('.' + extension))) {
369            photoType = photoAccessHelper.PhotoType.IMAGE;
370            resourceType = photoAccessHelper.ResourceType.IMAGE_RESOURCE;
371          } else {
372            photoType = photoAccessHelper.PhotoType.VIDEO;
373            resourceType = photoAccessHelper.ResourceType.VIDEO_RESOURCE;
374          }
375          let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest = photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(globalThis.abilityContext, photoType, extension, options);
376          assetChangeRequest.addResource(resourceType, fileUri);
377          await phAccessHelper.applyChanges(assetChangeRequest);
378          console.info(`pushCreateAssetSingle ${name} create success`)
379          successNum++;
380        }
381      }
382    }
383    console.info('Push_createAsset successfully fileNumber: ' + successNum);
384  }catch(err){
385    console.error('Push_createAsset push resource failed: ' + err)
386    return;
387  }
388}
389
390export function createSandboxFileUri(extension) {
391  let pathDir = globalThis.abilityContext.filesDir;
392  let path = pathDir + '/test' + new Date().getTime() + '.' + extension;
393  fs.openSync(path, fs.OpenMode.CREATE)
394  return fileuri.getUriFromPath(path);
395}
396
397export async function getBurstKey(testNum: string, fetchOps: photoAccessHelper.FetchOptions): Promise<string | number> {
398  let burstKey: string | number | undefined = -1;
399  try {
400    let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> = await phAccessHelper.getAssets(fetchOps);
401    if (fetchResult === undefined) {
402      console.error(`${testNum} :: getBurstKey :: fetchResult is undefined !`);
403      return burstKey;
404    }
405    let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();
406    if (photoAsset === undefined) {
407      console.error(`${testNum} :: getBurstKey :: photoAsset is undefined !`);
408      return burstKey;
409    }
410    burstKey = photoAsset.get(photoKeys.BURST_KEY).toString();
411    console.log(`${testNum} :: get burstKey success, burstKey is ${burstKey}`);
412    return burstKey;
413  } catch (error) {
414    console.error(`${testNum} :: getBurstKey failed, msg is ${error}`);
415    return burstKey;
416  }
417}
418
419export async function createMovingPhoto(testNum: string, context: Context, titleName: string) {
420  let photoAsset: photoAccessHelper.PhotoAsset | undefined = undefined;
421  try {
422    let photoType: photoAccessHelper.PhotoType = photoAccessHelper.PhotoType.IMAGE;
423    let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
424    let extension: string = 'jpg';
425    let options: photoAccessHelper.CreateOptions = {
426      title: titleName,
427      subtype: photoAccessHelper.PhotoSubtype.MOVING_PHOTO
428    }
429    let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest =
430      photoAccessHelper.MediaAssetChangeRequest.createAssetRequest(context, photoType, extension, options);
431    console.log(`${testNum} :: create assetChangeRequest success`);
432    let photoUri = "file://ohos.acts.multimedia.photoaccess/data/storage/el2/base/haps/phone/photos/test_mov_1.jpg";
433    let videoUri = "file://ohos.acts.multimedia.photoaccess/data/storage/el2/base/haps/phone/photos/test_mov_1.mp4";
434    assetChangeRequest.addResource(photoAccessHelper.ResourceType.IMAGE_RESOURCE, photoUri);
435    assetChangeRequest.addResource(photoAccessHelper.ResourceType.VIDEO_RESOURCE, videoUri);
436    console.log(`${testNum} :: add resource success`);
437    await phAccessHelper.applyChanges(assetChangeRequest);
438    console.log(`${testNum} :: applyChange success`);
439    photoAsset = assetChangeRequest.getAsset();
440  } catch (error) {
441    console.error(`${testNum} :: create moving photo failed, error is ${error}`);
442  }
443  return photoAsset;
444}
445
446export {
447  photoType,
448  photoKeys,
449  albumKeys,
450  albumType,
451  albumSubtype,
452};