diff --git a/CoreFile/DistributedFileSample/.gitignore b/CoreFile/DistributedFileSample/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/CoreFile/DistributedFileSample/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/AppScope/app.json5 b/CoreFile/DistributedFileSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..693d51c38d4ba104bbf1b82b8d5f108c37223ee9 --- /dev/null +++ b/CoreFile/DistributedFileSample/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.distributedfilesample", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/CoreFile/DistributedFileSample/AppScope/resources/base/element/string.json b/CoreFile/DistributedFileSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..9d4e186192c02385fb92fcf0d6b5849b35c45ac1 --- /dev/null +++ b/CoreFile/DistributedFileSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "DistributedFileSample" + } + ] +} diff --git a/CoreFile/DistributedFileSample/AppScope/resources/base/media/app_icon.png b/CoreFile/DistributedFileSample/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/CoreFile/DistributedFileSample/AppScope/resources/base/media/app_icon.png differ diff --git a/CoreFile/DistributedFileSample/README_zh.md b/CoreFile/DistributedFileSample/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..b0bd605021da274a6e2dffb2850ddd1cd0f466af --- /dev/null +++ b/CoreFile/DistributedFileSample/README_zh.md @@ -0,0 +1,77 @@ +# 分布式文件系统 + +## 介绍 + +本实例实现了分布式文件系统的文件跨设备访问、跨设备拷贝以及设计分布式文件数据等级。使用两台设备进行分布式组网,在组网环境下可以对文件进行跨设备的访问和拷贝,该工程中展示的代码详细描述可查如下链接。 + +- [ 设置分布式文件数据等级](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/set-security-label.md) +- [ 跨设备文件访问](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/file-access-across-devices.md) +- [ 跨设备文件拷贝](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/file-copy-across-devices.md) + +## 效果预览 + +| 应用界面 | +| :------------------------------------------------: | +| | + +使用说明: + +1. 本应用在进行分布式文件访问之前,需要两台设备进行组网并且都安装了本应用。 +2. 组网要求:两台设备连入同一个局域网中,确保设备进入可信状态,且两台设备的音乐软件能同步播放和暂停。 +3. 在启动应用后可以根据相应的按钮实现对应的功能点,首先便是设备A在分布式目录下创建文件,并将此文件的数据等级设置,使其可以跨设备进行访问。 +4. 由B设备访问应用公共目录并挂载,向A设备发起建链,设备B可在分布式路径下读取测试文件。 +5. 按钮“从沙箱复制到分布式目录”设备A在本地目录下创建一个文件,随后将其拷贝到分布式路径下。 +6. 按钮“从分布式目录复制到沙箱”设备A和B在确认组网建链后,由设备B从分布式路径下将测试文件拷贝到设备B的沙箱路径。 + +## 工程目录 + +``` +├──entry/src/main +| ├──ets +| | ├──commom +| | | ├──Logger.ts // 日志工具 +| | | ├──ShowToast.ets // 弹窗提示工具 +| | ├──entryability +| | | └──EntryAbility.ets // 程序入口类 +| | ├──entrybackupability +| | | └──EntryBackupAbility.ets +| | └──pages // 页面文件 +| | └──Index.ets // 主界面 +| ├──resources // 资源文件目录 +``` + +## 具体实现 + +1. 根据Openharmony提供完整的数据分级、设备分级标准,并针对不同设备制定不同的数据流转策略,来设置文件的安全等级。 +2. 完成分布式组网。 将需要跨设备访问的两个设备登录同一账号,保证设备蓝牙和Wi-Fi功能开启,蓝牙无需互连,Wi-Fi无需接入同一个局域网。 +3. 访问跨设备文件,分布式文件系统为应用提供了跨设备文件访问的能力,开发者在两个设备安装同一应用时,通过基础文件接口,可跨设备读写另一个设备该应用分布式文件路径下的文件。 +4. 拷贝跨设备文件,由设备A的将文件从沙箱路径拷贝到分布式路径下,再有组网的设备B从分布式路径将文件拷贝到设备B的应用沙箱路径。 + +## 相关权限 + +- [ohos.permission.DISTRIBUTED_SOFTBUS_CENTER](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/security/AccessToken/permissions-for-system-apps.md#ohospermissiondistributed_softbus_center) +- [ohos.permission.ACCESS_SERVICE_DM](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/security/AccessToken/permissions-for-system-apps.md#ohospermissionaccess_service_dm) +- [ohos.permission.DISTRIBUTED_DATASYNC](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissiondistributed_datasync) +- [ohos.permission.INTERNET](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissioninternet) + +## 依赖 + +不涉及 + +## 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.1.1 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.1.1 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.1.1 Release及以上。 +5. 本示例涉及部分接口需要配置系统应用签名,可以参考[特殊权限配置方法](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/security/hapsigntool-overview.md) ,把配置文件中的“apl”字段信息改为“system_basic”。 + +## 下载 + +``` +git init +git config core.sparsecheckout true +echo CoreFile/DistributedFileSample > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +``` diff --git a/CoreFile/DistributedFileSample/build-profile.json5 b/CoreFile/DistributedFileSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c97e4d39298e58d6e5eef88d2301eebd6085a13c --- /dev/null +++ b/CoreFile/DistributedFileSample/build-profile.json5 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.1.1(19)", + "compatibleSdkVersion": "5.1.1(19)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/code-linter.json5 b/CoreFile/DistributedFileSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/CoreFile/DistributedFileSample/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/.gitignore b/CoreFile/DistributedFileSample/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/build-profile.json5 b/CoreFile/DistributedFileSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/hvigorfile.ts b/CoreFile/DistributedFileSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d28cb60475cede46d0aa36973096d5544dbcd1 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/DistributedFileSample/entry/obfuscation-rules.txt b/CoreFile/DistributedFileSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/oh-package.json5 b/CoreFile/DistributedFileSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/CoreFile/DistributedFileSample/entry/src/main/ets/common/Logger.ts b/CoreFile/DistributedFileSample/entry/src/main/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..98d085038b35ed0a5be9a6c9882e9202d419fe3b --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0000; // 应用的编码 + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_DistributedFileSample]'); + diff --git a/CoreFile/DistributedFileSample/entry/src/main/ets/common/ShowToast.ets b/CoreFile/DistributedFileSample/entry/src/main/ets/common/ShowToast.ets new file mode 100644 index 0000000000000000000000000000000000000000..b95a0b3987d341d3382452dc74cb033b824c4c90 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/ets/common/ShowToast.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import promptAction from '@ohos.promptAction'; + +export function showToast(msg: string, dur: number) { + promptAction.showToast({ + message: msg, + duration: dur + }); +} diff --git a/CoreFile/DistributedFileSample/entry/src/main/ets/entryability/EntryAbility.ets b/CoreFile/DistributedFileSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f2f8b94aa24b0a50e272270e4e18b6df93ac5fd --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/CoreFile/DistributedFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/CoreFile/DistributedFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/ets/pages/Index.ets b/CoreFile/DistributedFileSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..8537950fd37d3691ea633b0fbd0ad40fca6c593b --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start cross_device_file_access_B] +// [Start import_interface_distributed] +// [Start dis_mount_public_dir] +import { BusinessError } from '@kit.BasicServicesKit'; +import { common, abilityAccessCtrl } from '@kit.AbilityKit'; +import { distributedDeviceManager } from '@kit.DistributedServiceKit'; +import { fileIo as fs, ListFileOptions, fileUri, securityLabel } from '@kit.CoreFileKit'; +import { buffer } from '@kit.ArkTS'; +import Logger from '../common/Logger'; +import { showToast } from '../common/ShowToast'; + +// [Start import_interface_distributed] +const BUFFER: number = 4096; // 读写文件的缓冲区 +const DELAY: number = 1000; // 延时1秒 +const MARGIN: number = 5; // 组件的间隔 + +// [Start cross_device_file_access_A] +let context = getContext(this) as common.UIAbilityContext; // 获取UIAbilityContext信息 +let pathDir: string = context.filesDir; // 应用沙箱路径 +let distributedPathDir: string = context.distributedFilesDir; // 应用分布式路径 +let atManager = abilityAccessCtrl.createAtManager(); + +// 设备A上在分布式路径下创建测试文件,并写入内容 +function createFile(path: string, fileName: string): void { + let filePath = path + '/' + fileName + '.txt'; + let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + setFileLv(filePath); + showToast('Successfully created file of level s0', DELAY); + fs.writeSync(file.fd, 'content OpenHarmony Distributed File System test'); + Logger.info('Succeeded in creating.'); + fs.closeSync(file.fd); +} + +// [End cross_device_file_access_A] + +// [Start set_security_label] +// 打开文件并设置文件数据等级为‘s0’ +function setFileLv(path: string): void { + let file = fs.openSync(path, fs.OpenMode.READ_ONLY); + securityLabel.setSecurityLabel(path, 's0').then(() => { + Logger.info('Successfully set the security label to s0.'); + fs.closeSync(file); + }).catch((err: BusinessError) => { + let error: BusinessError = err as BusinessError; + console.error(`Failed to setSecurityLabel. Code: ${error.code}, message: ${error.message}`); + }); +} + +// [End set_security_label] + +// 定义访问公共文件目录的回调 +let listeners: fs.DfsListeners = { + onStatus: (networkId: string, status: number): void => { + Logger.info('Failed to access public directory'); + } +} + +// [StartExclude cross_device_file_access_B] +// 申请多设备协同权限 +async function applyPermission() { + try { + await atManager.requestPermissionsFromUser(context, ['ohos.permission.DISTRIBUTED_DATASYNC']).then((data) => { + Logger.info('data: ' + JSON.stringify(data)); + }).catch((err: object) => { + Logger.error('err: ' + JSON.stringify(err)); + }) + } catch (error) { + Logger.error('catch err->' + JSON.stringify(error)); + } +} + +// [EndExclude cross_device_file_access_B] + +// 设备B主动向设备A发起建链,建链成功后设备B可在分布式路径下读取测试文件 +async function mountPublicDir() { + // [StartExclude cross_device_file_access_B] + // 通过分布式设备管理的接口获取设备A的networkId信息 + let dmInstance = distributedDeviceManager.createDeviceManager('ohos.samples.distributedmusicplayer'); + let deviceInfoList: distributedDeviceManager.DeviceBasicInfo[] = dmInstance.getAvailableDeviceListSync(); + let networkId = deviceInfoList[0].networkId; // 0表示可信设备列表中第一台设备 + // [EndExclude cross_device_file_access_B] + + // 访问并挂载公共文件目录 + fs.connectDfs(networkId, listeners).then(() => { + Logger.info('Success to connectDfs'); + let context = getContext(); // 获取设备B的UIAbilityContext信息 + let distributedFilesDir: string = context.distributedFilesDir; + // 获取分布式目录的文件路径 + let filePath: string = distributedFilesDir + '/distributedTest.txt'; + try { + // 打开分布式目录下的文件 + let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY); + // 定义接收读取数据的缓存 + let arrayBuffer = new ArrayBuffer(BUFFER); + + // 读取文件的内容,返回值是读取到的字节个数 + class Option { + public offset: number = 0; // 0表示从头开始读取文件内容 + public length: number = 0; // 读取的文件长度,初始化为0 + } + + let option = new Option(); + option.length = arrayBuffer.byteLength; + let num = fs.readSync(file.fd, arrayBuffer, option); + // 打印读取到的文件数据 + let buf = buffer.from(arrayBuffer, 0, num); + Logger.info('read result: ' + buf.toString()); + showToast('Success to connectDfs', DELAY); + } catch (error) { + let err: BusinessError = error as BusinessError; + Logger.error(`Failed to openSync / readSync. Code: ${err.code}, message: ${err.message}`); + } + }).catch((error: BusinessError) => { + let err: BusinessError = error as BusinessError; + Logger.error(`Failed to connectDfs Code: ${err.code}, message: ${err.message}`); + }); +} + +// [Start cross_device_file_access_B] + +// 取消公共文件目录挂载,断开链路。 +function disMountPublicDir(): void { + // 通过分布式设备管理的接口获取设备A的networkId信息 + let dmInstance = distributedDeviceManager.createDeviceManager('ohos.samples.distributedmusicplayer'); + let deviceInfoList: distributedDeviceManager.DeviceBasicInfo[] = dmInstance.getAvailableDeviceListSync(); + // 两台设备组网连接,deviceInfoList[0]即对应另一台设备 + let networkId = deviceInfoList[0].networkId; + fs.disconnectDfs(networkId).then(() => { + Logger.info('Success to disconnectDfs'); + }).catch((error: BusinessError) => { + let err: BusinessError = error as BusinessError; + Logger.error(`Failed to disconnectDfs Code: ${err.code}, message: ${err.message}`); + }) +} + +// [End dis_mount_public_dir] + +// [Start copy_sand_to_distributed] +// 将A设备的待拷贝沙箱文件,拷贝到A设备的分布式路径下。 +function copySandFile(): void { + // 待拷贝文件沙箱路径 + let filePath: string = pathDir + '/src.txt'; + try { + // 文件不存在时,需要创建文件并写入内容 + let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); + fs.writeSync(file.fd, 'Create file success'); + fs.closeSync(file); + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.error(`Failed to createFile. Code: ${error.code}, message: ${error.message}`); + } + // 获取待拷贝文件uri + let srcUri = fileUri.getUriFromPath(filePath); + // 将待拷贝的沙箱文件,拷贝到分布式目录下 + let destUri: string = fileUri.getUriFromPath(distributedPathDir + '/src.txt'); + try { + // 将沙箱路径下的文件拷贝到分布式路径下 + fs.copy(srcUri, destUri).then(() => { + Logger.info('Succeeded in copying---. '); + Logger.info('src: ' + srcUri + 'dest: ' + destUri); + // [StartExclude copy_sand_to_distributed] + setFileLv(distributedPathDir + '/src.txt'); + showToast('Succeed copy from sandDir to distributedDir', DELAY); + // [EndExclude copy_sand_to_distributed] + }).catch((error: BusinessError) => { + let err: BusinessError = error as BusinessError; + Logger.error(`Failed to copy. Code: ${err.code}, message: ${err.message}`); + }) + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.error(`Failed to getData. Code: ${error.code}, message: ${error.message}`); + } +} + +// [End copy_sand_to_distributed] + +// [End copy_distributed_to_sand] +// B设备在获取A端沙箱文件时,从B设备的分布式路径下将对应的文件拷贝走,以此完成跨设备拷贝。 +function copyDistributedFile(): void { + // 待拷贝文件的目标沙箱路径 + let filePath: string = pathDir + '/dest.txt'; + // 获取目标路径uri + let destUri = fileUri.getUriFromPath(filePath); + // 获取分布式路径下的源文件 + let srcUri: string = fileUri.getUriFromPath(distributedPathDir + '/src.txt'); + // 定义拷贝回调 + let progressListener: fs.ProgressListener = (progress: fs.Progress) => { + Logger.info(`progressSize: ${progress.processedSize}, totalSize: ${progress.totalSize}`); + }; + let options: fs.CopyOptions = { + 'progressListener': progressListener + }; + try { + // 将分布式路径下的文件拷贝到其他沙箱路径下 + fs.copy(srcUri, destUri, options).then(() => { + Logger.info('Succeeded in copying of paste. '); + showToast('Succeeded in copying of paste. ', DELAY); + Logger.info('src: ' + srcUri + 'dest: ' + destUri); + }).catch((error: BusinessError) => { + let err: BusinessError = error as BusinessError; + Logger.error(`Failed to copy. Code: ${err.code}, message: ${err.message}`); + }) + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.error(`Failed to copy. Code: ${error.code}, message: ${error.message}`); + } +} + +// [End copy_distributed_to_sand] + +// 查看文件列表 +function getListFile(pathDir: string): void { + let listFileOption: ListFileOptions = { + recursion: false, + listNum: 0, // 0表示不限制列出的文件数量 + filter: { + suffix: ['.png', '.jpg', '.txt', '.jpeg'], + displayName: ['*'], + fileSizeOver: 0, // 文件大小必须大于 0 字节 + lastModifiedAfter: new Date(0).getTime() + } + }; + let files = fs.listFileSync(pathDir, listFileOption); + for (let i = 0; i < files.length; i++) { + Logger.info(pathDir); + Logger.info(`The name of file: ${files[i]}`); + } +} + +@Entry +@Component +struct Distributed { + build() { + Column() { + Row() { + Button($r('app.string.CreateFile')) + .width('30%') + .height('40%') + .margin(MARGIN) + .onClick(() => { + createFile(distributedPathDir, 'distributedTest'); + }) + Button($r('app.string.AccessPublicFileDir')) + .width('30%') + .height('40%') + .margin(MARGIN) + .onClick(() => { + mountPublicDir(); + }) + Button($r('app.string.DisconnectingLink')) + .width('30%') + .height('40%') + .onClick(() => { + disMountPublicDir(); + }) + } + .width('100%') + .height('20%') + .align(Alignment.Center); + + Row() { + Button($r('app.string.CopySandToDistributed')) + .width('45%') + .height('40%') + .margin(MARGIN) + .onClick(() => { + copySandFile(); + }) + Button($r('app.string.CopyDistributedToSand')) + .width('45%') + .height('40%') + .onClick(() => { + copyDistributedFile(); + }) + } + .width('100%') + .height('20%') + .align(Alignment.Center); + + Button($r('app.string.ApplyPermission')) + .margin(MARGIN) + .width('30%') + .height('8%') + .align(Alignment.Center) + .onClick(() => { + applyPermission(); + }) + Button($r('app.string.GetFileList')) + .width('30%') + .height('8%') + .align(Alignment.Center) + .onClick(() => { + getListFile(pathDir); + getListFile(distributedPathDir); + }) + } + } +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/module.json5 b/CoreFile/DistributedFileSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9994b128dfb80fa46fa47b417277f6299fa3964 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/module.json5 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "continuable": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + ] + } + ] + } + ], + "definePermissions": [ + { + "name": "ohos.permission.ACCESS_SERVICE_DM", + "grantMode": "system_grant", + "availableLevel": "system_core", + "provisionEnable": true, + "distributedSceneEnable": false, + "label": "$string:EntryAbility_label" + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.DISTRIBUTED_DATASYNC", + "reason": "$string:dataflow", + "usedScene": { + "abilities": [ + "FormAbility" + ], + "when": "always" + }, + }, + { + "name": "ohos.permission.ACCESS_SERVICE_DM", + "reason": "$string:CerNetwork", + "usedScene": { + "abilities": [ + "FormAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.INTERNET", + "reason": "$string:requestINTER", + "usedScene": { + "abilities": [ + "FormAbility" + ], + "when": "always" + } + }, + ], + } +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/color.json b/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/string.json b/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ab72e840f17bf9299f0cbb2b4ccc522e54668930 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,64 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Distributed" + }, + { + "name": "dataflow", + "value": "跨设备数据流转" + }, + { + "name": "requestINTER", + "value": "网络请求" + }, + { + "name": "CerNetwork", + "value": "允许应用获取分布式设备的认证组网能力" + }, + { + "name": "SetFileLevel", + "value": "设置文件等级" + }, + { + "name": "AccessPublicFileDir", + "value": "访问公共目录" + }, + { + "name": "DisconnectingLink", + "value": "断开链路" + }, + { + "name": "CopySandToDistributed", + "value": "从沙箱复制到分布式目录" + }, + { + "name": "CopyDistributedToSand", + "value": "从分布式目录复制到沙箱" + }, + { + "name": "GetFileList", + "value": "获取文件列表" + }, + { + "name": "ApplyPermission", + "value": "申请权限" + }, + { + "name": "CreateFile", + "value": "文件创建" + }, + { + "name": "permit", + "value": "允许" + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/background.png b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/background.png differ diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/foreground.png b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/layered_image.json b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/startIcon.png b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/CoreFile/DistributedFileSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/backup_config.json b/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/main_pages.json b/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/en_US/element/string.json b/CoreFile/DistributedFileSample/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ba44c5f9b08872f845bae2f70a469da8365d383b --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,64 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Distributed" + }, + { + "name": "dataflow", + "value": "dataflow" + }, + { + "name": "requestINTER", + "value": "requestINTER" + }, + { + "name": "CerNetwork", + "value": "CerNetwork" + }, + { + "name": "SetFileLevel", + "value": "SetFileLevel" + }, + { + "name": "AccessPublicFileDir", + "value": "AccessPublicFileDir" + }, + { + "name": "DisconnectingLink", + "value": "DisconnectingLink" + }, + { + "name": "CopySandToDistributed", + "value": "CopySandToDistributed" + }, + { + "name": "CopyDistributedToSand", + "value": "CopyDistributedToSand" + }, + { + "name": "GetFileList", + "value": "GetFileList" + }, + { + "name": "ApplyPermission", + "value": "ApplyPermission" + }, + { + "name": "CreateFile", + "value": "CreateFile" + }, + { + "name": "permit", + "value": "permit" + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/main/resources/zh_CN/element/string.json b/CoreFile/DistributedFileSample/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..64195a84ecf159e379ad5d54c62fd5852a3a092a --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,64 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Distributed" + }, + { + "name": "dataflow", + "value": "跨设备数据流转" + }, + { + "name": "requestINTER", + "value": "网络请求" + }, + { + "name": "CerNetwork", + "value": "允许应用获取分布式设备的认证组网能力" + }, + { + "name": "SetFileLevel", + "value": "设置文件等级" + }, + { + "name": "AccessPublicFileDir", + "value": "访问公共目录" + }, + { + "name": "DisconnectingLink", + "value": "断开链路" + }, + { + "name": "CopySandToDistributed", + "value": "从沙箱复制到分布式目录" + }, + { + "name": "CopyDistributedToSand", + "value": "从分布式目录复制到沙箱" + }, + { + "name": "GetFileList", + "value": "获取文件列表" + }, + { + "name": "ApplyPermission", + "value": "申请权限" + }, + { + "name": "CreateFile", + "value": "文件创建" + }, + { + "name": "permit", + "value": "允许" + } + ] +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/mock/mock-config.json5 b/CoreFile/DistributedFileSample/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/DistributedFileSample.test.ets b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/DistributedFileSample.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e43d2528ac17cf4a5e5b84e7a29c882c195a1fdf --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/DistributedFileSample.test.ets @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component, abilityDelegatorRegistry } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const DELAY_TIME = 1200; // 延时1.2秒 +const TAG = '[Sample_DistributedFileSamples]'; +const DOMAIN = 0xF811; +const BUNDLE = 'DistributedFileSamples_'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function DistributedFileSampleTest() { + describe('DistributedFileSampleTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin'); + // start tested ability + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + // check top display ability + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(DOMAIN, TAG, BUNDLE + 'get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('TestAbility'); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end'); + }) + /** + * @tc.number ApplyPermission_001 + * @tc.name ApplyPermission_001 + * @tc.desc 权限申请 + */ + it(BUNDLE + 'ApplyPermission_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_001 begin'); + let str = await getResourceString($r('app.string.ApplyPermission')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_001 end'); + }) + /** + * @tc.number ApplyPermission_002 + * @tc.name ApplyPermission_002 + * @tc.desc 权限申请 + */ + it(BUNDLE + 'ApplyPermission_002', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_002 begin'); + let str = await getResourceString($r('app.string.permit')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_002 end'); + }) + /** + * @tc.number mountPublicDir_001 + * @tc.name mountPublicDir_001 + * @tc.desc 建链并访问文件 + */ + it(BUNDLE + 'mountPublicDir_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'mountPublicDir_001 begin'); + let str = await getResourceString($r('app.string.AccessPublicFileDir')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'mountPublicDir_001 end'); + }) + /** + * @tc.number copyDistributedFile_001 + * @tc.name copyDistributedFile_001 + * @tc.desc 跨设备拷贝文件 + */ + it(BUNDLE + 'copyDistributedFile_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'copyDistributedFile begin'); + let str = await getResourceString($r('app.string.CopyDistributedToSand')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'copyDistributedFile_001 end'); + }) + /** + * @tc.number disMountPublicDir_001 + * @tc.name disMountPublicDir_001 + * @tc.desc 关闭建链 + */ + it(BUNDLE + 'disMountPublicDir_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'disMountPublicDir_001 begin'); + let str = await getResourceString($r('app.string.DisconnectingLink')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'disMountPublicDir_001 end'); + }) + }) +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/List.test.ets b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..981f00d1bb9e44a79bda2363dc19d46615ff093f --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import readyTest from './Ready.test'; +import DistributedFileSampleTest from './DistributedFileSample.test'; + +export default function testsuite() { + readyTest(); + DistributedFileSampleTest(); +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/Ready.test.ets b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/Ready.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1d84a04df5a5c83dfc3cdb1c41f7310e2d16c35a --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/ohosTest/ets/test/Ready.test.ets @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect } from '@ohos/hypium' +import { Driver, ON, Component, abilityDelegatorRegistry } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const DELAY_TIME = 1500; // 延时1.5秒 +const TAG = '[Sample_DistributedFileSamples]'; +const DOMAIN = 0xF811; +const BUNDLE = 'DistributedFileSamples_'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function readyTest() { + describe('readyTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin'); + // start tested ability + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + // check top display ability + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info("get top ability"); + expect(ability.context.abilityInfo.name).assertEqual('TestAbility'); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end'); + + }) + /** + * @tc.number ApplyPermission_001 + * @tc.name ApplyPermission_001 + * @tc.desc 权限申请 + */ + it(BUNDLE + 'ApplyPermission_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_001 begin'); + let str = await getResourceString($r('app.string.ApplyPermission')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_001 end'); + }) + /** + * @tc.number ApplyPermission_002 + * @tc.name ApplyPermission_002 + * @tc.desc 允许权限 + */ + it(BUNDLE + 'ApplyPermission_002', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_002 begin'); + let str = await getResourceString($r('app.string.permit')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'ApplyPermission_002 end'); + }) + /** + * @tc.number CreateFile_001 + * @tc.name CreateFile_001 + * @tc.desc 分布式目录下创建文件 + */ + it(BUNDLE + 'CreateFile_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'CreateFile_001 begin'); + let str = await getResourceString($r('app.string.CreateFile')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'CreateFile_001 end'); + }) + /** + * @tc.number copySandFile_001 + * @tc.name copySandFile_001 + * @tc.desc 从沙箱路径复制文件到分布式路径 + */ + it(BUNDLE + 'copySandFile_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'copySandFile begin'); + let str = await getResourceString($r('app.string.CopySandToDistributed')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'copySandFile end'); + }) + + }) +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/ohosTest/module.json5 b/CoreFile/DistributedFileSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/CoreFile/DistributedFileSample/entry/src/test/List.test.ets b/CoreFile/DistributedFileSample/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/entry/src/test/LocalUnit.test.ets b/CoreFile/DistributedFileSample/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/CoreFile/DistributedFileSample/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/CoreFile/DistributedFileSample/hvigor/hvigor-config.json5 b/CoreFile/DistributedFileSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..43beb743cbd25c3507b1cf8a744bf8197b3bf2fb --- /dev/null +++ b/CoreFile/DistributedFileSample/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/CoreFile/DistributedFileSample/hvigorfile.ts b/CoreFile/DistributedFileSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4beb74fe5b573059b972acf9312d33ea1703c016 --- /dev/null +++ b/CoreFile/DistributedFileSample/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/DistributedFileSample/oh-package.json5 b/CoreFile/DistributedFileSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..93f097993a458e967d6d5239ea0580e79b5d6998 --- /dev/null +++ b/CoreFile/DistributedFileSample/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/CoreFile/DistributedFileSample/ohosTest.md b/CoreFile/DistributedFileSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..dce68cbf898c8ae1dad5c4145e3aebf7c27beb29 --- /dev/null +++ b/CoreFile/DistributedFileSample/ohosTest.md @@ -0,0 +1,22 @@ +# 测试用例归档 + +## 文件准备用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ---------------------------- | ---------------- | ---- | ---------------- | -------- | -------- | +| 拉起应用 | 设备正常运行 | \ | 应用被拉起 | 是 | pass | +| 权限申请 | 应用被拉起 | \ | 拉起权限申请弹窗 | 是 | pass | +| 允许多设备协同权限 | 拉起权限申请弹窗 | \ | 选择允许 | 是 | pass | +| 创建文件并设置文件等级 | 应用被拉起 | \ | 完成文件的创建 | 是 | pass | +| 将文件从沙箱拷贝到分布式目录 | 设备正常运行 | \ | 文件成功拷贝 | 是 | pass | + +## 跨设备文件访问和拷贝用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| -------------------- | --------------------------------- | ---- | ----------------------------------- | -------- | -------- | +| 拉起应用 | 设备正常运行 | \ | 应用被拉起 | 是 | pass | +| 权限申请 | 应用被拉起 | \ | 拉起权限申请弹窗 | 是 | pass | +| 允许多设备协同权限 | 拉起权限申请弹窗 | \ | 选择允许 | 是 | pass | +| 多设备建链并访问文件 | 两台设备已经完成可信组网 | \ | 成功建链并放了另一台设备的文件 | 是 | pass | +| 跨设备拷贝 | A设备已经将文件拷贝到分布式目录下 | \ | B设备成功从分布式目录拷贝到沙箱目录 | 是 | pass | + diff --git a/CoreFile/DistributedFileSample/screenshots/start.jpg b/CoreFile/DistributedFileSample/screenshots/start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..588998c6b36938d6a09c5ea60291565f04ca244b Binary files /dev/null and b/CoreFile/DistributedFileSample/screenshots/start.jpg differ diff --git a/CoreFile/FileBackupExtension/.gitignore b/CoreFile/FileBackupExtension/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/CoreFile/FileBackupExtension/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/AppScope/app.json5 b/CoreFile/FileBackupExtension/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..08891bc0f14caa41b0f16ec8621248b1d8942036 --- /dev/null +++ b/CoreFile/FileBackupExtension/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.filebackupextension", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/CoreFile/FileBackupExtension/AppScope/resources/base/element/string.json b/CoreFile/FileBackupExtension/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..57edf168387dd07561e5d29380f455d62df5a64b --- /dev/null +++ b/CoreFile/FileBackupExtension/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "FileBackupExtension" + } + ] +} diff --git a/CoreFile/FileBackupExtension/AppScope/resources/base/media/app_icon.png b/CoreFile/FileBackupExtension/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/CoreFile/FileBackupExtension/AppScope/resources/base/media/app_icon.png differ diff --git a/CoreFile/FileBackupExtension/README_zh.md b/CoreFile/FileBackupExtension/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..09d629b4276220db32da30533f440186e27501c4 --- /dev/null +++ b/CoreFile/FileBackupExtension/README_zh.md @@ -0,0 +1,71 @@ +# 应用接入数据备份恢复 + +## 介绍 + +应用接入数据备份恢复需要通过配置BackupExtensionAbility实现。 + +BackupExtensionAbility,是[Stage模型](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/application-models/stage-model-development-overview.md)模型中扩展组件[ ExtensionAbility](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/application-models/extensionability-overview.md)的派生类。开发者可以通过修改配置文件定制备份恢复框架的行为,包括是否允许备份恢复,备份哪些文件等。 + +本sample主要给备份恢复服务提供应用,用于生成数据、删除数据和备份恢复后显示数据。该工程中展示的代码详细描述可查如下链接。 + +- [应用接入数据备份恢复](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/app-file-backup-extension.md) + +## 效果预览 + +| 初始界面 | 文件创建 | 文件删除 | 文件恢复后显示 | +| -------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------- | +| | | | | + +使用说明: + +1. 点击按钮“文件创建”,应用会生成5个txt文件,大小在1Byte到1024Byte之间,用于校验备份和恢复的数据为同一数据。 +2. 本应用仅适用于生成和显示数据,具体的备份和恢复的操作需要另外的应用AppFileBackup来执行。 +3. 按钮“文件删除”操作用户在备份恢复的测试验证过程中删除文件。 + +## 工程目录 +``` +entry/src/main/ets/ +|---Application +|---Common +| |---Logger.ts // 日志工具 +| |---BackupExtension.ets // 备份恢复类 +|---entruability +| |---EntryAbility.ts // Ability类 +|---entrybackability +| |---EntryBackupAbility.ts +|---fileFs +| |---CreateFile.ts // 文件的创建和删除封装 +|---pages +| |---Index.ets // 首页 +``` +## 具体实现 + +1. 备份恢复框架的开发步骤,请参考介绍中应用接入数据备份恢复链接。 +1. 应用封装CreateFile类,其中包含个函数,用于文件的创建和删除,具体代码实现请参考:CreateFile.ets。 + +## 相关权限 + +无 + +## 依赖 + +该应用为备份恢复服务的框架实现,仅进行文件的创建和删除,不涉及备份和恢复的具体流程,数据文件的备份和恢复依赖于AppFileBackup应用。 + +## 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.1.1 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.1.1 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.1.1 Release及以上。 + +## 下载 + +如需单独下载本工程,执行如下命令: +``` +git init +git config core.sparsecheckout true +echo CoreFile/FileBackupExtension > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master + +``` diff --git a/CoreFile/FileBackupExtension/build-profile.json5 b/CoreFile/FileBackupExtension/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c97e4d39298e58d6e5eef88d2301eebd6085a13c --- /dev/null +++ b/CoreFile/FileBackupExtension/build-profile.json5 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.1.1(19)", + "compatibleSdkVersion": "5.1.1(19)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/code-linter.json5 b/CoreFile/FileBackupExtension/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/CoreFile/FileBackupExtension/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/.gitignore b/CoreFile/FileBackupExtension/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/build-profile.json5 b/CoreFile/FileBackupExtension/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/hvigorfile.ts b/CoreFile/FileBackupExtension/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d28cb60475cede46d0aa36973096d5544dbcd1 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/FileBackupExtension/entry/obfuscation-rules.txt b/CoreFile/FileBackupExtension/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/oh-package.json5 b/CoreFile/FileBackupExtension/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/common/BackupExtension.ets b/CoreFile/FileBackupExtension/entry/src/main/ets/common/BackupExtension.ets new file mode 100644 index 0000000000000000000000000000000000000000..27a91659304a8b5b72b33aafce1061526688022c --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/common/BackupExtension.ets @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start on_backup_restore] +import BackupExtensionAbility, { BundleVersion } from '@ohos.application.BackupExtensionAbility'; +import Logger from '../common/Logger'; + + +interface ErrorInfo { + type: string, + errorCode: number, + errorInfo: string +} + +export default class BackupExtension extends BackupExtensionAbility { + async onBackup() { + Logger.info(`onBackup ok`); + } + + async onRestore(bundleVersion: BundleVersion) { + Logger.info(`onRestore ok ${JSON.stringify(bundleVersion)}`); + Logger.info(`onRestore end`); + } +} + +class BackupExt extends BackupExtensionAbility { + //onBackupEx + async onBackupEx(backupInfo: string): Promise { + console.log(`onBackupEx ok`); + let errorInfo: ErrorInfo = { + type: 'ErrorInfo', + errorCode: 0, + errorInfo: 'app diy error info' + } + return JSON.stringify(errorInfo); + } + + // onRestoreEx + async onRestoreEx(bundleVersion: BundleVersion, restoreInfo: string): Promise { + console.log(`onRestoreEx ok ${JSON.stringify(bundleVersion)}`); + let errorInfo: ErrorInfo = { + type: 'ErrorInfo', + errorCode: 0, + errorInfo: 'app diy error info' + } + return JSON.stringify(errorInfo); + } +} +// [End on_backup_restore] diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/common/Logger.ts b/CoreFile/FileBackupExtension/entry/src/main/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..fbf4ecb0c07cea0cdd0a221849791c22de1a4976 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string = '[Sample_FileBackupExtension]'; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0000; // 应用的编码 + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_FileBackupExtension]'); + diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/entryability/EntryAbility.ets b/CoreFile/FileBackupExtension/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc2839f203ba057c186e19b0cbbbf80c8faa8b3 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/CoreFile/FileBackupExtension/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/fileFs/CreateFile.ts b/CoreFile/FileBackupExtension/entry/src/main/ets/fileFs/CreateFile.ts new file mode 100644 index 0000000000000000000000000000000000000000..fc6aafa4649a292243bab89797f00e78a2a8017c --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/fileFs/CreateFile.ts @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Logger from '../common/Logger'; +import { fileIo as fs } from '@kit.CoreFileKit'; +import { BusinessError } from '@ohos.base'; + +const ONE_KILOBYTE: number = 1024; // 1k = 1024B +const FILE_NUM: number = 5; // 创建文件的数量 + +export default class CreatFile { + baseDir: string = AppStorage.get('sanBoxFileDir') + '/TextDir'; + + constructor() { + } + + async createTestFiles(filePath: string): Promise { + try { + let num = FILE_NUM; + if (!fs.accessSync(filePath)) { + fs.mkdirSync(filePath); + } + let dpath = filePath; + Logger.info('sanBoxFileDir = ' + dpath); + Logger.info('num is = ' + num); + for (let i = 0; i < num; i++) { + let myFile = dpath + `/TestFile_${i}.txt`; + Logger.info('readyFile myFile = ' + myFile); + let file = fs.openSync(myFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); + fs.writeSync(file.fd, new ArrayBuffer(ONE_KILOBYTE * Math.random())); + fs.closeSync(file); + } + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.error('Failed to prepare media files, error:' + error.message + error.code); + } + } + + async deleteTestFiles(filePath: string): Promise { + try { + let num = FILE_NUM; + if (!fs.accessSync(filePath)) { + fs.mkdirSync(filePath); + } + let dpath = filePath; + Logger.info('sanBoxFileDir = ' + dpath); + Logger.info('num is = ' + num); + for (let i = 0; i < num; i++) { + let myFile = dpath + `/TestFile_${i}.txt`; + fs.unlink(myFile).then(() => { + Logger.info('remove file succeed'); + }).catch((err: BusinessError) => { + Logger.error('remove file failed with error message: ' + err.message + err.code); + }); + } + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.error('Failed to prepare media files, error:' + error.message + error.code); + } + } +} + + diff --git a/CoreFile/FileBackupExtension/entry/src/main/ets/pages/Index.ets b/CoreFile/FileBackupExtension/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..c828e1b00a90a2608643f6dcb507ad46ae378091 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import CreateFile from '../fileFs/CreateFile'; +import Logger from '../common/Logger'; +import fs from '@ohos.file.fs'; +import { common } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; + +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; +let countFile = 0; // 文件数量计数初始化 + +@Entry +@Component +struct BackupExample { + createFile = new CreateFile(); + baseDir: string = filesDir; + @State filePathSize: Array = []; + @State showFilePath: Array = []; + + onPageShow() { + try { + if (!fs.accessSync(this.baseDir)) { + fs.mkdirSync(this.baseDir); + // 数组初始化 + this.showFilePath[0] = ''; + this.filePathSize[0] = ''; + return; + } + Logger.info(`readyFileToFileFs successful`); + } catch (e) { + let error: BusinessError = e as BusinessError; + Logger.error(`readyFileToFileFs has failed for: {message: ${error.message}, code: ${error.code}}`); + } + let filenames = fs.listFileSync(this.baseDir); + countFile = filenames.length; + for (let i = 0; i < filenames.length; i++) { + Logger.info('filename:' + filenames[i]); + this.showFilePath[i] = filenames[i]; + let filePath = this.baseDir + '/' + filenames[i]; + this.filePathSize[i] = fs.statSync(filePath).size.toString() + 'Byte'; + Logger.info('arrayFilename: ' + i + this.showFilePath[i].toString()); + } + } + + build() { + Column() { + Text($r('app.string.FileData')) + .fontSize(14) + .fontColor($r('sys.color.font_primary')) + .margin({ top: 8, left: 48, bottom: 8 }) + .id('fileData') + .opacity(0.6) + .align(Alignment.TopStart) + .width('93%') + List({ space: 10, initialIndex: 0 }) { + ForEach(this.showFilePath, (item: string, index?: number) => { + ListItem() { + Column() { + Row() { + Text(' ' + item) + .fontSize(16) + .fontColor($r('sys.color.black')) + .width('70%') + .textAlign(TextAlign.Start) + .fontWeight(500) + .margin({ left: 20 }) + .id('file' + index) + if (index !== undefined) { + Text(this.filePathSize[index]) + .fontSize(14) + .width('20%') + .textAlign(TextAlign.End) + .fontColor($r('sys.color.black')) + .fontWeight(400) + .margin({ right: 16 }) + .opacity(0.6) + .id('size' + index) + } + } + .width('100%') + .height(56) + + if (this.showFilePath[0] !== '') { + Divider() + .strokeWidth('1vp') + .color($r('sys.color.black')) + .opacity(0.05) + .margin({ left: 24, right: 24 }) + .width('90%') + } + } + .width('100%') + } + }, (item: string) => item) + } + .height('80%') + .width('93%') + .borderRadius(24) + .backgroundColor(0xFFFFFF) + .align(Alignment.Center) + + Row() { + Button($r('app.string.CreateFiles')) + .id('createFiles') + .backgroundColor($r('sys.color.brand')) + .margin(15) + .width('35%') + .borderRadius(20) + .onClick(async () => { + await this.createFile.createTestFiles(this.baseDir); + this.onPageShow(); + }) + Button($r('app.string.FileDelete')) + .backgroundColor($r('sys.color.brand')) + .margin(15) + .width('35%') + .borderRadius(20) + .onClick(async () => { + await this.createFile.deleteTestFiles(this.baseDir); + for (let i = 0; i < countFile; i++) { + this.showFilePath[i] = ''; + } + }) + } + } + .width('100%') + .height('100%') + .backgroundColor('#F1F3F5') + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/module.json5 b/CoreFile/FileBackupExtension/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f683de16b7ab74290fce217fea27538e3170447b --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/module.json5 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "permissions": [ + ] + } + ], + // [Start extension_abilities] + "extensionAbilities": [ + { + "name": "BackupExtension", + "srcEntry": "./ets/common/BackupExtension.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + // [End extension_abilities] + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/color.json b/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/string.json b/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..c3f27a70fcfacd862b66e5f8712545f3275ae0ec --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/base/element/string.json @@ -0,0 +1,32 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "FileBackup" + }, + { + "name": "CreateFiles", + "value": "文件创建" + }, + { + "name": "FileData", + "value": "文件数据" + }, + { + "name": "FilelistWaitingToBeGenerated", + "value": "文件列表正在生成" + }, + { + "name": "FileDelete", + "value": "文件删除" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/background.png b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/background.png differ diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/foreground.png b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/foreground.png differ diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/layered_image.json b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/startIcon.png b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/CoreFile/FileBackupExtension/entry/src/main/resources/base/media/startIcon.png differ diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/backup_config.json b/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..8c0d561a7345eca6f6c09a118983d0d9e67becf5 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,11 @@ +{ + "allowToBackupRestore": true, + "includes": [ + "data/storage/el2/base/haps/*/files/" + ], + "excludes": [ + "" + ], + "fullBackupOnly": false, + "restoreDeps": "" +} diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/main_pages.json b/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/CoreFile/FileBackupExtension/entry/src/main/resources/dark/element/color.json b/CoreFile/FileBackupExtension/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/mock/mock-config.json5 b/CoreFile/FileBackupExtension/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/Index.test.ets b/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..08c87e09a68dffe7f2027022f38f19e6c5f2ec2c --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component, abilityDelegatorRegistry } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const DELAY_TIME = 1200; // 延时1.2秒 +const TAG = '[Sample_FileBackupExtension]'; +const DOMAIN = 0xF811; +const BUNDLE = 'FileBackupExtension_'; + +const DELEGATOR = abilityDelegatorRegistry.getAbilityDelegator(); +const BUNDLENAME = abilityDelegatorRegistry.getArguments().bundleName; +const ABILITYDELEGATOR = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = ABILITYDELEGATOR.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function IndexTest() { + describe('IndexTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin'); + // start tested ability + const want: Want = { + bundleName: BUNDLENAME, + abilityName: 'EntryAbility' + }; + await DELEGATOR.startAbility(want); + // check top display ability + const ability: UIAbility = await DELEGATOR.getCurrentTopAbility(); + hilog.info(DOMAIN, TAG, BUNDLE + 'get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('TestAbility'); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end'); + }) + /** + * @tc.number FileBackupExtension_001 + * @tc.name FileBackupExtension_001 + * @tc.desc 文件的创建 + */ + it(BUNDLE + 'FileBackupExtension_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'FileBackupExtension_001 begin'); + let str = await getResourceString($r('app.string.CreateFiles')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + hilog.info(DOMAIN, TAG, BUNDLE + 'Create the file'); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'FileBackupExtension_001 end'); + }) + /** + * @tc.number FileBackupExtension_002 + * @tc.name FileBackupExtension_002 + * @tc.desc 文件删除 + */ + it(BUNDLE + 'FileBackupExtension_002', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'FileBackupExtension_002 begin'); + let str = await getResourceString($r('app.string.FileDelete')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + hilog.info(DOMAIN, TAG, BUNDLE + 'Delete the file'); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'FileBackupExtension_002 end'); + }) + }) +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/List.test.ets b/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00cfe9627bd61a31322328fd121fab7f4d2f6d64 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import IndexTest from './Index.test'; + +export default function testsuite() { + IndexTest(); +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/ohosTest/module.json5 b/CoreFile/FileBackupExtension/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/CoreFile/FileBackupExtension/entry/src/test/List.test.ets b/CoreFile/FileBackupExtension/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/entry/src/test/LocalUnit.test.ets b/CoreFile/FileBackupExtension/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/CoreFile/FileBackupExtension/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/CoreFile/FileBackupExtension/hvigor/hvigor-config.json5 b/CoreFile/FileBackupExtension/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/CoreFile/FileBackupExtension/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/CoreFile/FileBackupExtension/hvigorfile.ts b/CoreFile/FileBackupExtension/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4beb74fe5b573059b972acf9312d33ea1703c016 --- /dev/null +++ b/CoreFile/FileBackupExtension/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/FileBackupExtension/oh-package.json5 b/CoreFile/FileBackupExtension/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9b142d655b140175b33fe2a0c804ca498119f87f --- /dev/null +++ b/CoreFile/FileBackupExtension/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/CoreFile/FileBackupExtension/ohosTest.md b/CoreFile/FileBackupExtension/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..5bfa93327d5ba626833fd473c94994ca758745a6 --- /dev/null +++ b/CoreFile/FileBackupExtension/ohosTest.md @@ -0,0 +1,10 @@ +# 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| -------- | ---------------- | ---- | -------------- | -------- | -------- | +| 拉起应用 | 设备正常运行 | \ | 应用被拉起 | 是 | pass | +| 文件创建 | 应用被拉起 | \ | 输出创建的文件 | 是 | pass | +| 文件删除 | 文件已经成功创建 | \ | 文件被删除 | 是 | pass | + diff --git a/CoreFile/FileBackupExtension/screenshots/fileCreate.jpg b/CoreFile/FileBackupExtension/screenshots/fileCreate.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cf78db1bf3eedf3d0a5abc40e8a94346d5bbc55 Binary files /dev/null and b/CoreFile/FileBackupExtension/screenshots/fileCreate.jpg differ diff --git a/CoreFile/FileBackupExtension/screenshots/fileDelete.jpg b/CoreFile/FileBackupExtension/screenshots/fileDelete.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69661629a3143f1ece356f07943eaa7e528f1260 Binary files /dev/null and b/CoreFile/FileBackupExtension/screenshots/fileDelete.jpg differ diff --git a/CoreFile/FileBackupExtension/screenshots/fileRestore.jpg b/CoreFile/FileBackupExtension/screenshots/fileRestore.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3cf78db1bf3eedf3d0a5abc40e8a94346d5bbc55 Binary files /dev/null and b/CoreFile/FileBackupExtension/screenshots/fileRestore.jpg differ diff --git a/CoreFile/FileBackupExtension/screenshots/start.jpg b/CoreFile/FileBackupExtension/screenshots/start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c754711035cdae672df8e5951ffe2569aceb9577 Binary files /dev/null and b/CoreFile/FileBackupExtension/screenshots/start.jpg differ diff --git a/CoreFile/FileSample/.gitignore b/CoreFile/FileSample/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/CoreFile/FileSample/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/CoreFile/FileSample/AppScope/app.json5 b/CoreFile/FileSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5f5ec44f1980783800b35f0907b4c64262e2ef4b --- /dev/null +++ b/CoreFile/FileSample/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.filesample", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/CoreFile/FileSample/AppScope/resources/base/element/string.json b/CoreFile/FileSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..ef4815cfeafb046482f6a75a843340b81ff3c9bf --- /dev/null +++ b/CoreFile/FileSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "FileSample" + } + ] +} diff --git a/CoreFile/FileSample/AppScope/resources/base/media/app_icon.png b/CoreFile/FileSample/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/CoreFile/FileSample/AppScope/resources/base/media/app_icon.png differ diff --git a/CoreFile/FileSample/README_zh.md b/CoreFile/FileSample/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..399e1286852b9d4ddc6f56b9cb2c151096d80b6b --- /dev/null +++ b/CoreFile/FileSample/README_zh.md @@ -0,0 +1,107 @@ +# 应用文件访问(ArKTS) + +## 介绍 + +本实例主要实现了对应用沙箱目录下的文件的访问,使用ohos.file.fileuri 、ohos.file.fs、ohos.file.statvfs、ohos.application.Want 。实现了文件的创建、读写、内容复制、文件流的使用、文件哈希流的使用、文件系统空间大小的获取以及对分享文件的接收和读取功能,该工程中展示的代码详细描述可查如下链接。 + +- [ 应用文件访问(ArkTS)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/app-file-access.md) + +## 效果预览 + +| 应用成功启动界面 | 文件访问结果 | +| ------------------------------------------------- | ----------------------------------------------- | +| | | + +使用说明: + +1. 本应用主要是对应用的沙箱文件进行访问,同时能获取到文件系统的存储空间大小。 +2. 在主界面中通过点击相应的按钮,应用可以完成相应的功能,完成的反馈将如日志的形式出现在主界面的上半部分。 +3. 本应用涉及到了对分享文件的接收和读取,在使用分享文件的应用通过弹窗选择跳转到本应用之后,点击“查看分享的文件数据”可以读取到分享文件的内容。 + +## 工程目录 + +``` +//应用文件访问 +FileSample +├──entry/src/main +| ├──ets +| | ├──commom +| | | ├──Logger.ts // 日志工具 +| | ├──entryability +| | | └──EntryAbility.ets // 程序入口类 +| | ├──entrybackupability +| | | └──EntryBackupAbility.ets +| | ├──fileFs +| | | └──fileFs.ets // 文件访问函数 +| | └──pages // 页面文件 +| | └──Index.ets // 主界面 +| ├──resources // 资源文件目录 +``` + +## 具体实现 + +- 在应用开始访问文件之前,使用UIAbilityContext[获取UIAbility的上下文信息](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/application-models/uiability-usage.md),然后调用Context的相关接口获取应用的沙箱文件路径。 + +- 文件的新建、读写、内容复制、查看文件列表、文件流的使用、文件哈希流的使用的功能函数都集成在fileFs.ets文件中,源码参考:fileFs.ets。 + +- 使用fs.openSync、fs.writeSync、fs.readSync、fs.closeSync分别用来来创建文件夹、打开文件、写文件、读文件、关闭文件,文件接口请参考:[ohos.file.fs](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md) + +- 使用[ohos.file.statvfs](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-statvfs.md)、ohos.file.storageStatistics提供的API获取文件系统空间和应用空间的大小。 + +- 该应用涉及对分享文件的接收和读取,需要配置[ module.json5](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/quick-start/module-configuration-file.md)文件,示例如下。 + + ``` + { + "module": { + ... + "abilities": [ + { + ... + "skills": [ + { + ... + "actions": [ + "ohos.want.action.sendData" + ], + "uris": [ + { + "scheme": "file", + "type": "text/plain" + } + ] + } + ] + } + ] + } + } + + ``` + +## 相关权限 + +无 + +## 依赖 + +不涉及 + +## 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.1.1 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.1.1 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.1.1 Release及以上。 + +## 下载 + +如需单独下载本工程,执行如下命令 + +``` +git init +git config core.sparsecheckout true +echo CoreFile/FileSample > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +``` + diff --git a/CoreFile/FileSample/build-profile.json5 b/CoreFile/FileSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..da50e1f91f33c91d395e77f588491fe8334862d4 --- /dev/null +++ b/CoreFile/FileSample/build-profile.json5 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.1.1(19)", + "compatibleSdkVersion": "5.1.1(19)", + "runtimeOS": "HarmonyOS" + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/.gitignore b/CoreFile/FileSample/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/CoreFile/FileSample/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/CoreFile/FileSample/entry/build-profile.json5 b/CoreFile/FileSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..eed6635f664fa08b992d84590bf62be7e0bb5381 --- /dev/null +++ b/CoreFile/FileSample/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/hvigorfile.ts b/CoreFile/FileSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d28cb60475cede46d0aa36973096d5544dbcd1 --- /dev/null +++ b/CoreFile/FileSample/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/FileSample/entry/obfuscation-rules.txt b/CoreFile/FileSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..fdbb5b9852d7dd5f39bddaeb21ab5ee1f3346749 --- /dev/null +++ b/CoreFile/FileSample/entry/obfuscation-rules.txt @@ -0,0 +1,22 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/CoreFile/FileSample/entry/oh-package.json5 b/CoreFile/FileSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/CoreFile/FileSample/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/CoreFile/FileSample/entry/src/main/ets/common/Logger.ts b/CoreFile/FileSample/entry/src/main/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..c755aa416c9ec0cdbc0cee1b21a029e5d4a5ddd9 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string = '[Sample_FileSample]'; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0000; // 应用的编码 + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_FileSample]'); + diff --git a/CoreFile/FileSample/entry/src/main/ets/entryability/EntryAbility.ets b/CoreFile/FileSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..2c599114f21e8c01711dd9808ecf62a7b84e9dff --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import Logger from '../common/Logger'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; // 日志标签 + +export default class EntryAbility extends UIAbility { + async onNewWant(want: Want): Promise { + Logger.info('Received want object:' + JSON.stringify(want)); + // 获取分享文件的 URI + let uri: string | undefined = want.uri; + await AppStorage.setOrCreate('URI', uri); + if (uri === '') { + Logger.info('uri is invalid'); + return; + } + } + + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', `Failed to load the content. Cause: %{public}s`, JSON.stringify(err) ?? ''); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onBackground'); + } +} diff --git a/CoreFile/FileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/CoreFile/FileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..a69a50694c914b9952b3e5115d6c9c6329389873 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; // 日志标签 + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', `onRestore ok %{public}s`, JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/ets/fileFs/FileFs.ets b/CoreFile/FileSample/entry/src/main/ets/fileFs/FileFs.ets new file mode 100644 index 0000000000000000000000000000000000000000..291a8eda75bb8732ed55a048e0b44fe21515ccea --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/ets/fileFs/FileFs.ets @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start create_Write_File] +// [Start read_Write_File] +// [Start streams_Read_Write_File] +// [Start view_File_List] +// [Start streams_file] +// [Start hash_File_Stream] +import { fileIo as fs, ReadOptions, WriteOptions, ListFileOptions } from '@kit.CoreFileKit'; +import { buffer } from '@kit.ArkTS'; +import { common } from '@kit.AbilityKit'; +import { hash } from '@kit.CoreFileKit'; +import Logger from '../common/Logger'; + +// 获取应用文件沙箱路径 +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; + +// [StartExclude create_Write_File] +const BUFFER: number = 1024; // 读取文件数据的缓冲区大小 +const READSIZE: number = 0; // 初始化读取的字节数为 0 + +// [EndExclude create_Write_File] + +export function createFile(): string { + // 新建并打开文件 + let file = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // 写入一段内容至文件 + let writeLen = fs.writeSync(file.fd, 'Try to write str : hello world'); + Logger.info('The length of str is: ' + writeLen); + // 从文件读取一段内容 + let arrayBuffer = new ArrayBuffer(BUFFER); + let readOptions: ReadOptions = { + offset: 0, // 从文件的开头开始读取 + length: arrayBuffer.byteLength + }; + let readLen = fs.readSync(file.fd, arrayBuffer, readOptions); + let buf = buffer.from(arrayBuffer, 0, readLen); // 这个 Buffer 对象是 arrayBuffer 中从位置 0 开始的前 readLen 字节 + Logger.info('the content of file: ' + buf.toString()); + let str = 'the content of file: ' + buf.toString(); + // 关闭文件 + fs.closeSync(file); + return str; +} + +// [End create_Write_File] + +// 读取文件内容并写入到另一个文件 test.txt => testFile.txt +export function readWriteFile(): void { + // 打开文件 + let srcFile = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + let destFile = fs.openSync(filesDir + '/testFile.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // 读取源文件内容并写入至目的文件 + let bufSize = BUFFER; + let readSize = READSIZE; + let buf = new ArrayBuffer(bufSize); + let readOptions: ReadOptions = { + offset: readSize, + length: bufSize + }; + let readLen = fs.readSync(srcFile.fd, buf, readOptions); + while (readLen > 0) { // 循环继续,直到没有更多数据可以读取 + readSize += readLen; + let writeOptions: WriteOptions = { + length: readLen + }; + fs.writeSync(destFile.fd, buf, writeOptions); + readOptions.offset = readSize; + readLen = fs.readSync(srcFile.fd, buf, readOptions); + Logger.info('test.txt => testFile.txt'); + } + // 关闭文件 + fs.closeSync(srcFile); + fs.closeSync(destFile); +} + +// [End read_Write_File] + +// 以流的形式读写文件test.txt => destFile.txt +export async function readWriteFileWithStream(): Promise { + // 打开文件流 + let inputStream = fs.createStreamSync(filesDir + '/test.txt', 'r+'); + let outputStream = fs.createStreamSync(filesDir + '/destFile.txt', 'w+'); + // 以流的形式读取源文件内容并写入目的文件 + let bufSize = BUFFER; + let readSize = READSIZE; + let buf = new ArrayBuffer(bufSize); + let readOptions: ReadOptions = { + offset: readSize, + length: bufSize + }; + let readLen = await inputStream.read(buf, readOptions); + readSize += readLen; + while (readLen > 0) { // 循环继续,直到没有更多数据可以读取 + const writeBuf = readLen < bufSize ? buf.slice(0, readLen) : buf; + await outputStream.write(writeBuf); + readOptions.offset = readSize; + readLen = await inputStream.read(buf, readOptions); + readSize += readLen; + } + // 关闭文件流 + inputStream.closeSync(); + outputStream.closeSync(); +} + +// [End streams_Read_Write_File] + +// 查看文件列表 +export function getListFile(): string { + let str = ''; + let listFileOption: ListFileOptions = { + recursion: false, + listNum: 0, // 0 表示不限制文件数量 + filter: { + suffix: ['.png', '.jpg', '.txt', '.jpeg', '.json'], + displayName: ['*'], + fileSizeOver: 0, // 0 表示列出所有文件,不限制文件大小 + lastModifiedAfter: new Date(0).getTime() // 返回的时间戳是0 + } + }; + let files = fs.listFileSync(filesDir, listFileOption); + for (let i = 0; i < files.length; i++) { + Logger.info(`The name of file: ${files[i]}`); + str += files[i] + '\n'; + } + return str; +} + +// [End view_File_List] + +// 使用文件流 +export function copyFileWithReadable(): void { + // 创建文件可读流 + const rs = fs.createReadStream(`${filesDir}/test.txt`); + // 创建文件可写流 + const ws = fs.createWriteStream(`${filesDir}/destFile.txt`); + // 暂停模式拷贝文件 + rs.on('readable', () => { + const data = rs.read(); + if (!data) { + return; + } + ws.write(data); + }); +} + +export function copyFileWithData(): void { + // 创建文件可读流 + const rs = fs.createReadStream(`${filesDir}/testFile.txt`); + // 创建文件可写流 + const ws = fs.createWriteStream(`${filesDir}/destFile.txt`); + // 流动模式拷贝文件 + rs.on('data', (emitData) => { + const data = emitData?.data; + if (!data) { + return; + } + ws.write(data as Uint8Array); + }); +} + +// [End streams_file] + +// 使用文件哈希流 +export function hashFileWithStream() { + const filePath = `${filesDir}/test.txt`; + // 创建文件可读流 + const rs = fs.createReadStream(filePath); + // 创建哈希流 + const hs = hash.createHash('sha256'); + rs.on('data', (emitData) => { + const data = emitData?.data; + // 0 表示获取字符串中第一个字符的 字符编码 (即 Unicode 编码点)的值 + hs.update(new Uint8Array(data?.split('').map((x: string) => x.charCodeAt(0))).buffer); + }); + rs.on('close', async () => { + const hashResult = hs.digest(); + const fileHash = await hash.hash(filePath, 'sha256'); + Logger.info(`hashResult: ${hashResult}, fileHash: ${fileHash}`); + }); +} + +// [End hash_File_Stream] + +// 根据文件名读取文件内容 +export function readFile(fileName: string): string { + let file = fs.openSync(filesDir + '/' + fileName + '.txt', fs.OpenMode.READ_ONLY); + let arrayBuffer = new ArrayBuffer(BUFFER); + let readOptions: ReadOptions = { + offset: 0, // 从文件的开头开始读取 + length: arrayBuffer.byteLength + }; + let readLen = fs.readSync(file.fd, arrayBuffer, readOptions); + // 这个 buf 对象是 arrayBuffer 中从位置 0 开始的前 readLen 字节 + let buf = buffer.from(arrayBuffer, 0, readLen); + Logger.info('the content of file: ' + buf.toString()); + let str = 'the content of file: ' + buf.toString(); + return str; +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/ets/pages/Index.ets b/CoreFile/FileSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..58dca08ce332e587f27ae5352af5a6c2aa86daf1 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start import_starf_storageStatistics] +import { common } from '@kit.AbilityKit'; +import { statfs } from '@kit.CoreFileKit'; +import { buffer } from '@kit.ArkTS'; +import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { storageStatistics } from '@kit.CoreFileKit'; +import Logger from '../common/Logger'; +import { + createFile, + readWriteFile, + getListFile, + readWriteFileWithStream, + readFile, + copyFileWithReadable, + copyFileWithData, + hashFileWithStream +} from '../fileFs/FileFs'; + +// [StartExclude import_starf_storageStatistics] +const BUFFER: number = 1024; // 读取文件缓冲区 +const MARGIN = 5; // 组件间的间隔 +// [EndExclude import_starf_storageStatistics] + +// 获取应用文件路径 +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; +// [End import_starf_storageStatistics] + +// [Start get_share_file] +function getShareFile(): string { + let strFile = ''; + try { + let URI: string | undefined = AppStorage.get('URI'); + if (URI === null || URI === undefined) { + Logger.info('uri is invalid'); + let str = 'uri is invalid'; + return str; + } + try { + // 根据需要对被分享文件的URI进行相应操作。例如读写的方式打开URI获取file对象 + let file = fs.openSync(URI, fs.OpenMode.READ_WRITE); + Logger.info('open file successfully!'); + // [StartExclude get_share_file] + // 1024为读取文件内容的缓冲区大小 + let arrayBuffer = new ArrayBuffer(BUFFER); + let readOptions: ReadOptions = { + offset: 0, // 从文件的开头开始读取 + length: arrayBuffer.byteLength + }; + let readLen = fs.readSync(file.fd, arrayBuffer, readOptions); + // 这个 buf 对象是 arrayBuffer 中从位置 0 开始的前 readLen 字节 + let buf = buffer.from(arrayBuffer, 0, readLen); + Logger.info('the content of file: ' + buf.toString()); + // 关闭文件 + strFile = 'the content of file: ' + buf.toString(); + fs.closeSync(file); + // [EndExclude get_share_file] + } catch (err) { + let error: BusinessError = err as BusinessError; + Logger.info(`Invoke openSync failed, code is ${error.code}, message is ${error.message}`); + } + } catch (error) { + let err: BusinessError = error as BusinessError; + Logger.info(`Invoke openSync failed, code is ${err.code}, message is ${err.message}`); + } + return strFile; +} + +// [End get_share_file] + +@Entry +@Component +export default struct Index { + @State message: string = ''; + @State filename: string = ''; + + build() { + Column() { + TextArea({ + text: this.message, + placeholder: '', + }) + .width('100%') + .height('40%') + TextInput({ + text: 'test' + }) + .width('100%') + .height('5%') + .onChange((value) => this.filename = value) + Row() { + Button($r('app.string.createWriteReadfile')) + .width('25%') + .height('100%') + .onClick(() => { + this.message += createFile() + '\n'; + }) + Button($r('app.string.copyDocument')) + .width('25%') + .height('100%') + .onClick(() => { + readWriteFile(); + readWriteFileWithStream(); + copyFileWithReadable(); + copyFileWithData(); + }) + Button($r('app.string.ReadFile')) + .width('25%') + .height('100%') + .onClick(() => { + this.message += readFile(this.filename) + '\n'; + }) + Button($r('app.string.GetFileList')) + .width('25%') + .height('100%') + .onClick(() => { + this.message += getListFile() + '\n'; + }) + } + .width('100%') + .height('8%') + .margin(MARGIN) + + Button($r('app.string.getFileSystemSize')) + .width('80%') + .height('6%') + .margin(MARGIN) + .onClick(() => { + // [Start statfs_get_FreeSize] + statfs.getFreeSize(filesDir, (err: BusinessError, number: number) => { + if (err) { + Logger.info(`Invoke getFreeSize failed, code is ${err.code}, message is ${err.message}`); + } else { + Logger.info(`Invoke getFreeSize succeeded, size is ${number}`); + // [StartExclude statfs_get_FreeSize] + this.message += 'The size of the remaining space in the file system data: ' + number.toString() + '\n'; + // [EndExclude statfs_get_FreeSize] + } + }); + // [End statfs_get_FreeSize] + }) + Button($r('app.string.appStorageSpaceSize')) + .width('80%') + .height('6%') + .margin(MARGIN) + .onClick(() => { + // [Start storageStatistics_getCurrentBundleStats] + storageStatistics.getCurrentBundleStats((err: BusinessError, bundleStats: storageStatistics.BundleStats) => { + if (err) { + Logger.info(`Invoke getCurrentBundleStats failed, code is ${err.code}, message is ${err.message}`); + } else { + Logger.info(`Invoke getCurrentBundleStats succeeded, appsize is ${bundleStats.appSize}`); + // [StartExclude storageStatistics_getCurrentBundleStats] + this.message += 'The size of the storage space in the system: ' + bundleStats.appSize.toString() + '\n'; + // [EndExclude storageStatistics_getCurrentBundleStats] + } + }); + // [End storageStatistics_getCurrentBundleStats] + }) + Row() { + Button($r('app.string.hash')) + .onClick(() => { + hashFileWithStream(); + }) + .width('50%') + .height('90%') + Button($r('app.string.getShareFile')) + .onClick(() => { + this.message += getShareFile() + '\n'; + let str: string | undefined = AppStorage.get('URI'); + this.message += str + '\n'; + }) + .width('50%') + .height('90%') + } + .width('100%') + .height('8%') + .margin(MARGIN) + } + .width('100%') + .height('100%') + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .backgroundColor('rgb(242,242,242)') + } +} + diff --git a/CoreFile/FileSample/entry/src/main/module.json5 b/CoreFile/FileSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c69216e1564056b43eb4d648b42894b32d660573 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/module.json5 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.want.action.sendData" + ], + "uris": [ + { + "scheme": "file", + "type": "text/plain", + } + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": true, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ], + + } +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/base/element/color.json b/CoreFile/FileSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/base/element/string.json b/CoreFile/FileSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..9a02a50e7a25f36886b5e6c59b08e5ff718cf5f0 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,52 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "FileManagement" + }, + { + "name": "Dataflow", + "value": "跨设备数据流转" + }, + { + "name": "createWriteReadfile", + "value": "读写文件" + }, + { + "name": "copyDocument", + "value": "文件复制" + }, + { + "name": "ReadFile", + "value": "读取文件内容" + }, + { + "name": "GetFileList", + "value": "获取文件列表" + }, + { + "name": "getFileSystemSize", + "value": "获取文件系统数据分区剩余空间大小" + }, + { + "name": "appStorageSpaceSize", + "value": "获取当前应用的存储空间大小" + }, + { + "name": "getShareFile", + "value": "读取分享文件" + }, + { + "name": "hash", + "value": "hash计算" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/base/media/background.png b/CoreFile/FileSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/CoreFile/FileSample/entry/src/main/resources/base/media/background.png differ diff --git a/CoreFile/FileSample/entry/src/main/resources/base/media/foreground.png b/CoreFile/FileSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/CoreFile/FileSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/CoreFile/FileSample/entry/src/main/resources/base/media/layered_image.json b/CoreFile/FileSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/base/media/startIcon.png b/CoreFile/FileSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/CoreFile/FileSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/CoreFile/FileSample/entry/src/main/resources/base/profile/backup_config.json b/CoreFile/FileSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..207fff904845be0165b51080e8f03d9e6c1a5a6e --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,11 @@ +{ + "allowToBackupRestore": true, + "includes": [ + "data/app/el2/100/base/com.example.filesample/haps/entry/files" + ], + "excludes": [ + "" + ], + "fullBackupOnly": false, + "restoreDeps": "" +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/base/profile/main_pages.json b/CoreFile/FileSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..55c3f007f87b7ce5206d325f968cc56f2f79441f --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/en_US/element/string.json b/CoreFile/FileSample/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1dc636333435db1dbd8b802c647dea5b69a6e052 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,52 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "FileManagement" + }, + { + "name": "Dataflow", + "value": "Dataflow" + }, + { + "name": "createWriteReadfile", + "value": "WriteReadFile" + }, + { + "name": "copyDocument", + "value": "copyDocument" + }, + { + "name": "ReadFile", + "value": "ReadFile" + }, + { + "name": "GetFileList", + "value": "GetFileList" + }, + { + "name": "getFileSystemSize", + "value": "getFileSystemSize" + }, + { + "name": "appStorageSpaceSize", + "value": "appStorageSpaceSize" + }, + { + "name": "getShareFile", + "value": "getShareFile" + }, + { + "name": "hash", + "value": "hash" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/main/resources/zh_CN/element/string.json b/CoreFile/FileSample/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..195fb38ff0cebc3bf1475d7c3302162c9012a398 --- /dev/null +++ b/CoreFile/FileSample/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,52 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "FileManagement" + }, + { + "name": "Dataflow", + "value": "跨设备数据流转" + }, + { + "name": "createWriteReadfile", + "value": "读写文件" + }, + { + "name": "copyDocument", + "value": "文件复制" + }, + { + "name": "ReadFile", + "value": "读取文件内容" + }, + { + "name": "GetFileList", + "value": "获取文件列表" + }, + { + "name": "getFileSystemSize", + "value": "获取文件系统数据分区剩余空间大小" + }, + { + "name": "appStorageSpaceSize", + "value": "获取当前应用的存储空间大小" + }, + { + "name": "getShareFile", + "value": "读取分享文件" + }, + { + "name": "hash", + "value": "hash" + } + ] +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/ohosTest/ets/test/Index.test.ets b/CoreFile/FileSample/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1d8d629fb04fb4d8a3e4a6b29e1d8761c8344762 --- /dev/null +++ b/CoreFile/FileSample/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component, abilityDelegatorRegistry } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; + +const DELAY_TIME = 1500; // 延时1.5秒 +const TAG = '[Sample_ApplicationFile]'; +const DOMAIN = 0xF811; +const BUNDLE = 'FileSample_'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function IndexTest() { + describe('IndexTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin'); + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + hilog.info(DOMAIN, TAG, BUNDLE + 'get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end'); + }) + /** + * @tc.number fileAccessTest_001 + * @tc.name fileAccessTest_001 + * @tc.desc 文件的创建和读写 + */ + it(BUNDLE + 'fileAccessTest_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_001 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.createWriteReadfile')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_001 end'); + }) + /** + * @tc.number fileAccessTest_002 + * @tc.name fileAccessTest_002 + * @tc.desc 文件内容复制test.txt => destFile.txt + */ + it(BUNDLE + 'fileAccessTest_002', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_002 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.copyDocument')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_002 end'); + }) + /** + * @tc.number fileAccessTest_003 + * @tc.name fileAccessTest_003 + * @tc.desc 读取文件内容 + */ + it(BUNDLE + 'fileAccessTest_003', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_003 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.ReadFile')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_003 end'); + }) + /** + * @tc.number fileAccessTest_004 + * @tc.name fileAccessTest_004 + * @tc.desc 获取文件列表 + */ + it(BUNDLE + 'fileAccessTest_004', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_004 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.GetFileList')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_004 end'); + }) + /** + * @tc.number fileAccessTest_005 + * @tc.name fileAccessTest_005 + * @tc.desc 获取文件系统数据分区剩余空间大小 + */ + it(BUNDLE + 'fileAccessTest_005', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_005 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.getFileSystemSize')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_005 end'); + }) + /** + * @tc.number fileAccessTest_006 + * @tc.name fileAccessTest_006 + * @tc.desc 获取当前应用的存储空间大小 + */ + it(BUNDLE + 'fileAccessTest_006', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_006 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.appStorageSpaceSize')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_006 end'); + }) + /** + * @tc.number fileAccessTest_007 + * @tc.name fileAccessTest_007 + * @tc.desc 文件哈希流计算 + */ + it(BUNDLE + 'fileAccessTest_007', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_007 begin'); + let driver: Driver = Driver.create(); + let str = await getResourceString($r('app.string.hash')); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'fileAccessTest_007 end'); + }) + }) +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/ohosTest/ets/test/List.test.ets b/CoreFile/FileSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00cfe9627bd61a31322328fd121fab7f4d2f6d64 --- /dev/null +++ b/CoreFile/FileSample/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import IndexTest from './Index.test'; + +export default function testsuite() { + IndexTest(); +} \ No newline at end of file diff --git a/CoreFile/FileSample/entry/src/ohosTest/module.json5 b/CoreFile/FileSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/CoreFile/FileSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/CoreFile/FileSample/hvigor/hvigor-config.json5 b/CoreFile/FileSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..43beb743cbd25c3507b1cf8a744bf8197b3bf2fb --- /dev/null +++ b/CoreFile/FileSample/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/CoreFile/FileSample/hvigorfile.ts b/CoreFile/FileSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4beb74fe5b573059b972acf9312d33ea1703c016 --- /dev/null +++ b/CoreFile/FileSample/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/FileSample/oh-package.json5 b/CoreFile/FileSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..952ab183532e81c9c50e5de1e64393704e1e48fe --- /dev/null +++ b/CoreFile/FileSample/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.18", + "@ohos/hamock": "1.0.0" + } +} diff --git a/CoreFile/FileSample/ohosTest.md b/CoreFile/FileSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..b6d3f1eb0b0d7ab7e946cbb230d692d97eadfefb --- /dev/null +++ b/CoreFile/FileSample/ohosTest.md @@ -0,0 +1,14 @@ +# 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| -------------------------------- | ------------ | ------ | ------------------------------ | -------- | -------- | +| 文件创建并写入 | 设备正常运行 | | test.txt文件内容 | 是 | pass | +| 文件内容复制 | 设备正常运行 | | | 是 | pass | +| 读取文件内容 | 设备正常运行 | 文件名 | 对应文件的内容 | 是 | pass | +| 获取文件列表 | 设备正常运行 | | 文件列表 | 是 | pass | +| 获取文件系统数据分区剩余空间大小 | 设备正常运行 | | 数字字符串,表示空间大小 | 是 | pass | +| 获取当前应用的存储空间大小 | 设备正常运行 | | 数字字符串,表示空间大小 | 是 | pass | +| 文件哈希计算 | 设备正常运行 | | 日志中输出hashResult和fileHash | 是 | pass | + diff --git a/CoreFile/FileSample/screenshots/end.jpg b/CoreFile/FileSample/screenshots/end.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3d3cfb94f2b7eac681407b338617e7a3ba303e3b Binary files /dev/null and b/CoreFile/FileSample/screenshots/end.jpg differ diff --git a/CoreFile/FileSample/screenshots/start.jpg b/CoreFile/FileSample/screenshots/start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d84880049d93e1ba0ca2233826e14e6bf2cb355e Binary files /dev/null and b/CoreFile/FileSample/screenshots/start.jpg differ diff --git a/CoreFile/NDKAppFileSample/.gitignore b/CoreFile/NDKAppFileSample/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/CoreFile/NDKAppFileSample/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/AppScope/app.json5 b/CoreFile/NDKAppFileSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..089e8345e9c895c6ae4c940f5da3da4847971c2a --- /dev/null +++ b/CoreFile/NDKAppFileSample/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "app": { + "bundleName": "com.samples.ndkappfilesample", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/CoreFile/NDKAppFileSample/AppScope/resources/base/element/string.json b/CoreFile/NDKAppFileSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..42807f9a7ded386aef72f7d636ade1e532944576 --- /dev/null +++ b/CoreFile/NDKAppFileSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NDKAppFileSample" + } + ] +} diff --git a/CoreFile/NDKAppFileSample/AppScope/resources/base/media/app_icon.png b/CoreFile/NDKAppFileSample/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/CoreFile/NDKAppFileSample/AppScope/resources/base/media/app_icon.png differ diff --git a/CoreFile/NDKAppFileSample/README_zh.md b/CoreFile/NDKAppFileSample/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..c2da3920e4729ba995e5af19e60dca00a3b58a3f --- /dev/null +++ b/CoreFile/NDKAppFileSample/README_zh.md @@ -0,0 +1,103 @@ +# 应用文件访问(C++) + +## 介绍 + + 本实例主要实现了使用C++的方式去访问应用沙箱目录下的文件,使用接口FileManagement_ErrCode OH_FileIO_GetFileLocation(char *uri, int uriLength, FileIO_FileLocation *location),接口的详细说明请参考:FileIO。主要实现的功能是:使用文件uri作为入参,调用C语言函数去访问应用文件,并确定文件的存储位置。该工程中展示的代码详细描述可查如下链接。 + +- [应用文件访问(C/C++)](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/native-fileio-guidelines.md) + +## 效果预览 + +| 应用启动界面 | 文件访问结果 | +| ------------------------------------------------- | ----------------------------------------------- | +| | | + +使用说明: + +1. 本应用主要使用napi的方式,使用C语言函数对应用的沙箱文件进行访问,可以在创建文件后向napi定义的函数传递文件的uri参数,通过uri对文件进行访问,并确定文件的存储文件是本地还是云端。 +2. 在启动应用之后,按顺序点击界面上的两个按钮,先创建文件,在对文件进行访问,通过日的反馈知道访问的结果。 + +## 工程目录 + +``` +NDKAppFileSample +├──entry/src/main +| ├──cpp +| | ├──types +| | | ├──libentry +| | | └──CMakeLists.txt // CMake脚本文件 +| | | └──napi_init.cpp // napi函数封装类 +| ├──ets +| | ├──commom +| | | ├──Logger.ts // 封装日志类 +| | ├──entryability +| | | └──EntryAbility.ets // 程序入口类 +| | ├──entrybackupability +| | | └──EntryBackupAbility.ets +| | ├──fileFs +| | | └──fileFs.ets // 文件创建函数封装 +| | └──pages // 页面文件 +| | └──Index.ets // 主界面 +| ├──resources // 资源文件目录 +``` + +## 具体实现 + +1. 在CMake脚本中链接动态库,即在CMakeLists.txt中添加以下lib。 + + ``` + target_link_libraries(sample PUBLIC libohfileio.so) + ``` + +2. 添加头文件 + + ``` + #include + ``` + +3. 调用OH_FileIO_GetFileLocation接口获取文件存储位置。示例代码如下所示: + + ```c + void GetFileLocationExample() { + char *uri = "file://com.example.demo/data/storage/el2/base/files/test.txt"; + FileIO_FileLocation location; + FileManagement_ErrCode ret = OH_FileIO_GetFileLocation(uri, strlen(uri), &location); + if (ret == 0) { + if (location == FileIO_FileLocation::LOCAL) { + printf("This file is on local."); + } else if (location == FileIO_FileLocation::CLOUD) { + printf("This file is on cloud."); + } else if (location == FileIO_FileLocation::LOCAL_AND_CLOUD) { + printf("This file is both on local and cloud."); + } + } else { + printf("GetFileLocation failed, error code is %d", ret); + } + } + ``` + +## 相关权限 + +无 + +## 依赖 + +不涉及 + +## 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.1.1 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.1.1 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.1.1 Release及以上。 + +## 下载 + +``` +git init +git config core.sparsecheckout true +echo CoreFile/NDKAppFileSample > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +``` + diff --git a/CoreFile/NDKAppFileSample/build-profile.json5 b/CoreFile/NDKAppFileSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8023497dff665539e99399a5bc0cbbe3b06ad9a2 --- /dev/null +++ b/CoreFile/NDKAppFileSample/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.1.1(19)", + "targetSdkVersion": "5.1.1(19)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "externalNativeOptions": { + "abiFilters": [ + "arm64-v8a", + "x86_64" + ] + } + } + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/code-linter.json5 b/CoreFile/NDKAppFileSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/CoreFile/NDKAppFileSample/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/.gitignore b/CoreFile/NDKAppFileSample/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/build-profile.json5 b/CoreFile/NDKAppFileSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..01bed8940ff6f2d5843f8d1d7e184725f59be699 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/build-profile.json5 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/hvigorfile.ts b/CoreFile/NDKAppFileSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d28cb60475cede46d0aa36973096d5544dbcd1 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/NDKAppFileSample/entry/obfuscation-rules.txt b/CoreFile/NDKAppFileSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/oh-package.json5 b/CoreFile/NDKAppFileSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..118bdd4fe7699368a010e04c24f5bfc887cf1298 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/oh-package.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/cpp/CMakeLists.txt b/CoreFile/NDKAppFileSample/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..57d6c2cf3bb86f1612ebfdd21dcb1de6f94fb50a --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(NDKAppFileSample) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED napi_init.cpp) +target_link_libraries(entry PUBLIC libace_napi.z.so PUBLIC libohfileio.so PUBLIC libhilog_ndk.z.so) \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/cpp/napi_init.cpp b/CoreFile/NDKAppFileSample/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8fa5a676a9e2ea0f7acd7d015de39bbb22b24063 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "napi/native_api.h" +#include +#include "hilog/log.h" +#include + +#undef LOG_TAG +#define LOG_TAG "Sample_NDKAppFileAccess" + +// [Start get_file_location] +static napi_value GetFileLocation(napi_env env, napi_callback_info info) { + // [StartExclude get_file_location] + size_t argc = 1; + napi_value args[1] = {nullptr}; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // 确保传入了一个参数 + if (argc < 1) { + napi_throw_error(env, nullptr, "Expected one argument"); + return nullptr; + } + // 确保传入的是字符串 + napi_valuetype valuetype; + napi_typeof(env, args[0], &valuetype); + if (valuetype != napi_string) { + napi_throw_error(env, nullptr, "Argument should be a string"); + return nullptr; + } + // 获取字符串的长度 + size_t strLength = 0; + napi_get_value_string_utf8(env, args[0], nullptr, 0, &strLength); + // [EndExclude get_file_location] + // 为 char* uri 分配内存 + char *uri = new char[strLength + 1]; // +1 for null terminator + // 将 JavaScript 字符串复制到 uri + // [StartExclude get_file_location] + napi_get_value_string_utf8(env, args[0], uri, strLength + 1, &strLength); + // 输出 uri 字符串(用于调试) + OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.WatcherType=OnTrigger: %{public}s", uri); + // [EndExclude get_file_location] + FileIO_FileLocation location; + FileManagement_ErrCode ret = OH_FileIO_GetFileLocation(uri, strlen(uri), &location); + if (ret == 0) { + if (location == FileIO_FileLocation::LOCAL) { + OH_LOG_INFO(LogType::LOG_APP, "This file is on local."); + } else if (location == FileIO_FileLocation::CLOUD) { + OH_LOG_INFO(LogType::LOG_APP, "This file is on cloud."); + } else if (location == FileIO_FileLocation::LOCAL_AND_CLOUD) { + OH_LOG_INFO(LogType::LOG_APP, "This file is both on local and cloud."); + } + } else { + OH_LOG_INFO(LogType::LOG_APP, "GetFileLocation failed, error code is %{public}d", ret); + } + // [StartExclude get_file_location] + // 如果需要返回值,可以创建一个 JavaScript 字符串返回 + napi_value result; + napi_create_string_utf8(env, uri, strLength, &result); + return result; + // [EndExclude get_file_location] +} +// [End get_file_location] +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor desc[] = { + {"getFileLocation", nullptr, GetFileLocation, nullptr, nullptr, nullptr, napi_default, nullptr}}; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); } diff --git a/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/Index.d.ts b/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..3fda4ca42101d8cab805328d9c0cd5bd4cb914fd --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const getFileLocation: (uri: string) => string; \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/oh-package.json5 b/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6abf3b7c20f22c62aaac6a995a25cae672f73f35 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/ets/common/Logger.ts b/CoreFile/NDKAppFileSample/entry/src/main/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..e8235b04f40ae9b505e231b1313793d02f08cad4 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string = '[Sample_NDKAppFileSample]'; + private format: string = `%{public}s`; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0000; // 应用的编码 + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_NDKAppFileSample]'); + diff --git a/CoreFile/NDKAppFileSample/entry/src/main/ets/entryability/EntryAbility.ets b/CoreFile/NDKAppFileSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..5afd14516d50a8898c7a11765e5d4bd211c95e10 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; // 应用的编码 + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', `Failed to load the content. Cause: %{public}s`, JSON.stringify(err) ?? ''); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onBackground'); + } +}; diff --git a/CoreFile/NDKAppFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/CoreFile/NDKAppFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..bfb5ec138342078036fc8b9fcacec64c20eb6621 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; // 应用的编码 + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', `onRestore ok %{public}s`, JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/ets/fileFs/FileFs.ets b/CoreFile/NDKAppFileSample/entry/src/main/ets/fileFs/FileFs.ets new file mode 100644 index 0000000000000000000000000000000000000000..2633102d17d9c6bad26058458c0ebcc394131e8f --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/ets/fileFs/FileFs.ets @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { common } from '@kit.AbilityKit'; +import { fileIo as fs, ReadOptions } from '@kit.CoreFileKit'; +import { buffer } from '@kit.ArkTS'; +import Logger from '../common/Logger'; + +const BUFFER: number = 1024; // 读取文件缓冲区大小 + +// 获取应用文件沙箱路径 +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; + +export function createFile(): string { + // 新建并打开文件 + let file = fs.openSync(filesDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // 写入一段内容至文件 + let writeLen = fs.writeSync(file.fd, 'Try to write str : hello world'); + Logger.info('The length of str is: ' + writeLen); + // 从文件读取一段内容 + let arrayBuffer = new ArrayBuffer(BUFFER); + let readOptions: ReadOptions = { + offset: 0, // 从文件的开头开始读取 + length: arrayBuffer.byteLength + }; + let readLen = fs.readSync(file.fd, arrayBuffer, readOptions); + // 这个 buf 对象是 arrayBuffer 中从位置 0 开始的前 readLen 字节 + let buf = buffer.from(arrayBuffer, 0, readLen); + Logger.info('the content of file: ' + buf.toString()); + let str = 'the content of file: ' + buf.toString(); + // 关闭文件 + fs.closeSync(file); + return str; +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/ets/pages/Index.ets b/CoreFile/NDKAppFileSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..9fc336f799b2cb05621e11c26f5f0574f986647f --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { fileUri } from '@kit.CoreFileKit'; +import { common } from '@kit.AbilityKit'; +import testNapi from 'libentry.so'; +import { createFile } from '../fileFs/FileFs'; + +// 获取应用文件沙箱路径 +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; + +let filePath = filesDir + '/test.txt'; +let uri = fileUri.getUriFromPath(filePath); + +@Entry +@Component +struct Index { + @State message: string = ''; + + build() { + Column() { + TextArea({ + text: this.message, + placeholder: '', + }) + .width('100%') + .height('50%') + Row() { + Button($r('app.string.createWriteReadfile')) + .onClick(() => { + this.message += createFile() + '\n'; + }) + Button($r('app.string.DetermineFileLocation')) + .onClick(() => { + this.message += testNapi.getFileLocation(uri) + '\n'; + }) + } + + } + } +} diff --git a/CoreFile/NDKAppFileSample/entry/src/main/module.json5 b/CoreFile/NDKAppFileSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e1157a62520d73a3244b923d000b9260e80b9538 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/module.json5 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.want.action.sendData" + ], + "uris": [ + { + "scheme": "file", + "type": "text/plain", + } + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/color.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/string.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..57b6b1f4e1a87e3f7609aacfa61ae54d38a3f917 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "NDKAppFileSample" + }, + { + "name": "createWriteReadfile", + "value": "创建文件" + }, + { + "name": "DetermineFileLocation", + "value": "判定文件位置" + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/background.png b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/background.png differ diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/foreground.png b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/layered_image.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/startIcon.png b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/backup_config.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/main_pages.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/en_US/element/string.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..9ba2ee7b69a77dfedf93e5868affa5c61baf82c3 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "NDKAppFileSample" + }, + { + "name": "createWriteReadfile", + "value": "createWriteReadFile" + }, + { + "name": "DetermineFileLocation", + "value": "DetermineFileLocation" + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/main/resources/zh_CN/element/string.json b/CoreFile/NDKAppFileSample/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..8621b9837a0a8b0102487df6cbc319bcd4181ee9 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "NDKAppFileSample" + }, + { + "name": "createWriteReadfile", + "value": "创建文件" + }, + { + "name": "DetermineFileLocation", + "value": "判定文件位置" + } + ] +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/common/Logger.ts b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a9cb046a71466af03fd6a64c86231711f04a534 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string = '[Sample_NDKAppFileSample]'; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0xF811; + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_NDKAppFileSample]'); + diff --git a/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/Index.test.ets b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..94e7242f7b5de15bde7c221a631548c8c4e9c184 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component, abilityDelegatorRegistry, } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import Logger from '../common/Logger'; + +const DELAY_TIME = 1500; // 延时1.5秒 +const BUNDLE = 'NDKAppFileAccess_'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function IndexTest() { + describe('IndexTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + Logger.info('StartAbility_001 begin'); + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + Logger.info('get top ability'); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + done(); + Logger.info('StartAbility_001 end'); + }) + /** + * @tc.number NDKFileAccessTest_001 + * @tc.name NDkFileAccessTest_001 + * @tc.desc 文件的创建 + */ + it(BUNDLE + 'fileAccessTest_001', 0, async () => { + Logger.info(BUNDLE + 'NDKFileAccessTest_001 begin'); + let str = await getResourceString($r('app.string.createWriteReadfile')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + Logger.info(BUNDLE + 'NDKFileAccessTest_001 end'); + }) + /** + * @tc.number NDKFileAccessTest_002 + * @tc.name NDKFileAccessTest_002 + * @tc.desc 判断文件位置 + */ + it(BUNDLE + 'fileAccessTest_002', 0, async () => { + Logger.info(BUNDLE + 'NDKFileAccessTest_002 begin'); + let str = await getResourceString($r('app.string.DetermineFileLocation')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + Logger.info(BUNDLE + 'NDKFileAccessTest_002 end'); + }) + }) +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/List.test.ets b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00cfe9627bd61a31322328fd121fab7f4d2f6d64 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import IndexTest from './Index.test'; + +export default function testsuite() { + IndexTest(); +} \ No newline at end of file diff --git a/CoreFile/NDKAppFileSample/entry/src/ohosTest/module.json5 b/CoreFile/NDKAppFileSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/CoreFile/NDKAppFileSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/CoreFile/NDKAppFileSample/hvigor/hvigor-config.json5 b/CoreFile/NDKAppFileSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..43beb743cbd25c3507b1cf8a744bf8197b3bf2fb --- /dev/null +++ b/CoreFile/NDKAppFileSample/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/CoreFile/NDKAppFileSample/hvigorfile.ts b/CoreFile/NDKAppFileSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4beb74fe5b573059b972acf9312d33ea1703c016 --- /dev/null +++ b/CoreFile/NDKAppFileSample/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/NDKAppFileSample/oh-package.json5 b/CoreFile/NDKAppFileSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..93f097993a458e967d6d5239ea0580e79b5d6998 --- /dev/null +++ b/CoreFile/NDKAppFileSample/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/CoreFile/NDKAppFileSample/ohosTest.md b/CoreFile/NDKAppFileSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..0dbec0172a36f3c74ceebdac99fa4c8fb71704bf --- /dev/null +++ b/CoreFile/NDKAppFileSample/ohosTest.md @@ -0,0 +1,10 @@ +# 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------ | ------------ | ---- | -------------------------- | -------- | -------- | +| 拉起应用 | 设备正常运行 | | 成功拉起应用,主页元素齐备 | 是 | Pass | +| 创建文件 | 设备正常运行 | | 文件内容 | 是 | Pass | +| 确定文件位置 | 文件成功创建 | | 文件URI | 是 | pass | + diff --git a/CoreFile/NDKAppFileSample/screenshots/end.jpg b/CoreFile/NDKAppFileSample/screenshots/end.jpg new file mode 100644 index 0000000000000000000000000000000000000000..791d48cb3a9f4f37d328f08bc29d11d01aa750e4 Binary files /dev/null and b/CoreFile/NDKAppFileSample/screenshots/end.jpg differ diff --git a/CoreFile/NDKAppFileSample/screenshots/start.jpg b/CoreFile/NDKAppFileSample/screenshots/start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..180a127cf5e6263c47b2c0df1d0fd14242f81ee2 Binary files /dev/null and b/CoreFile/NDKAppFileSample/screenshots/start.jpg differ diff --git a/CoreFile/SandBoxShare/.gitignore b/CoreFile/SandBoxShare/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/CoreFile/SandBoxShare/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/CoreFile/SandBoxShare/AppScope/app.json5 b/CoreFile/SandBoxShare/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..58e0d787bddb87947f18502f18258d0cdcfd2a2b --- /dev/null +++ b/CoreFile/SandBoxShare/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.sandboxshare", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/CoreFile/SandBoxShare/AppScope/resources/base/element/string.json b/CoreFile/SandBoxShare/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..cff118d84662eedd9c8e51bd304e52ee7dabddb2 --- /dev/null +++ b/CoreFile/SandBoxShare/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "SandboxShare" + } + ] +} diff --git a/CoreFile/SandBoxShare/AppScope/resources/base/media/app_icon.png b/CoreFile/SandBoxShare/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/CoreFile/SandBoxShare/AppScope/resources/base/media/app_icon.png differ diff --git a/CoreFile/SandBoxShare/README_zh.md b/CoreFile/SandBoxShare/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..8c4f07c2e95a47cdddf836d1b9c2e929f7f7ea65 --- /dev/null +++ b/CoreFile/SandBoxShare/README_zh.md @@ -0,0 +1,69 @@ +# 应用文件分享 + +本示例主要展示了沙箱文件分享相关的功能,使用 ohos.file.fileuri、ohos.file.fs、ohos.ability.wantConstant、ohos.application.Want 等接口,实现了获取文件uri、创建沙箱文件、提供want中操作want常数、应用组件间的信息传递的功能,该工程中展示的代码详细描述可查如下链接。 + +- [ 应用文件分享](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/file-management/share-app-file.md) + +### 效果预览 + +| 创建文件界面 | 选择分享应用弹窗 | 应用接收文件并读取 | +| ------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------- | +| | | | + +使用说明: + +1. 因本应用的功能依赖FileSample(code/DocsSample/CoreFile/FileSample)应用,在使用本应用之前首先应安装FileSample应用,文件分享之前使FileSample应用在后台。 +2. 在主界面,可以点击创建文件按钮,在沙箱目录下创建一个txt文件,通过“查看文件列表”和“获取文件内容”按钮分别获取文件列表和test.txt文件的内容。 +3. 点击“文件分享”按钮,可以拉起分享弹窗,选择要接收的应用之后,该应用就会被拉起,接收传递的want参数后可以根据对应的URI对分享的文件进行读写。 + +### 工程目录 +``` +├──entry/src/main +| ├──ets +| | ├──common +| | | └──Logger.ts // 日志工具 +| | ├──entryability +| | | └──EntryAbility.ets // 程序入口类 +| | ├──entrybackupability +| | | └──EntryBackupAbility.ets +| | ├──fileFs +| | | └──fileFs.ets // 文件访问函数 +| | └──pages // 页面文件 +| | └──Index.ets // 主界面 +| ├──resources // 资源文件目录 +``` +### 具体实现 + +* 增添文件、查找指定类型文件、获取文件uri、传递want信息启动ability的功能接口封装在fileFs.ts,源码参考:FileFs.ts + + * 使用fs.openSync、fs.writeSync、fs.readSync、fs.closeSync分别用来打开文件、写文件、读文件、关闭文件。文件接口请参考:[@ohos.file.fs](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md) + + * 使用fileUri.getUriFromPath来获取文件uri,文件URI的获取请参考接口文档:[@ohos.file.fileuri](https://gitee.com/openharmony/docs/blob/OpenHarmony-5.0.1-Release/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fileuri.md) + + * 分享文件至FileSample应用打开并读取。 + * 调用 implicitStartAbility 方法传递want参数启动新的ability。 + +### 相关权限 + +无 + +### 依赖 + +本应用需要依赖FileSample应用和NDKAppFileSample应用,启动前预先安装这两个应用才可以进行自动化测试,若只安装了FileSample依赖应用,请删除SandBoxShare_005测试用例,沙箱文件需分享至FileSample应用打开并读取内容。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.1.1 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.1.1 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.1.1 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: +``` +git init +git config core.sparsecheckout true +echo CoreFile/SandBoxShare > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master diff --git a/CoreFile/SandBoxShare/build-profile.json5 b/CoreFile/SandBoxShare/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..da50e1f91f33c91d395e77f588491fe8334862d4 --- /dev/null +++ b/CoreFile/SandBoxShare/build-profile.json5 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.1.1(19)", + "compatibleSdkVersion": "5.1.1(19)", + "runtimeOS": "HarmonyOS" + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/.gitignore b/CoreFile/SandBoxShare/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/build-profile.json5 b/CoreFile/SandBoxShare/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..eed6635f664fa08b992d84590bf62be7e0bb5381 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/hvigorfile.ts b/CoreFile/SandBoxShare/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3d28cb60475cede46d0aa36973096d5544dbcd1 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/SandBoxShare/entry/obfuscation-rules.txt b/CoreFile/SandBoxShare/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..fdbb5b9852d7dd5f39bddaeb21ab5ee1f3346749 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/obfuscation-rules.txt @@ -0,0 +1,22 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/oh-package.json5 b/CoreFile/SandBoxShare/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/CoreFile/SandBoxShare/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/CoreFile/SandBoxShare/entry/src/main/ets/common/Logger.ts b/CoreFile/SandBoxShare/entry/src/main/ets/common/Logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..e0eee3f39440db85d4ea0263431c02d5ef0f9366 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/ets/common/Logger.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private domain: number; + private prefix: string = '[Sample_SandBoxShare]'; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0000; // 应用的编码 + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]): void { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number): void { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_SandBoxShare]'); + diff --git a/CoreFile/SandBoxShare/entry/src/main/ets/entryability/EntryAbility.ets b/CoreFile/SandBoxShare/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..c742f2424d9d26aa2f0d9cf1d1926720b9a0066f --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; // 日志标签 + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', `Failed to load the content. Cause: %{public}s`, JSON.stringify(err) ?? ''); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + + + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', `%{public}s`, 'Ability onBackground'); + } +} diff --git a/CoreFile/SandBoxShare/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/CoreFile/SandBoxShare/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..517f05cca4407c42faef72bec99e1d1bd4cfdbff --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; // 改为自己应用的编号 + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', `onRestore ok %{public}s`, JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/ets/fileFs/FileFs.ets b/CoreFile/SandBoxShare/entry/src/main/ets/fileFs/FileFs.ets new file mode 100644 index 0000000000000000000000000000000000000000..7ff68ab5321137121b123e5573939f25763aad3b --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/ets/fileFs/FileFs.ets @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start application_file_share] +// [Start get_uri] +import { common } from '@kit.AbilityKit'; +import { fileIo as fs, ReadOptions, ListFileOptions } from '@kit.CoreFileKit'; +import Logger from '../common/Logger'; +import { buffer } from '@kit.ArkTS'; +import { fileUri } from '@kit.CoreFileKit'; +import { Want, wantConstant } from '@kit.AbilityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; + +// 获取应用文件路径 +let context = getContext(this) as common.UIAbilityContext; +let filesDir = context.filesDir; + +// 分享应用文件 +export async function shareFile(fileName: string): Promise { + // 获取文件的沙箱路径 + let pathInSandbox = context.filesDir + '/' + fileName + '.txt'; + // 将沙箱路径转换为uri + let uri = fileUri.getUriFromPath(pathInSandbox); + // [End get_uri] + Logger.info('FilePath is : ' + uri); + let want: Want = { + // 配置被分享文件的读写权限,例如对被分享应用进行读写授权 + flags: wantConstant.Flags.FLAG_AUTH_WRITE_URI_PERMISSION | wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION, + // 配置分享应用的隐式拉起规则 + action: 'ohos.want.action.sendData', + uri: uri, + type: 'text/plain', + }; + await context.startAbility(want) + .then(() => { + Logger.info('Invoke getCurrentBundleStats succeeded.'); + }) + .catch((err: BusinessError) => { + Logger.error(`Invoke startAbility failed, code is ${err.code}, message is ${err.message}`); + }); +} + +// [End application_file_share] +// 新建并读写一个文件test1.txt +export function createFile(): number { + // 新建并打开文件 + let file = fs.openSync(filesDir + '/test1.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + // 写入一段内容至文件 + let writeLen = fs.writeSync(file.fd, 'Share file test1.txt from SandboxShare'); + Logger.info('The length of str is: ' + writeLen); + // 关闭文件 + fs.closeSync(file); + return writeLen; +} + +// 读取文件内容 +export function readFile(fileName: string): string { + let file = fs.openSync(filesDir + '/' + fileName + '.txt', fs.OpenMode.READ_WRITE); + // 创建一个大小为1024字节的ArrayBuffer对象,用于存储从文件中读取的数据 + let arrayBuffer = new ArrayBuffer(1024); + let readOptions: ReadOptions = { + offset: 0, // 从文件的开头开始读取 + length: arrayBuffer.byteLength + }; + let readLen = fs.readSync(file.fd, arrayBuffer, readOptions); + let buf = buffer.from(arrayBuffer, 0, readLen); // 这个 Buffer 对象是 arrayBuffer 中从位置 0 开始的前 readLen 字节 + Logger.info('the content of file: ' + buf.toString()); + // 关闭文件 + let str = 'the content of file: ' + buf.toString(); + fs.closeSync(file); + return str; +} + +// 查看文件列表 +export function getListFile(): string { + let str = ''; + let listFileOption: ListFileOptions = { + recursion: false, + listNum: 0, // 0 表示不限制文件数量 + filter: { + suffix: ['.png', '.jpg', '.txt'], + displayName: ['*'], + fileSizeOver: 0, // 0 表示列出所有文件,不限制文件大小 + lastModifiedAfter: new Date(0).getTime() // 返回的时间戳是0 + } + }; + let files = fs.listFileSync(filesDir, listFileOption); + for (let i = 0; i < files.length; i++) { + Logger.info(`The name of file: ${files[i]}`); + str += files[i] + '\n'; + } + return str; +} diff --git a/CoreFile/SandBoxShare/entry/src/main/ets/pages/Index.ets b/CoreFile/SandBoxShare/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..ab5cafd899d4ba7ac37c8a2559ebde2fdb455efb --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createFile, readFile, getListFile, shareFile } from '../fileFs/FileFs'; + +const MARGIN = 5; // 组件间的间隔 + +@Entry +@Component +struct Index { + @State message: string = ''; + @State fileName: string = ''; + + build() { + Column() { + TextArea({ + text: this.message + }) + .width('100%') + .height('40%') + Text($r('app.string.ShareFileBasedOnName')) + .width('100%') + .height('5%') + TextInput({ + text: 'test1' + }) + .width('100%') + .height('6%') + .margin(MARGIN) + .onChange((value) => this.fileName = value) + Button($r('app.string.CreateFileTest')) + .margin(MARGIN) + .onClick(() => { + let writeLen = createFile(); + this.message += 'The length of str is: ' + writeLen.toString() + '\n'; + }) + Button($r('app.string.getFileList')) + .margin(MARGIN) + .onClick(() => { + this.message += getListFile() + '\n'; + }) + Button($r('app.string.ReadFile')) + .onClick(() => { + this.message += readFile(this.fileName) + '\n'; + }) + Button($r('app.string.FileShare')) + .margin(MARGIN) + .onClick(() => { + shareFile(this.fileName); + }) + } + } +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/module.json5 b/CoreFile/SandBoxShare/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..078f5c6fd0ebe30e75d4609bb94dee8b59282bc5 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/module.json5 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.want.action.sendData", + "ohos.arkui.intent.action.SEND_DATA" + ], + "uris": [ + { + "scheme": "file", + "type": "text/plain", + "host": "*", + "path": "*" + } + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/element/color.json b/CoreFile/SandBoxShare/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/element/string.json b/CoreFile/SandBoxShare/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..5dddbe4a62d280348e2308307290f91406f003f9 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/base/element/string.json @@ -0,0 +1,40 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "ShareFile" + }, + { + "name": "ShareFileBasedOnName", + "value": "根据文件名分享文件" + }, + { + "name": "CreateFileTest", + "value": "创建文本文件" + }, + { + "name": "getFileList", + "value": "获取文件列表" + }, + { + "name": "ReadFile", + "value": "读取文件内容" + }, + { + "name": "FileShare", + "value": "分享文件" + }, + { + "name": "getShareFile", + "value": "读取分享文件" + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/media/background.png b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/background.png differ diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/media/foreground.png b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/foreground.png differ diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/media/layered_image.json b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/media/startIcon.png b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/CoreFile/SandBoxShare/entry/src/main/resources/base/media/startIcon.png differ diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/backup_config.json b/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/main_pages.json b/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..55c3f007f87b7ce5206d325f968cc56f2f79441f --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/en_US/element/string.json b/CoreFile/SandBoxShare/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..de69e571331d42e8a25be933b51c1090d22fb7fa --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,40 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "ShareFile" + }, + { + "name": "ShareFileBasedOnName", + "value": "ShareFileBasedOnName" + }, + { + "name": "CreateFileTest", + "value": "CreateFileTest" + }, + { + "name": "getFileList", + "value": "GetFileList" + }, + { + "name": "ReadFile", + "value": "ReadFile" + }, + { + "name": "FileShare", + "value": "FileShare" + }, + { + "name": "getShareFile", + "value": "getShareFile" + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/main/resources/zh_CN/element/string.json b/CoreFile/SandBoxShare/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..d2a9a3b40efe8d50c1478a04b94028d8e185556c --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,40 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "ShareFile" + }, + { + "name": "ShareFileBasedOnName", + "value": "根据文件名分享文件" + }, + { + "name": "CreateFileTest", + "value": "创建文本文件" + }, + { + "name": "getFileList", + "value": "获取文件列表" + }, + { + "name": "ReadFile", + "value": "读取文件内容" + }, + { + "name": "FileShare", + "value": "分享文件" + }, + { + "name": "getShareFile", + "value": "读取分享文件" + } + ] +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/Index.test.ets b/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/Index.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..bd4251bbbf269f08785519e753ab5bbb8b7f54f3 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/Index.test.ets @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON, Component, abilityDelegatorRegistry } from '@kit.TestKit'; +import { UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; + +const DELAY_TIME = 1200; // 延时1.2秒 +const TAG = '[Sample_SandBoxShare]'; +const DOMAIN = 0xF811; +const BUNDLE = 'SandBoxShare_'; + +const delegator = abilityDelegatorRegistry.getAbilityDelegator(); +const bundleName = abilityDelegatorRegistry.getArguments().bundleName; +const abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); + +async function getResourceString(resource: Resource): Promise { + let manage = abilityDelegator.getAppContext().resourceManager; + let text = await manage.getStringValue(resource); + return text; +} + +export default function IndexTest() { + describe('IndexTest', () => { + /** + * @tc.number StartAbility_001 + * @tc.name StartAbility_001 + * @tc.desc 启动Ability + */ + it(BUNDLE + 'StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin"'); + const want: Want = { + bundleName: bundleName, + abilityName: 'EntryAbility' + }; + await delegator.startAbility(want); + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + const ability: UIAbility = await delegator.getCurrentTopAbility(); + console.info("get top ability"); + expect(ability.context.abilityInfo.name).assertEqual('EntryAbility'); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end'); + }) + /** + * @tc.number SandBoxShare_001 + * @tc.name SandBoxShare_001 + * @tc.desc 文件的创建 + */ + it(BUNDLE + 'SandBoxShare_001', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_001 begin'); + let str = await getResourceString($r('app.string.CreateFileTest')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_001 end'); + }) + /** + * @tc.number SandBoxShare_002 + * @tc.name SandBoxShare_002 + * @tc.desc 获取文件列表 + */ + it(BUNDLE + 'SandBoxShare_002', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_002 begin'); + let str = await getResourceString($r('app.string.getFileList')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_002 end'); + }) + /** + * @tc.number SandBoxShare_003 + * @tc.name SandBoxShare_003 + * @tc.desc 读取文件内容 + */ + it(BUNDLE + 'SandBoxShare_003', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_003 begin'); + let str = await getResourceString($r('app.string.ReadFile')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_003 end'); + }) + /** + * @tc.number fileAccessTest_004 + * @tc.name fileAccessTest_004 + * @tc.desc 分享文件 + */ + it(BUNDLE + 'SandBoxShare_004', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_004 begin'); + let str = await getResourceString($r('app.string.FileShare')); + let driver: Driver = Driver.create(); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_004 end'); + }) + /** + * @tc.number fileAccessTest_005 + * @tc.name fileAccessTest_005 + * @tc.desc 在另一个应用查看分享的数据 FileManagement + */ + it(BUNDLE + 'SandBoxShare_005', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_005 begin'); + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + await driver.assertComponentExist(ON.text('FileManagement')); + let button: Component = await driver.findComponent(ON.text('FileManagement')); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_005 end'); + }) + /** + * @tc.number fileAccessTest_006 + * @tc.name fileAccessTest_006 + * @tc.desc 在另一个应用查看分享的数据 + */ + it(BUNDLE + 'SandBoxShare_006', 0, async () => { + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_006 begin'); + let str = await getResourceString($r('app.string.getShareFile')); + let driver: Driver = Driver.create(); + await driver.delayMs(DELAY_TIME); + await driver.assertComponentExist(ON.text(str)); + let button: Component = await driver.findComponent(ON.text(str)); + await button.click(); + await driver.delayMs(DELAY_TIME); + hilog.info(DOMAIN, TAG, BUNDLE + 'SandBoxShare_006 end'); + }) + }) +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/List.test.ets b/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..00cfe9627bd61a31322328fd121fab7f4d2f6d64 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import IndexTest from './Index.test'; + +export default function testsuite() { + IndexTest(); +} \ No newline at end of file diff --git a/CoreFile/SandBoxShare/entry/src/ohosTest/module.json5 b/CoreFile/SandBoxShare/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/CoreFile/SandBoxShare/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/CoreFile/SandBoxShare/hvigor/hvigor-config.json5 b/CoreFile/SandBoxShare/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..43beb743cbd25c3507b1cf8a744bf8197b3bf2fb --- /dev/null +++ b/CoreFile/SandBoxShare/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/CoreFile/SandBoxShare/hvigorfile.ts b/CoreFile/SandBoxShare/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4beb74fe5b573059b972acf9312d33ea1703c016 --- /dev/null +++ b/CoreFile/SandBoxShare/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/CoreFile/SandBoxShare/oh-package.json5 b/CoreFile/SandBoxShare/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..952ab183532e81c9c50e5de1e64393704e1e48fe --- /dev/null +++ b/CoreFile/SandBoxShare/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.18", + "@ohos/hamock": "1.0.0" + } +} diff --git a/CoreFile/SandBoxShare/ohosTest.md b/CoreFile/SandBoxShare/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..a114ff37907140670a569dd5d75cb984ebeb8bcf --- /dev/null +++ b/CoreFile/SandBoxShare/ohosTest.md @@ -0,0 +1,13 @@ +# 测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| -------------- | ------------ | ---- | ------------------------------ | -------- | -------- | +| 拉起应用 | 设备正常运行 | | 成功拉起应用,主页元素齐备 | 是 | Pass | +| 创建文件 | 设备正常运行 | | 文件成功创建 | 是 | Pass | +| 获取文件列表 | 设备正常运行 | | 目录下的文件列表 | 是 | Pass | +| 读取文件内容 | 设备正常运行 | | 前面步骤中创建并写入的文件内容 | 是 | Pass | +| 分享文件 | 权限申请成功 | | 拉起应用选择弹窗 | 是 | Pass | +| 启动被分享应用 | 弹窗拉起 | | 成功启动被分享应用 | 是 | pass | + diff --git a/CoreFile/SandBoxShare/screenshots/fileReception.jpg b/CoreFile/SandBoxShare/screenshots/fileReception.jpg new file mode 100644 index 0000000000000000000000000000000000000000..531214c9ec55268509c3000ababbb1cb5a6c0f67 Binary files /dev/null and b/CoreFile/SandBoxShare/screenshots/fileReception.jpg differ diff --git a/CoreFile/SandBoxShare/screenshots/share.jpg b/CoreFile/SandBoxShare/screenshots/share.jpg new file mode 100644 index 0000000000000000000000000000000000000000..015b2a2b52d7622f03fe49016bc3cbf15a213ac6 Binary files /dev/null and b/CoreFile/SandBoxShare/screenshots/share.jpg differ diff --git a/CoreFile/SandBoxShare/screenshots/start.jpg b/CoreFile/SandBoxShare/screenshots/start.jpg new file mode 100644 index 0000000000000000000000000000000000000000..71a0f865da072f95ff0bfb265d4d0992463132c2 Binary files /dev/null and b/CoreFile/SandBoxShare/screenshots/start.jpg differ