修改问题

Signed-off-by: CZY <chenzhengyang@openvalley.net>
This commit is contained in:
CZY 2023-08-15 10:05:12 +08:00
parent aff1343f30
commit 2e15406887
593 changed files with 31772 additions and 1089 deletions

View File

@ -135,6 +135,7 @@ Note:If the text contains special characters, please escape them according to th
<filteritem type="filepath" name="code/BasicFeature/TaskManagement/WorkScheduler/signTool/hap-sign-tool.jar" desc="Provided by code/BasicFeature/TaskManagement/WorkScheduler"/>
<filteritem type="filepath" name="code/BasicFeature/Connectivity/UploadAndDownLoad/environment/hfs.exe" desc="Provided by hfs"/>
<filteritem type="filepath" name="code/Solutions/Shopping/OrangeShopping/libs/ohos-qr-code-scan-1.0.1.har" desc="Provided by media/QRCodeScan"/>
<filteritem type="filepath" name="code/Solutions/Shopping/OrangeShopping/libs/ohos-sharecomponent-1.0.2.har" desc="Provided by code/BasicFeature/ApplicationModels/CustomShare"/>
<filteritem type="filepath" name="code/BasicFeature/Connectivity/StageSocket/certificate_file.zip" desc="Provided by code/BasicFeature/Connectivity/StageSocket"/>
</filefilter>
<filefilter name="defaultPolicyFilter" desc="License文件头校验策略的过滤条件" >

View File

@ -36,7 +36,7 @@
<tr height="18" style='height:13.50pt;'>
<td width="140" align="center" rowspan="3" style='height:27.00pt' x:str><strong>UI</strong></td>
<td rowspan="2" x:str><strong>声明式开发范式</strong></td>
<td width="170" x:str><a href="code/UI/ArkTsComponentCollection/ComponentCollection">ArkTS组件集</a></td>
<td width="170" x:str><a href="code/UI/ArkTsComponentCollection/ComponentCollection">ArkTS组件集API 10</a></td>
<td width="170" x:str><a href="code/UI/ArkTsComponentCollection/Canvas">画布组件</a></td>
<td width="170" x:str><a href="code/UI/ArkTsComponentCollection/DefiningPageLayoutAndConnection">页面布局和连接</a></td>
<td width="170" x:str><a href="code/UI/ArkTsComponentCollection/Drag">拖拽事件</a></td>
@ -55,24 +55,30 @@
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td height="270" align="center" rowspan="24" style='height:202.50pt' x:str><strong>基础特性</strong></td>
<td height="270" align="center" rowspan="27" style='height:202.50pt' x:str><strong>基础特性</strong></td>
<td x:str><strong>应用模型</strong></td>
<td x:str><a href="code/BasicFeature/ApplicationModels/StageModel">Stage模型</a></td>
<td x:str><a href="code/BasicFeature/ApplicationModels/StageModel">Stage模型API 10</a></td>
<td x:str><a href="code/BasicFeature/ApplicationModels/AbilityStartMode">Ability的启动方式</a></td>
<td x:str><a href="code/BasicFeature/ApplicationModels/CustomShare">自定义分享</a></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>通知</strong></td>
<td rowspan="2" x:str><strong>通知</strong></td>
<td x:str><a href="code/BasicFeature/Notification/CustomEmitter">自定义Emitter</a></td>
<td x:str><a href="code/BasicFeature/Notification/CustomNotification">自定义通知</a></td>
<td x:str><a href="code/BasicFeature/Notification/CustomCommonEvent">公共事件的订阅和发布API 10</a></td>
<td x:str><a href="code/BasicFeature/Notification/CustomNotificationBadge">自定义通知角标API 10</a></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/BasicFeature/Notification/CustomNotificationPush">自定义通知推送API 10</a></td>
<td ></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>窗口管理</strong></td>
<td x:str><a href="code/BasicFeature/WindowManagement/WindowManage">窗口管理</a></td>
<td ></td>
<td x:str><a href="code/BasicFeature/WindowManagement/WindowRatio">窗口API 10</a></td>
<td ></td>
<td ></td>
</tr>
@ -99,13 +105,19 @@
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/BasicFeature/Media/AVRecorder">音视频录制</a></td>
<td x:str><a href="code/BasicFeature/Media/Audio">音频管理API 10</a></td>
<td ></td>
<td ></td>
<td x:str><a href="code/BasicFeature/Media/VideoPlay">视频播放</a></td>
<td x:str><a href="code/BasicFeature/Media/VoiceCallDemo">音频通话示例</td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>安全</strong></td>
<td rowspan="2"><strong>安全</strong></td>
<td x:str><a href="code/BasicFeature/Security/Cipher">加解密</a></td>
<td ><a href="code/BasicFeature/Security/AppAccountManager">应用账号管理</a></td>
<td x:str><a href="code/BasicFeature/Security/AppAccountManager">应用账号管理</a></td>
<td x:str><a href="code/BasicFeature/Security/CertificateFramework">证书算法库框架</a></td>
<td x:str><a href="code/BasicFeature/Security/CryptoFramework">通用密钥库系统cryptoFramework</a></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/BasicFeature/Security/Huks">通用密钥库系统huks</a></td>
<td x:str><a href="code/BasicFeature/Security/PaySecurely">支付</a></td>
<td ></td>
<td ></td>
</tr>
@ -118,7 +130,8 @@
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/BasicFeature/Connectivity/StageSocket">Socket连接</a></td>
<td ></td>
<td x:str><a href="code/BasicFeature/Connectivity/Bluetooth">蓝牙</a></td>
<td x:str><a href="code/BasicFeature/Connectivity/UploadAndDownLoad">上传和下载API 10</a></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
@ -130,21 +143,22 @@
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>文件管理</strong></td>
<td x:str><a href="code/BasicFeature/FileManagement/FileManager">文件管理</a></td>
<td x:str><a href="code/BasicFeature/FileManagement/FileBackupExtension">应用接入数据备份恢复API 10</a></td>
<td x:str><a href="code/BasicFeature/FileManagement/FileManager">文件管理API 10</a></td>
<td x:str><a href="code/BasicFeature/FileManagement/MediaCollections">媒体管理合集</a></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td rowspan="2" x:str><strong>设备管理</strong></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/Location">位置服务</a></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/ScreenDetector">屏幕探测</a></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/DeviceManagementCollection">设备管理合集API 10</a></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/Sensor">传感器</a></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/Vibrator/CustomHaptic">自定义振动API 10</a></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/BasicFeature/DeviceManagement/Vibrator/BasicVibration">振动</a></td>
<td x:str><a href="code/BasicFeature/DeviceManagement/Vibrator/CustomHaptic">自定义振动API 10</a></td>
<td ></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
@ -192,7 +206,6 @@
<td ></td>
<td ></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>资源</strong></td>
@ -208,17 +221,24 @@
<td x:str></td>
<td x:str></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>国际化</strong></td>
<td x:str><a href="code/BasicFeature/International/International">国际化</a></td>
<td ></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><strong>Native</strong></td>
<td x:str><a href="code/BasicFeature/Native/NdkRawfile">获取Rawfile资源</a></td>
<td ></td>
<td x:str><a href="code/BasicFeature/Native/NdkXComponent">Native XComponentAPI 10</a></td>
<td ></td>
<td ></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td height="90" align="center" rowspan="9" style='height:67.50pt;' x:str><strong>系统特性</strong></td>
<td rowspan="2" x:str><strong>应用模型</strong></td>
<td x:str><a href="code/SystemFeature/ApplicationModels/Launcher">仿桌面应用</a></td>
<td x:str><a href="code/SystemFeature/ApplicationModels/Launcher">仿桌面应用API 10</a></td>
<td x:str><a href="code/SystemFeature/ApplicationModels/MissionManager">任务管理</a></td>
<td x:str><a href="code/SystemFeature/ApplicationModels/StaticSubscriber">静态订阅</a></td>
<td x:str><a href="code/SystemFeature/ApplicationModels/AccessibilityExtAbility">无障碍扩展</a></td>
@ -281,7 +301,7 @@
<tr height="18" style='height:13.50pt;'>
<td height="90" align="center" rowspan="7" style='height:67.50pt;' x:str><strong>关键特性</strong></td>
<td rowspan="2" x:str><strong>一次开发,多端部署</strong></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities">ArkTS一多能力集合</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/AdaptiveCapabilities">ArkTS一多能力集合API 10</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/JsAdaptiveCapabilities">Js一多能力集合</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/Weather">入门示例:天气应用</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/HealthyDiet">典型页面场景:健康饮食</a></td>
@ -290,7 +310,7 @@
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/AppMarket">典型页面场景:应用市场首页</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/MusicAlbum">典型页面场景:音乐专辑页</a></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/Settings">典型页面场景:设置应用页面</a></td>
<td ></td>
<td x:str><a href="code/SuperFeature/MultiDeviceAppDev/MultiColumns">典型页面场景一多分栏控件API 10</a></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td rowspan="3" x:str><strong>分布式</strong></td>
@ -316,12 +336,12 @@
<td x:str><a href="code/SuperFeature/Widget/AdaptiveServiceWidget">Js多设备自适应服务卡片</a></td>
<td x:str><a href="code/SuperFeature/Widget/FormExtAbility">Stage模型卡片</a></td>
<td x:str><a href="code/SuperFeature/Widget/FormGame">Stage模型卡片JS与C++通信</a></td>
<td x:str><a href="code/SuperFeature/Widget/ArkTSCard/Calculator">ArkTS卡片计算器</a></td>
<td x:str><a href="code/SuperFeature/Widget/RequestAddForm">应用主动添加数据代理卡片到桌面API 10</a></td>
</tr>
<tr height="18" style='height:13.50pt;'>
<td x:str><a href="code/SuperFeature/Widget/ArkTSCard/CanvasGame">ArkTS卡片Canvas小游戏</a></td>
<td x:str><a href="code/SuperFeature/Widget/ArkTSCard/MusicControl">ArkTs音乐卡片</a></td>
<td></td>
<td x:str><a href="code/SuperFeature/Widget/ArkTSCard/Calculator">ArkTS卡片计算器</a></td>
<td></td>
</tr>
<tr height="18" style='height:13.50pt;'>

View File

@ -14,7 +14,7 @@
*/
import hilog from '@ohos.hilog';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
import { describe, it, expect } from '@ohos/hypium'
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import { Driver, ON } from '@ohos.UiTest';
@ -28,7 +28,6 @@ export default function abilityTest() {
* 拉起应用
*/
it('StartAbility_001', 0, async function (done) {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0xF811, 'testTag', 'StartAbility_001 begin');
let abilityDelegatorRegistry = AbilityDelegatorRegistry.getAbilityDelegator();
try {
@ -48,7 +47,6 @@ export default function abilityTest() {
* 检查页面
*/
it('CheckPage_001', 0, async function () {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0xF811, 'testTag', 'CheckPage_001 begin');
await DRIVER.delayMs(1000);
// 检查是否存在这三个板块
@ -62,7 +60,6 @@ export default function abilityTest() {
* 进入详情页
*/
it('CheckDetailPage_001', 0, async function () {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0xF811, 'testTag', 'CheckDetailPage_001 begin');
await DRIVER.delayMs(1000);
// 点击番茄
@ -77,9 +74,9 @@ export default function abilityTest() {
let contentTablePoint = await contentTable.getBoundsCenter();
// 向左滑动
await DRIVER.fling({
x: contentTablePoint.x + 100, y: contentTablePoint.y
x: contentTablePoint.x + 200, y: contentTablePoint.y
}, {
x: contentTablePoint.x - 100, y: contentTablePoint.y
x: contentTablePoint.x - 200, y: contentTablePoint.y
}, 50, 200);
await DRIVER.delayMs(1000);
await DRIVER.assertComponentExist(ON.id('CaloriesProgress'));
@ -100,7 +97,6 @@ export default function abilityTest() {
* 进入另个一个详情页
*/
it('CheckDetailPage_002', 0, async function () {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0xF811, 'testTag', 'CheckDetailPage_002 begin');
// 点击黄瓜
await DRIVER.delayMs(1000);

View File

@ -174,6 +174,7 @@ export default function abilityTest() {
await clickAndToast('process');
await clickAndToast('getDispatcherVersion');
await clickAndToast('getAbilityInfo');
await driver.delayMs(1000);
await driver.pressBack();
await driver.delayMs(1000);
logger.info(TAG, `${BUNDLE}Bundle_001 end`);
@ -190,6 +191,7 @@ export default function abilityTest() {
await driver.assertComponentExist(ON.text('verifyAccessToken', MatchPattern.CONTAINS))
let component = await driver.findComponent(ON.text('verifyAccessToken', MatchPattern.CONTAINS));
await component.click();
await driver.delayMs(1000);
await driver.waitForComponent(ON.type('Toast'), 2000);
await driver.delayMs(1000);
await driver.pressBack();
@ -209,6 +211,7 @@ export default function abilityTest() {
await clickAndToast('denormalizeUri');
await clickAndToast('notifyChange');
await clickAndToast('off');
await driver.delayMs(1000);
await driver.pressBack();
await driver.delayMs(1000);
logger.info(TAG, `${BUNDLE}DataShareHelper_001 end`);
@ -225,6 +228,7 @@ export default function abilityTest() {
await clickAndToast('setWakeUpScreen');
await clickAndToast('setPreferredOrientation');
await clickAndToast('getTopWindow');
await driver.delayMs(1000);
await driver.pressBack();
await driver.delayMs(1000);
logger.info(TAG, `${BUNDLE}Window_001 end`);

View File

@ -15,7 +15,7 @@
{
"module": {
"name": "advertiser_test",
"name": "entry_test",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",

View File

@ -52,7 +52,6 @@ export default function abilityTest() {
await DRIVER.delayMs(1000);
let ability = await abilityDelegatorRegistry.getCurrentTopAbility();
let manager = ability.context.resourceManager;
await DRIVER.click(676,696); // 关掉自动弹出的输入法
await DRIVER.assertComponentExist(ON.text(await manager.getStringValue($r('app.string.configuration'))));
await DRIVER.assertComponentExist(ON.id('GET'));
await DRIVER.assertComponentExist(ON.id('key1'));

View File

@ -95,6 +95,7 @@ export struct setting {
TextInput({ placeholder: $r('app.string.web') })
.width('75%')
.margin({ left: 4, right: 2 })
.enableKeyboardOnFocus(false)
.onChange((value: string) => {
this.url = value
})

View File

@ -54,14 +54,21 @@ export default function appTest() {
// 输入服务器地址
await driver.assertComponentExist(ON.id('text_ip_input'))
let ipInput = await driver.findComponent(ON.id('text_ip_input'))
// 校验输入的IP地址格式是否正确
await ipInput.inputText("xxx.xxx.xxx.xxx")
await driver.delayMs(1000)
hilog.info(DOMAIN, TAG, BUNDLE + ' bindServer bind server')
// 点击绑定按钮
// 点击绑定按钮,显示格式不正确
await driver.assertComponentExist(ON.id('btn_bind'))
let btnBind = await driver.findComponent(ON.id('btn_bind'))
await btnBind.click()
await driver.delayMs(500)
// 重新输入正确格式的IP地址
await ipInput.inputText("192.168.43.244")
await driver.delayMs(1000)
// 点击绑定按钮
await btnBind.click()
await driver.delayMs(500)
hilog.info(DOMAIN, TAG, BUNDLE + ' bindServer end')
})
/**

View File

@ -262,7 +262,7 @@ struct Watcher {
.align(Alignment.Start)
Flex({ direction: FlexDirection.Column }) {
Row() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween }) {
Row() {
Text($r('app.string.watcherTitleText'))
.fontSize(14)
@ -276,7 +276,7 @@ struct Watcher {
.opacity(0.6)
}
.width('61%')
.margin({ left: 24, right: 52 })
.padding({ left: 24, right: 52 })
.backgroundColor('#f1f3f5')
Row() {
@ -304,6 +304,7 @@ struct Watcher {
}
})
}
.justifyContent(FlexAlign.SpaceBetween)
.height(48)
.margin({ right: 24 })
.width('30%')
@ -411,7 +412,7 @@ struct Watcher {
.margin({ right: 24 })
.id('stopWatcher')
.onClick(() => {
let showEventArray = [''];
let showEventArray = [];
Logger.info('onClick this.eventArray.length = ' + this.eventArray.length);
let j = 0;
for (let i = 0; i < this.eventArray.length; i++) {

View File

@ -367,6 +367,50 @@ export default function abilityTest() {
Logger.info(TAG, 'File_Fs_backward_004 end');
})
/**
* 点击添加监听后停止监听,测试停止监听页面是否出现弹窗白屏
*/
it(BUNDLE + 'StopWatcherFunction_001', 0, async function () {
Logger.info(TAG, BUNDLE + 'StopWatcherFunction_001 begin')
let driver = await Driver.create()
await driver.delayMs(1000)
// 点击停止监听按钮
await driver.assertComponentExist(ON.id('stopWatcher'));
let stopWatcher = await driver.findComponent(ON.id('stopWatcher'));
await stopWatcher.click();
await driver.delayMs(1000);
// 点击添加监听按钮
await driver.assertComponentExist(ON.id('addWatcher'));
let addWatcher = await driver.findComponent(ON.id('addWatcher'));
await addWatcher.click();
await addWatcher.click();
await driver.delayMs(1000);
// 点击确定
let confirmText = await getResourceString($r('app.string.label_confirm'));
await driver.assertComponentExist(ON.text(confirmText));
let sureWatcher = await driver.findComponent(ON.text(confirmText));
await sureWatcher.click();
await driver.delayMs(1000);
// 点击停止监听按钮
await driver.assertComponentExist(ON.id('stopWatcher'));
let stopWatcherTwo = await driver.findComponent(ON.id('stopWatcher'));
await stopWatcherTwo.click();
await driver.delayMs(1000);
// 点击确定按钮
let confirmTextTwo = await getResourceString($r('app.string.label_confirm'));
await driver.assertComponentExist(ON.text(confirmTextTwo));
let sureWatcherTwo = await driver.findComponent(ON.text(confirmTextTwo));
await sureWatcherTwo.click();
await driver.delayMs(1000);
// 点击停止监听按钮
await driver.assertComponentExist(ON.id('stopWatcher'));
let stopWatcherThree = await driver.findComponent(ON.id('stopWatcher'));
await stopWatcherThree.click();
await stopWatcherThree.click();
await driver.delayMs(1000);
Logger.info(TAG, BUNDLE + 'StopWatcherFunction_001 end')
})
/**
* 添加IN_CREATE监听
*/

View File

@ -0,0 +1,11 @@
/node_modules
/oh_modules
/local.properties
/.idea
**/build
/.hvigor
.cxx
/.clangd
/.clang-format
/.clang-tidy
**/.test

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.picker",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name"
}
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "app_name",
"value": "Picker"
}
]
}

View File

@ -0,0 +1,88 @@
# 选择并查看文档与媒体文件
### 介绍
应用使用[@ohos.file.picker](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-picker.md)、[@ohos.multimedia.mediaLibrary](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-medialibrary.md)、[@ohos.file.fs](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fs.md) 等接口实现了picker拉起文档编辑保存、拉起系统相册图片查看、拉起视频并播放的功能。
### 效果预览
| 首页 | 查看并编辑文档界面 | 查看图片界面 | 查看视频界面 |
| ------------------------------------ | ----------------------------------- | -------------------------------------- | ------------------------------------ |
| ![](./screenshots/device/Index.jpeg) | ![](./screenshots/device/Edit.jpeg) | ![](./screenshots/device/Picture.jpeg) | ![](./screenshots/device/Video.jpeg) |
使用说明:
1. 在首页,应用展示出最近打开过的文档信息,点击信息可以进入对应文档的查看界面。通过点击右上方的三个按钮,可以分别实现新建文档、选择图片或视频并打开预览、选择文档并打开的功能。
2. 在查看文档界面点击右上方左一按钮可以实现当前文档另存为的功能点击右上方中间的按钮开启文档的编辑功能textArea变成可编辑状态用户输入数据后点击右上方第三个按钮可以将当前文档内容进行保存操作。
3. 在查看图片界面picker拉起系统相册的图片用户至多可选择三张图片查看点击图片可以切换所显示的图片名及大小信息。
4. 在查看视频界面picker拉起系统相册的视频用户至多可选择三个视频查看点击视频播放并且可以显示的视频名及大小信息。
### 工程目录
```
entry/src/main/ets/
|---common
| |---Common.ts
| |---Utils.ts
| |---Logger.ts //日志工具
|---entryability
| |---EntryAbility.ts //ability类
|---media
| |---MediaFileUri.ts //媒体文件相关函数
|---pages
| |---EditFile.ets //查看并编辑文档界面
| |---Index.ets //首页
| |---ViewMedia.ets //查看图片和视频界面
```
### 具体实现
- 拉起picker选择文件、拉起picker保存文件、拉起picker选择图片或视频的功能封装在Index.ets源码参考[Index.ets](src/main/ets/pages/Index.ets)
* 使用mediaLiabrary.getMediaLibrary来获取媒体库的实例用于访问和修改用户等个人媒体数据信息如视频、图片、文档等使用media.getFileAssets来获取文件资源使用来fetchFileResult.getFirstObject获取文件检索结果中的头一个文件资产接口参考[@ohos.multimedia.mediaLibrary](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-medialibrary.md)
* 使用new picker.DocumentViewPicker来创建文件picker实例使用documentPicker.select来拉起picker选择文件使用documentPicker.save来拉起picker保存文件接口参考[@ohos.file.picker](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-picker.md)
* 使用new picker.PhotoViewPicker来创建图库picker实例使用photoPicker.select来拉起picker选择图片或视频接口参考[@ohos.file.picker](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-picker.md)
- 编辑文件并保存的功能封装在EditFile.ets源码参考[EditFile.ets](src/main/ets/pages/EditFile.ets)
* 使用fs.mkdirSync、fs.openSync、fs.writeSync、fs.readSync、fs.closeSync分别用来来创建文件夹、打开文件、写文件、读文件、关闭文件接口参考[@ohos.file.fs](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fs.md)
- 拉起图片或视频并查看的功能封装在ViewMedia.ets源码参考[ViewMedia.ets](src/main/ets/pages/ViewMedia.ets)
* 使用new picker.PhotoViewPicker来创建图库picker实例使用photoPicker.save来拉起picker保存图片或视频接口参考[@ohos.file.picker](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-picker.md)
* 使用mediaLiabrary.getMediaLibrary来获取媒体库的实例用于访问和修改用户等个人媒体数据信息如视频、图片、文档等然后使用media.getFileAssets来获取文件资源再使用fileAsset.displayName来获取图片或视频的名称接口参考[@ohos.multimedia.mediaLibrary](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-medialibrary.md)
### 相关权限
| 权限名 | 权限说明 | 级别 |
| -------------------------------- | ---------------------------------------- | ------------ |
| ohos.permission.MEDIA_LOCATION | 允许应用访问用户媒体文件中的地理位置信息 | normal |
| ohos.permission.READ_MEDIA | 允许应用读取用户外部存储中的媒体文件信息 | normal |
| ohos.permission.WRITE_MEDIA | 允许应用读写用户外部存储中的媒体文件信息 | normal |
| ohos.permission.WRITE_IMAGEVIDEO | 允许修改用户公共目录的图片或视频文件 | system_basic |
| ohos.permission.READ_IMAGEVIDEO | 允许读取用户公共目录的图片或视频文件 | system_basic |
### 依赖
不涉及
### 约束与限制
1.本示例仅支持标准系统上运行支持设备RK3568。
2.本示例为Stage模型已适配API version 9版本SDK版本号3.2.12.2镜像版本号OpenHarmony 4.0.9.1 。
3.本示例需要使用DevEco Studio 3.1 Beta2 (Build Version: 3.1.0.400, built on April 7, 2023)及以上版本才可编译运行。
4.本示例涉及部分接口需要配置系统应用签名,可以参考[特殊权限配置方法](https://docs.openharmony.cn/pages/v3.2/zh-cn/application-dev/security/hapsigntool-overview.md/) 把配置文件中的“apl”字段信息改为“system_basic”。
### 下载
如需单独下载本工程,执行如下命令:
```
git init
git config core.sparsecheckout true
echo code/BasicFeature/FileManagement/FileShare/Picker > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master
```

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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": {
"signingConfigs": [],
"compileSdkVersion": 9,
"compatibleSdkVersion": 9,
"products": [
{
"name": "default",
"signingConfig": "default",
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

View File

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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": {
},
"targets": [
{
"name": "default",
"runtimeOS": "OpenHarmony"
},
{
"name": "ohosTest",
}
]
}

View File

@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
export { hapTasks } from '@ohos/hvigor-ohos-plugin';

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.
*/
{
"license": "",
"devDependencies": {},
"author": "",
"name": "entry",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {}
}

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import type { Permissions } from '@ohos.abilityAccessCtrl';
import { describe, it, expect } from '@ohos/hypium';
import util from '@ohos.util';
import Logger from '../common/Logger';
const INDEX: number = 2; // 序号
const SLEEP_TIME: number = 10; // 睡眠时间
const RADIX: number = 16; // parInt第二个参数值
const TAG = 'pickerCommon';
const GRANT_MAX: number = 3;
// ############################################# 应用授权 ##########################################################
export function reqPermissions(context): void {
let atManager = abilityAccessCtrl.createAtManager();
const permissions: Array<Permissions> = [
'ohos.permission.READ_MEDIA',
'ohos.permission.WRITE_MEDIA',
'ohos.permission.MEDIA_LOCATION',
'ohos.permission.DISTRIBUTED_DATASYNC'
];
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
Logger.info(TAG, `[requestPermissions] data: ${JSON.stringify(data)}`);
let grantStatus: Array<number> = data.authResults;
let arrLength = grantStatus.length;
if (arrLength < GRANT_MAX) {
Logger.info(TAG, '[requestPermissions] Do not have 3 permissions.');
} else {
if (grantStatus[0] === 0 && grantStatus[1] === 0 && grantStatus[INDEX] === 0) {
// 授权成功
Logger.info(TAG, '[requestPermissions] Success to start request permissions.');
} else {
// 授权失败
Logger.info(TAG, '[requestPermissions] Do not have permissions.');
}
}
}).catch((err) => {
Logger.error(TAG, `[requestPermissions] Failed to start request permissions. Error: ${JSON.stringify(err)}`);
});
}
export function strToUtf8Bytes(content: string | number | boolean): Array<number> {
const code = encodeURIComponent(content);
let bytes = [];
for (let i = 0; i < code.length; i++) {
const char = code.charAt(i);
if (char === '%') {
const hex = code.charAt(i + 1) + code.charAt(i + INDEX);
const hexValue = parseInt(hex, RADIX);
bytes.push(hexValue);
i += INDEX;
} else {
bytes.push(char.charCodeAt(0));
}
}
return bytes;
}
export function strToArrayBuffer(text: string): ArrayBuffer {
const bytes = this.strToUtf8Bytes(text);
const buffer = new ArrayBuffer(bytes.length);
const bufView = new DataView(buffer);
for (let i = 0; i < bytes.length; i++) {
bufView.setUint8(i, bytes[i]);
}
return buffer;
}
export async function sleep(times: number): Promise<void> {
if (!times) {
times = SLEEP_TIME;
}
await new Promise((res) => setTimeout(res, times));
}
export function randomString(num: number, chars: string): string {
let len = num;
let maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
export function bufferToString(buffer: ArrayBuffer): string {
let textDecoder = new util.TextDecoder('utf-8', {
ignoreBOM: true
});
let resultPut = textDecoder.decodeWithStream(new Uint8Array(buffer), {
stream: true
});
return resultPut;
}
export function stringToBuffer(content: string): Uint8Array {
let textEncoder = new util.TextEncoder('utf-8');
let resultBuf = textEncoder.encodeInto(content);
return resultBuf;
}
export {
describe, it, expect
};

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.hilog';
/**
* Common log for all features.
*/
export class Logger {
private domain: number;
private prefix: string;
private format: string = '%{public}s, %{public}s';
constructor(prefix: string) {
this.prefix = prefix;
this.domain = 0xFF00;
}
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('[Picker]');

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 router from '@ohos.router';
import hilog from '@ohos.hilog';
import prompt from '@ohos.prompt';
let log = '';
const TIMEOUT_MAX = 10;
export class DocFileInfo {
constructor(public filename: string, public size: number) {
this.filename = filename;
this.size = size;
}
}
export default class Utils {
/**
*
*/
clearLog(): void {
log = '';
}
/**
*
* @param message
*/
setLog(message: string): void {
if (log === null || log === undefined) {
log = message;
} else {
log += '\n' + message;
}
}
/**
*
* @returns
*/
getLog(): string {
return log;
}
/**
*
* @param str
*/
myLog(info: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, tag, hilog.LogLevel.INFO);
hilog.info(0x0000, tag, '%{public}s', info);
this.setLog('[info]' + info);
}
/**
*
* @param str
*/
myWarnLog(warn: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.WARN);
hilog.warn(0x0000, 'testTag', 'Failed Cause: %{public}s', warn);
this.setLog('[warn]' + warn);
}
/**
*
* @param str
*/
myErrLog(err: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, tag, hilog.LogLevel.ERROR);
hilog.error(0x0000, tag, 'Failed Cause: %{public}s', err);
this.setLog('[error]' + err);
}
/**
* Toast提示
* @param info
*/
showInfo(info): void {
prompt.showToast({
message: info,
duration: 2000
});
}
/**
*
* @param toAbility
* @param mParams
*/
myBack(toAbility: string = '', mParams: { [key: string]: string } = null): void {
let options = {
url: toAbility,
params: mParams
};
router.back(options);
}
/**
*
* @param toAbility
* @param mParams
*/
async goToPage(toAbility: string, mParams: { [key: string]: string }): Promise<void> {
let options = {
url: toAbility,
params: mParams
};
try {
await router.pushUrl(options);
} catch (err) {
hilog.error(0x0000, 'err', 'fail callback, code: %{public}s', err.msg);
}
}
/**
*
* @param times
*/
async sleep(times): Promise<void> {
if (!times) {
times = TIMEOUT_MAX;
}
await new Promise((res) => setTimeout(res, times));
};
}

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import type { Permissions } from '@ohos.abilityAccessCtrl';
import type Want from '@ohos.application.Want';
import MediaFileUri from '../media/MediaFileUri';
import Logger from '../common/Logger';
const TAG = 'EntryAbility: ';
let wantInfo = null;
export default class EntryAbility extends UIAbility {
private mediaFileUri: MediaFileUri = new MediaFileUri();
private fileName: string = '';
private size: number = 0;
private content: string = '';
private showFlag: Boolean = false;
private windowStage: window.WindowStage;
private loadFlag: Boolean = false;
private loadFileSize: number = 0;
private loadFileName: string = '';
private loadFileContent: string = '';
private loadUri: string = '';
private storage: LocalStorage = new LocalStorage();
onCreate(want, launchParam): void {
Logger.info(TAG, 'Ability onCreate');
this.getPermission(want);
wantInfo = want;
}
getWantInfo(want: Want): void {
if (want === null || want === undefined) {
Logger.info(TAG, 'getWantInfo want is null');
return;
}
let srcUri = want.uri;
if (srcUri === null || srcUri === undefined) {
Logger.info(TAG, 'getWantInfo srcUri is null');
return;
}
let parameters = want.parameters;
if (parameters === null || parameters === undefined) {
Logger.info(TAG, 'getWantInfo parameters is null');
return;
}
let keyFd = want.parameters.keyFd;
if (keyFd === null || keyFd === undefined) {
Logger.info(TAG, 'getWantInfo keyFd is null');
return;
}
let size = want.parameters.keyFd.size;
if (size === null || size === undefined) {
Logger.info(TAG, 'getWantInfo size is null');
return;
}
let name = want.parameters.keyFd.name;
if (name === null || name === undefined) {
Logger.info(TAG, 'getWantInfo name is null');
return;
}
let content = want.parameters.keyFd.content;
if (content === null || content === undefined) {
Logger.info(TAG, 'getWantInfo content is null');
return;
}
let fd = want.parameters.keyFd.value;
if (fd === null || fd === undefined) {
Logger.info(TAG, 'getWantInfo fd is null');
return;
}
this.loadFlag = true;
this.loadFileName = want.parameters.keyFd.name;
this.loadFileSize = want.parameters.keyFd.size;
this.loadFileContent = want.parameters.keyFd.content;
this.loadUri = want.uri;
this.storage.setOrCreate('loadFlag', this.loadFlag);
this.storage.setOrCreate('loadUri', this.loadUri);
this.storage.setOrCreate('loadFileName', this.loadFileName);
this.storage.setOrCreate('loadFileSize', this.loadFileSize);
this.storage.setOrCreate('loadFileContent', this.loadFileContent);
this.storage.setOrCreate('fd', fd);
Logger.info(TAG, 'getWantInfo Ability loadFlag: ' + this.loadFlag);
Logger.info(TAG, 'getWantInfo Ability loadUri: ' + want.uri);
Logger.info(TAG, 'getWantInfo Ability loadFileName: ' + this.loadFileName);
Logger.info(TAG, 'getWantInfo Ability loadFileSize: ' + this.loadFileSize);
Logger.info(TAG, 'getWantInfo Ability loadFileContent: ' + this.loadFileContent);
this.loadEditFilePage();
}
onNewWant(want, launchParam): void {
Logger.info(TAG, 'Ability onNewWant');
wantInfo = want;
this.getWantInfo(want);
}
onDestroy(): void {
Logger.info(TAG, 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
this.windowStage = windowStage;
// Main window is created, set main page for this ability
Logger.info(TAG, 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
Logger.error(TAG, 'Failed to load the content. Cause: ' + JSON.stringify(err) ?? '');
return;
}
Logger.info(TAG, 'Succeeded in loading the content. Data: ' + JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
Logger.info(TAG, 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
Logger.info(TAG, 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
Logger.info(TAG, 'Ability onBackground');
}
loadEditFilePage(): void {
this.windowStage.loadContent('pages/EditFile', this.storage, (err, data) => {
if (err.code) {
Logger.error(TAG, 'Failed to load the content. Cause: ' + JSON.stringify(err) ?? '');
return;
}
Logger.info(TAG, 'Succeeded in loading the content. Data: ' + JSON.stringify(data) ?? '');
});
}
getPermission(want: Want): void {
let array: Array<Permissions> = [
'ohos.permission.READ_MEDIA',
'ohos.permission.WRITE_MEDIA',
'ohos.permission.MEDIA_LOCATION',
'ohos.permission.READ_IMAGEVIDEO',
'ohos.permission.WRITE_IMAGEVIDEO',
];
let context = this.context;
let atManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
atManager.requestPermissionsFromUser(context, array).then((data) => {
Logger.info(TAG, 'data type:' + typeof (data));
Logger.info(TAG, 'data:' + data);
Logger.info(TAG, 'data permissions:' + data.permissions);
Logger.info(TAG, 'data result:' + data.authResults);
this.mediaFileUri.getAllFiles(context);
Logger.info(TAG, 'getPermission getWantInfo');
this.getWantInfo(want);
}).catch((err) => {
Logger.error(TAG, 'Failed to start ability' + err.code);
});
}
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 fileIo from '@ohos.fileio';
import fs from '@ohos.file.fs';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import Logger from '../common/Logger';
import { bufferToString } from '../common/Common';
const RECENT_MAX = 10; // 最近打开最大文件数
const BUFFER_SIZE = 4096; // 文件读写缓冲区大小
const COMMON_FD = -1; // 文件fd默认值
const TAG = 'MediaFileUri';
const MODE_READ_ONLY = 0;
const MODE_WRITE_ONLY = 1;
const MODE_READ_WRITE = 2;
export default class MediaFileUri {
private commonFd: number = COMMON_FD;
content: string = '';
private fileSizeList: Array<number> = [];
private fileNameList: Array<string> = [];
private fileUriList: Array<string> = [];
constructor() {
}
getMode(openFlag: number): number {
let mode;
switch (openFlag) {
case MODE_READ_ONLY:
mode = fs.OpenMode.READ_ONLY; // r
break;
case MODE_WRITE_ONLY:
mode = fs.OpenMode.WRITE_ONLY; // w
break;
case MODE_READ_WRITE:
mode = fs.OpenMode.READ_WRITE; // rw
break;
}
return mode;
}
myWriteSync(fd: number, content: string, isClose: boolean): void {
try {
let result = fs.writeSync(fd, content);
Logger.info(TAG, 'myWriteSync: write result = ' + result);
} catch (err) {
Logger.error(TAG, 'myWriteSync write failed with error:' + err);
}
if (isClose) {
this.closeSync(fd);
this.commonFd = COMMON_FD;
} else {
this.commonFd = fd;
}
}
// sync-close
closeSync(fd: number): void {
try {
fileIo.closeSync(fd);
Logger.info(TAG, 'closeSync file finish.');
} catch (err) {
Logger.error(TAG, 'closeSync file error = ' + err);
}
}
readFileContent(uri: string, isRead: boolean = true, isClose: boolean = true): string {
let content = '';
Logger.info(TAG, 'open path = ' + uri);
let file;
if (isClose || this.commonFd === COMMON_FD) {
try {
file = fs.openSync(uri, fs.OpenMode.READ_ONLY);
Logger.info(TAG, 'openReadSync: get fd success. fd = ' + file.fd);
this.commonFd = file.fd;
} catch (err) {
Logger.error(TAG, 'openReadSync: open file failed. error = ' + err);
return content;
}
if (file === undefined) {
Logger.error(TAG, 'openReadSync: open file failed. file = undefined.');
return content;
}
}
if (isRead) {
try {
let buffer = new ArrayBuffer(BUFFER_SIZE);
let readOut = fs.readSync(this.commonFd, buffer, {
offset: 0
});
content = bufferToString(buffer);
Logger.info(TAG, 'myReadSync: read result: ' + String.fromCharCode.apply(null, new Uint8Array(buffer.slice(0, readOut))));
} catch (err) {
Logger.error(TAG, 'myReadSync: read error: ' + err);
return content;
}
if (isClose) {
this.closeSync(this.commonFd);
this.commonFd = COMMON_FD;
} else {
this.commonFd = this.commonFd;
}
}
return content;
}
myGetFileSize(uri: string, mode: number): number {
let file = fs.openSync(uri, mode); // fs.OpenMode.READ_ONLY
Logger.info(TAG, 'file fd: ' + file.fd);
let stat = fs.statSync(file.fd);
Logger.info(TAG, 'get file info succeed, the size of file is ' + stat.size);
return stat.size;
}
writeFileContent(uri: string, content: string): void {
Logger.info(TAG, 'writeFileContent begin');
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
Logger.info(TAG, 'writeFileContent file fd: ' + file.fd);
let writeLen = fs.writeSync(file.fd, content);
Logger.info(TAG, 'writeFileContent write data to file succeed and size is:' + writeLen);
fs.closeSync(file);
}
getAllFiles(context): void {
Logger.info(TAG, 'getAllFiles begin');
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.FILE; // mediaLibrary.MediaType.IMAGE
let args = imageType.toString();
// 创建文件获取选项此处参数为获取image类型的文件资源
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [args],
order: 'date_added DESC'
};
let media = mediaLibrary.getMediaLibrary(context);
// 获取文件资源使用callback方式返回异步结果
media.getFileAssets(imagesFetchOp, async (error, fetchFileResult) => {
// 判断获取的文件资源的检索结果集是否为undefined若为undefined则接口调用失败
if (fetchFileResult === undefined) {
Logger.error(TAG, 'get fetchFileResult failed with error: ' + error);
return;
}
// 获取文件检索结果集中的总数
const count = fetchFileResult.getCount();
// 判断结果集中的数量是否小于0小于0时表示接口调用失败
if (count < 0) {
Logger.error(TAG, 'get count from fetchFileResult failed, count: ' + count);
return;
}
// 判断结果集中的数量是否等于0等于0时表示接口调用成功但是检索结果集为空请检查文件获取选项参数配置是否有误和设备中是否存在相应文件
if (count === 0) {
Logger.info(TAG, 'The count of fetchFileResult is zero');
return;
}
Logger.info(TAG, 'Get fetchFileResult successfully, count: ' + count);
// 获取文件检索结果集中的第一个资源使用callback方式返回异步结果文件数量较多时请使用getAllObject接口
fetchFileResult.getFirstObject(async (error, fileAsset) => {
// 检查获取的第一个资源是否为undefined若为undefined则接口调用失败
if (fileAsset === undefined) {
Logger.error(TAG, 'get first object failed with error: ' + error);
return;
}
Logger.info(TAG, 'fileAsset.displayName ' + '0 : ' + fileAsset.displayName);
Logger.info(TAG, 'fileAsset.uri 0:' + fileAsset.uri);
let index = 0;
this.fileNameList[index] = fileAsset.displayName;
this.fileSizeList[index] = fileAsset.size;
this.fileUriList[index] = fileAsset.uri;
// this.writeFileContent(this.fileUriList[index])
// 调用 getNextObject 接口获取下一个资源,直到最后一个
for (let i = 1; i < count && i < RECENT_MAX; i++) {
let fileAsset = await fetchFileResult.getNextObject();
if (fileAsset === undefined) {
Logger.error(TAG, 'get Next object failed with error: ' + error);
return;
}
index = index + 1;
this.fileNameList[index] = fileAsset.displayName;
this.fileSizeList[index] = fileAsset.size;
this.fileUriList[index] = fileAsset.uri;
Logger.info(TAG, 'fileAsset.uri:' + i.toString() + fileAsset.uri);
Logger.info(TAG, 'fileAsset.displayName ' + i + ': ' + fileAsset.displayName);
}
AppStorage.SetOrCreate('fileNameList', this.fileNameList);
AppStorage.SetOrCreate('fileSizeList', this.fileSizeList);
AppStorage.SetOrCreate('fileUriList', this.fileUriList);
// 释放FetchFileResult实例并使其失效。无法调用其他方法
fetchFileResult.close();
});
});
}
}

View File

@ -0,0 +1,346 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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';
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import router from '@ohos.router';
import picker from '@ohos.file.picker';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import MediaFileUri from '../media/MediaFileUri';
import Logger from '../common/Logger';
const TAG = 'EditFile: ';
let storage = LocalStorage.GetShared();
const OPACITY_VALUE = 0.6; // 透明度
@Entry(storage)
@Component
struct EditFile {
@State myContext: Context = getContext(this) as common.UIAbilityContext;
@StorageLink('myFileSize') myFileSize: number = 0;
@State myFileName: string = '';
@StorageLink('myFileContent') myFileContent: string = '';
@State myUri: string = '';
@State opacityValue: number = OPACITY_VALUE;
@LocalStorageLink('loadFlag') loadFlag: Boolean = false;
@LocalStorageLink('loadFileSize') loadFileSize: number = 0;
@LocalStorageLink('loadFileName') loadFileName: string = '';
@LocalStorageLink('loadFileContent') loadFileContent: string = '';
@LocalStorageLink('loadUri') loadUri: string = '';
@LocalStorageLink('fd') loadFd: number = 0;
@StorageLink('editable') editable: Boolean = false;
newFileContent: string = '';
public fileContentFlag: boolean = false;
scroller: Scroller = new Scroller();
controller: TextAreaController = new TextAreaController();
mediaFileUri: MediaFileUri = new MediaFileUri();
@State uriSave: string = '';
getFileInfo(): void {
if (this.loadFlag) {
this.myFileName = this.loadFileName;
this.myFileContent = this.loadFileContent;
this.myFileSize = this.loadFileSize;
this.myUri = this.loadUri;
Logger.info(TAG, 'The count of getFileInfo is myFileContent ' + this.myFileContent);
} else {
this.myUri = router.getParams()['uri'];
this.myFileName = router.getParams()['fileName'];
this.myFileContent = this.mediaFileUri.readFileContent(this.myUri);
this.myFileSize = this.mediaFileUri.myGetFileSize(this.myUri, fs.OpenMode.READ_ONLY);
Logger.info(TAG, 'The count of getFileInfo is myFileName is: ' + this.myFileName);
Logger.info(TAG, 'The count of getFileInfo is myFileContent ' + this.myFileContent);
Logger.info(TAG, 'The count of getFileInfo is myFileSize ' + this.myFileSize);
}
AppStorage.SetOrCreate('myFileContent', this.myFileContent);
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
}
async writeContentForSaveAsFile(myUri: string, wrFlag: Boolean = false): Promise<void> {
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.FILE; // mediaLibrary.MediaType.IMAGE
let args = imageType.toString();
// 创建文件获取选项此处参数为获取image类型的文件资源
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [args], // imageType.toString()
uri: myUri,
};
let media = mediaLibrary.getMediaLibrary(getContext(this));
// 获取文件资源使用callback方式返回异步结果
media.getFileAssets(imagesFetchOp, async (error, fetchFileResult) => {
// 判断获取的文件资源的检索结果集是否为undefined若为undefined则接口调用失败
if (fetchFileResult === undefined) {
Logger.error(TAG, 'get fetchFileResult failed with error: ' + error);
return;
}
// 获取文件检索结果集中的总数
const count = fetchFileResult.getCount();
// 判断结果集中的数量是否小于0小于0时表示接口调用失败
if (count < 0) {
Logger.error(TAG, 'get count from fetchFileResult failed, count: ' + count);
return;
}
// 判断结果集中的数量是否等于0等于0时表示接口调用成功但是检索结果集为空请检查文件获取选项参数配置是否有误和设备中是否存在相应文件
if (count === 0) {
Logger.info(TAG, 'The count of fetchFileResult is zero');
return;
}
Logger.info(TAG, 'Get fetchFileResult successfully, count: ' + count);
// 获取文件检索结果集中的第一个资源使用callback方式返回异步结果文件数量较多时请使用getAllObject接口
fetchFileResult.getFirstObject(async (error, fileAsset) => {
// 检查获取的第一个资源是否为undefined若为undefined则接口调用失败
if (fileAsset === undefined) {
Logger.error(TAG, 'get first object failed with error: ' + error);
return;
}
Logger.info(TAG, 'fileAsset.displayName ' + '0 : ' + fileAsset.displayName);
Logger.info(TAG, 'fileAsset.uri 0:' + fileAsset.uri);
Logger.info(TAG, 'myUri: ' + myUri);
if (wrFlag) {
Logger.info(TAG, 'fileAsset.displayName wrFlag is true');
Logger.info(TAG, 'fileAsset.displayName wrFlag myFileContent :' + this.myFileContent);
this.mediaFileUri.writeFileContent(myUri, this.myFileContent);
}
fetchFileResult.close();
});
});
}
/**
* 拉起picker保存文件
*/
async callFilePickerSaveFile(): Promise<void> {
try {
let DocumentSaveOptions = new picker.DocumentSaveOptions();
DocumentSaveOptions.newFileNames = ['MyDocument_01.txt'];
let documentPicker = new picker.DocumentViewPicker();
documentPicker.save(DocumentSaveOptions).then((DocumentSaveResult) => {
Logger.info(TAG, 'DocumentViewPicker.save successfully, DocumentSaveResult uri: ' + JSON.stringify(DocumentSaveResult));
if (DocumentSaveResult !== null && DocumentSaveResult !== undefined) {
this.uriSave = DocumentSaveResult[0];
Logger.info(TAG, `save callFilePickerSaveFile file this.uriSave: ${this.uriSave}`);
}
Logger.info(TAG, 'fileAsset.displayName wrFlag myFileContent :' + this.myFileContent);
this.writeContentForSaveAsFile(this.uriSave, true); // 用 medialibrary 重新获取uri进行写入操作
}).catch((err) => {
Logger.error(TAG, 'DocumentViewPicker.save failed with err: ' + err);
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + err);
}
}
onPageShow(): void {
this.getFileInfo();
}
aboutToDisappear(): void {
}
onPageHide(): void {
}
terminateSelf(context) {
context.terminateSelf();
}
build() {
Column() {
// 顶部的行容器
Row() {
// 后退箭头
Row() {
Image($r('app.media.ic_back'))
.focusable(true)
.focusOnTouch(true)
.id('backIndex')
.width(25)
.height(25)
.align(Alignment.Start)
.onClick(() => {
if (this.loadFlag) {
Logger.info(TAG, 'end page');
let context = getContext(this);
this.terminateSelf(context);
} else {
router.back();
}
})
}
.margin({ left: '5%' })
// 文件名及信息
Column() {
Row() {
Text(this.myFileName)
.focusable(true)
.focusOnTouch(true)
.fontSize(20)
.fontFamily('HarmonyHeiTi-Bold')
.fontColor('#182431')
.textAlign(TextAlign.Start)
.fontWeight(700)
.lineHeight(28)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.align(Alignment.Start)
.margin({ left: '5%', top: '0.4%', bottom: '0.3%' })
Row() {
Text('size: ' + JSON.stringify(this.myFileSize) + 'B')
.focusable(true)
.focusOnTouch(true)
.opacity(0.6)
.fontFamily('HarmonyHeiTi')
.fontSize(14)
.fontColor('#182431')
.textAlign(TextAlign.Start)
.lineHeight(19)
.fontWeight(400)
}
.width('100%')
.margin({ left: '5%', top: '0.3%', bottom: '0.5%' })
.align(Alignment.Start)
}
.width('45%')
.margin({ left: '5%' })
// 右边三个图标
Row() {
Image($r('app.media.ic_saveas'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.id('saveAs')
.margin({ right: '12%' })
.onClick(() => {
this.callFilePickerSaveFile();
})
.visibility(this.loadFlag ? Visibility.Hidden : Visibility.Visible)
Image($r('app.media.ic_writting'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.id('editable')
.margin({ right: '12%' })
.onClick(() => {
this.editable = true;
AppStorage.SetOrCreate('editable', this.editable);
Logger.info(TAG, 'EditFile caretPosition length = ' + this.myFileContent.length);
this.controller.caretPosition(this.myFileContent.length);
promptAction.showToast({ message: $r('app.string.editable') });
})
Image($r('app.media.ic_save'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.id('save')
.margin({ right: '5%' })
.onClick(() => {
if (this.fileContentFlag) {
this.myFileContent = this.newFileContent;
AppStorage.SetOrCreate('myFileContent', this.myFileContent);
Logger.info(TAG, 'save onClick myFileContent is: ' + this.myFileContent);
Logger.info(TAG, 'save onClick this.loadUri: ' + this.loadUri);
if (this.loadFlag) {
let file = fs.openSync(this.loadUri, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE | fs.OpenMode.TRUNC);
Logger.info(TAG, 'save onClick file.fd is: ' + file.fd);
fs.write(file.fd, this.myFileContent).then((writeLen) => {
Logger.info(TAG, "write data to file succeed and size is:" + writeLen);
this.myFileSize = fs.statSync(file.fd).size;
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'save onClick this.myFileSize ' + this.myFileSize);
}).catch((err) => {
Logger.info(TAG, "write data to file failed with error message: " + err.message + ", error code: " + err.code);
});
fs.closeSync(file);
} else {
let file = fs.openSync(this.myUri, fs.OpenMode.READ_WRITE | fs.OpenMode.TRUNC);
let writeLen = fs.writeSync(file.fd, this.myFileContent);
this.myFileSize = fs.statSync(file.fd).size;
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'write data to file succeed and size is:' + writeLen);
fs.closeSync(file);
}
this.editable = false;
AppStorage.SetOrCreate('editable', this.editable);
promptAction.showToast({ message: $r('app.string.saved') });
}
})
}
.height('50%')
.width('37.2%')
.padding({ right: '0.5%' })
.justifyContent(FlexAlign.End)
}
.height('7.4%')
.width('100%')
Scroll(this.scroller) {
// TextArea的行容器
Row() {
TextArea({ text: this.myFileContent, placeholder: 'Input text here...', controller: this.controller })
.id('textArea')
.fontSize(16)
.fontColor('#182431')
.opacity(this.opacityValue)
.fontWeight(400)
.align(Alignment.TopStart)
.textAlign(TextAlign.Start)
.backgroundColor('#f1f3f5')
.fontFamily('HarmonyHeiTi')
.padding({
top: 0,
right: 0,
left: 0,
bottom: 0
}) // 默认为top: 8 vp, right: 16 vp, bottom: 8 vp, left: 16 vp需要更改
.focusable(this.editable ? true : false)
.focusOnTouch(true)
.defaultFocus(false)
.onFocus(() => {
this.opacityValue = 1;
})
.onBlur(() => {
this.opacityValue = OPACITY_VALUE;
})
.onChange((value: string) => {
this.newFileContent = value;
this.fileContentFlag = true;
})
}
.padding({ top: '4%', left: '6.7%', right: '6.7%' })
}
}
.backgroundColor('#f1f3f5')
.height('100%')
}
}

View File

@ -0,0 +1,391 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 picker from '@ohos.file.picker';
import Logger from '../common/Logger';
import MediaFileUri from '../media/MediaFileUri';
import router from '@ohos.router';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
const MAX_SELECT_NUM = 3; // 选择媒体文件的最大数目
const TAG = 'pickerIndex';
@Entry
@Component
struct Index {
mediaFileUri: MediaFileUri = new MediaFileUri();
scroller: Scroller = new Scroller();
@State uri: string = 'Hello World';
@State filename: string = '';
@State sizeFile: number = 0;
authorizeBundleName: string = 'com.open.file.uri.demo';
@State log: string = '';
@State imageFlagCur: number = 0;
@StorageLink('fileSizeList') fileSizeList: Array<number> = [];
@StorageLink('fileNameList') fileNameList: Array<string> = [];
@StorageLink('fileUriList') fileUriList: Array<string> = [];
@StorageLink('imageNames') imageNames: Array<string> = [];
/**
* 拉起picker选择文件
*/
async callFilePickerSelectFile(): Promise<void> {
try {
let DocumentSelectOptions = new picker.DocumentSelectOptions();
let documentPicker = new picker.DocumentViewPicker();
documentPicker.select(DocumentSelectOptions).then((DocumentSelectResult) => {
Logger.info(TAG, 'DocumentViewPicker.select successfully, DocumentSelectResult uri: ' + JSON.stringify(DocumentSelectResult));
let editFlag = false;
if (DocumentSelectResult !== null && DocumentSelectResult !== undefined) {
DocumentSelectResult.forEach((value) => {
this.uri = value;
editFlag = true;
Logger.info(TAG, `select file uri: ${this.uri}`);
})
}
if (editFlag) {
this.getFilenameByUri(this.uri);
}
}).catch((err) => {
Logger.error(TAG, 'DocumentViewPicker.select failed with err: ' + err);
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + err);
}
}
/**
* 拉起picker保存文件
*/
async callFilePickerSaveFile(): Promise<void> {
try {
let DocumentSaveOptions = new picker.DocumentSaveOptions();
DocumentSaveOptions.newFileNames = ['MyDocument_01.txt'];
let documentPicker = new picker.DocumentViewPicker();
documentPicker.save(DocumentSaveOptions).then((DocumentSaveResult) => {
Logger.info(TAG, 'DocumentViewPicker.save successfully, DocumentSaveResult uri: ' + JSON.stringify(DocumentSaveResult));
if (DocumentSaveResult !== null && DocumentSaveResult !== undefined) {
this.uri = DocumentSaveResult[0];
Logger.info(TAG, `save file uri: ${this.uri}`);
}
this.getFilenameByUri(this.uri);
}).catch((err) => {
Logger.error(TAG, 'DocumentViewPicker.save failed with err: ' + err);
});
} catch (err) {
Logger.error(TAG, 'DocumentViewPicker failed with err: ' + err);
}
}
async getFilenameByUriForMedia(myUris: string[]) {
Logger.info(TAG, ' getFilenameByUriForMedia begin');
// 创建文件获取选项此处参数为获取image类型的文件资源
let imagesFetchOp = {
selections: mediaLibrary.FileKey.MEDIA_TYPE + '= ? OR ' + mediaLibrary.FileKey.MEDIA_TYPE + '= ?',
selectionArgs: [mediaLibrary.MediaType.IMAGE.toString(), mediaLibrary.MediaType.VIDEO.toString()],
uri: myUris[0],
};
let media = mediaLibrary.getMediaLibrary(getContext(this));
// 获取文件资源使用callback方式返回异步结果
media.getFileAssets(imagesFetchOp, async (error, fetchFileResult) => {
// 判断获取的文件资源的检索结果集是否为undefined若为undefined则接口调用失败
Logger.info(TAG, 'getFilenameByUriForMedia getMediaLibrary is ok');
if (fetchFileResult === undefined) {
Logger.error(TAG, 'get fetchFileResult failed with error: ' + error);
return;
}
// 获取文件检索结果集中的总数
const count = fetchFileResult.getCount();
Logger.info(TAG, ' getFilenameByUriForMedia count is: ' + count);
// 判断结果集中的数量是否小于0小于0时表示接口调用失败
if (count < 0) {
Logger.error(TAG, 'get count from fetchFileResult failed, count: ' + count);
return;
}
// 判断结果集中的数量是否等于0等于0时表示接口调用成功但是检索结果集为空请检查文件获取选项参数配置是否有误和设备中是否存在相应文件
if (count === 0) {
Logger.info(TAG, 'The count of fetchFileResult is zero');
return;
}
Logger.info(TAG, 'Get fetchFileResult successfully, count: ' + count);
// 获取文件检索结果集中的第一个资源使用callback方式返回异步结果文件数量较多时请使用getAllObject接口
fetchFileResult.getFirstObject(async (error, fileAsset) => {
// 检查获取的第一个资源是否为undefined若为undefined则接口调用失败
if (fileAsset === undefined) {
Logger.error(TAG, 'get first object failed with error: ' + error);
return;
}
Logger.info(TAG, ' fileAsset.uri 0:' + fileAsset.uri);
Logger.info(TAG, ' myUri: ' + myUris[0]);
let index = 0;
this.imageNames[index] = fileAsset.displayName;
// if (fileAsset.mediaType === mediaLibrary.MediaType.IMAGE) {
// this.imageFlagCur = 1;
// } else if (fileAsset.mediaType === mediaLibrary.MediaType.VIDEO) {
// this.imageFlagCur = 2;
// } else {
// this.imageFlagCur = 0;
// }
Logger.info(TAG, ' ViewMedia imageFlagCur ' + this.imageFlagCur);
router.pushUrl({
url: 'pages/ViewMedia',
params: {
// imageFlag: this.imageFlagCur,
uris: myUris
}
}, router.RouterMode.Standard);
fetchFileResult.close();
});
});
}
async getFilenameByUri(myUri: string): Promise<void> {
let fileKeyObj = mediaLibrary.FileKey;
let imageType = mediaLibrary.MediaType.FILE; // mediaLibrary.MediaType.IMAGE
let args = imageType.toString();
// 创建文件获取选项此处参数为获取image类型的文件资源
let imagesFetchOp = {
selections: fileKeyObj.MEDIA_TYPE + '= ?',
selectionArgs: [args], // imageType.toString()
uri: myUri,
};
let media = mediaLibrary.getMediaLibrary(getContext(this));
// 获取文件资源使用callback方式返回异步结果
media.getFileAssets(imagesFetchOp, async (error, fetchFileResult) => {
// 判断获取的文件资源的检索结果集是否为undefined若为undefined则接口调用失败
if (fetchFileResult === undefined) {
Logger.error(TAG, 'get fetchFileResult failed with error: ' + error);
return;
}
// 获取文件检索结果集中的总数
const count = fetchFileResult.getCount();
// 判断结果集中的数量是否小于0小于0时表示接口调用失败
if (count < 0) {
Logger.error(TAG, 'get count from fetchFileResult failed, count: ' + count);
return;
}
// 判断结果集中的数量是否等于0等于0时表示接口调用成功但是检索结果集为空请检查文件获取选项参数配置是否有误和设备中是否存在相应文件
if (count === 0) {
Logger.info(TAG, 'The count of fetchFileResult is zero');
return;
}
Logger.info(TAG, 'Get fetchFileResult successfully, count: ' + count);
// 获取文件检索结果集中的第一个资源使用callback方式返回异步结果文件数量较多时请使用getAllObject接口
fetchFileResult.getFirstObject(async (error, fileAsset) => {
// 检查获取的第一个资源是否为undefined若为undefined则接口调用失败
if (fileAsset === undefined) {
Logger.error(TAG, 'get first object failed with error: ' + error);
return;
}
Logger.info(TAG, 'fileAsset.displayName ' + '0 : ' + fileAsset.displayName);
Logger.info(TAG, 'fileAsset.uri 0:' + fileAsset.uri);
Logger.info(TAG, 'myUri: ' + myUri);
this.filename = fileAsset.displayName;
router.pushUrl({
url: 'pages/EditFile',
params: {
fileName: this.filename,
uri: myUri
}
}, router.RouterMode.Standard);
fetchFileResult.close();
});
});
}
/**
* 拉起picker选择图片/视频
*/
async callFilePickerSelectImage(): Promise<void> { // async 用于申明一个 function 是异步的
let array: string[];
try {
// 设置photoPicker的参数
let PhotoSelectOptions = new picker.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE; // 过滤选择媒体文件类型
PhotoSelectOptions.maxSelectNumber = MAX_SELECT_NUM; // 选择媒体文件的最大数目
let mediaFlag = false;
let photoPicker = new picker.PhotoViewPicker(); // 使用图库选择器对象前需要先创建PhotoViewPicker实例
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
Logger.info(TAG, 'PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult)); // 日志中记录成功信息
if (PhotoSelectResult !== null && PhotoSelectResult !== undefined) { // 接口采用callback异步返回形式返回PhotoSelectResult对象故进行下一步操作前要先判断是否已经成功返回PhotoSelectResult对象了
// PhotoSelectResult为返回的结果集。
// 其中包含Array<string>类型的photoUris为返回图库选择后的媒体文件的uri数组还包含boolean类型的isOriginalPhoto指示返回图库选择后的媒体文件是否为原图。
// 声明变量array其取值为PhotoSelectResult中的数组。
array = PhotoSelectResult['photoUris'];
array.forEach((value) => {
this.uri = value;
mediaFlag = true;
Logger.info(TAG, `select image/video uri: ${this.uri}`);
})
}
if (mediaFlag) {
this.getFilenameByUriForMedia(array);
}
})
.catch((err) => {
Logger.error(TAG, 'PhotoViewPicker.select failed with err: ' + err);
});
} catch (err) {
Logger.error(TAG, 'PhotoViewPicker failed with err: ' + err);
}
}
aboutToAppear(): void {
this.mediaFileUri.getAllFiles(getContext(this));
}
aboutToDisappear(): void {
this.fileNameList = [];
this.fileSizeList = [];
this.fileUriList = [];
}
onPageShow(): void {
this.mediaFileUri.getAllFiles(getContext(this));
}
build() {
Scroll(this.scroller) {
Row() {
Column() {
Row() {
Column() {
Text($r('app.string.last_open'))
.fontFamily('HarmonyHeiTi-Bold')
.fontSize(30)
.fontWeight(700)
.textAlign(TextAlign.Start)
.fontColor('#182431')
.lineHeight(41)
.width('70%')
.height(41)
}
.width('50%')
.margin({ left: '6.7%' })
.alignItems(HorizontalAlign.Start)
Row() {
Image($r('app.media.ic_saveas'))
.width(25)
.height(25)
.margin({ right: '12%' })
.id('newFile')
.onClick(() => {
this.callFilePickerSaveFile();
})
Image($r('app.media.ic_picture'))
.width(25)
.height(25)
.id('picture')
.margin({ right: '12%' })
.onClick(() => {
this.callFilePickerSelectImage();
})
Image($r('app.media.ic_folder'))
.width(25)
.height(25)
.id('folder')
.opacity(1)
.margin({ right: '6%' })
.onClick(() => {
this.callFilePickerSelectFile();
})
}
.justifyContent(FlexAlign.End)
.padding({ right: '8%' })
.width('50%')
}
// 第一行结束
.width('100%')
.height(41)
.margin({ top: 7, left: 24, right: 25, bottom: 8 })
Column() {
List({ space: 12, initialIndex: 0 }) {
ForEach(this.fileNameList, (item, index) => {
ListItem() {
Row() {
Image($r('app.media.ic_docs'))
.width('3.3%')
.height(22)
.margin({ left: 15, right: 19 })
Text(item)
.fontSize(16)
.fontFamily('HarmonyHeiTi-Medium')
.fontColor('#182431')
.lineHeight(22)
.fontWeight(500)
.textAlign(TextAlign.Start)
.margin({ left: 0, right: 16 })
.width('64.5%')
Text('Size: ' + JSON.stringify(this.fileSizeList[index]) + 'B')
.fontSize(14)
.fontFamily('HarmonyHeiTi-Medium')
.lineHeight(19)
.fontColor('#182431')
.textAlign(TextAlign.End)
.opacity(0.6)
.width('20.8%')
.margin({ left: 0, right: 12 })
}
.id('fileItem' + index)
.borderRadius(24)
.width('100%')
.height(64)
.padding({ right: 12 })
.backgroundColor('#FFFFFF')
}
.onClick(() => {
Logger.info(TAG, 'fileAsset.displayName fileName item: ' + item);
router.pushUrl({
url: 'pages/EditFile',
params: {
fileName: item,
uri: this.fileUriList[index]
}
}, router.RouterMode.Standard);
})
}, item => item)
}
.listDirection(Axis.Vertical) // 排列方向
.id('indexList')
.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果
.scrollBar(BarState.Auto)
.alignListItem(ListItemAlign.Center)
.margin({ top: '1%', left: 12, right: 12 })
}
.height('100%')
.width('100%')
}
.alignItems(HorizontalAlign.Center)
.width('100%')
.height('100%')
.backgroundColor('#f1f3f5')
}
.height('100%')
}
}
}

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.app.ability.common';
import fs from '@ohos.file.fs'; // 实现应用文件访问能力
import router from '@ohos.router';
import picker from '@ohos.file.picker';
import mediaLibrary from '@ohos.multimedia.mediaLibrary';
import MediaFileUri from '../media/MediaFileUri';
import Logger from '../common/Logger';
const TAG = 'ViewMedia';
@Entry
@Component
struct ViewMedia {
@State myContext: Context = getContext(this) as common.UIAbilityContext;
@State myFileSizes: number[] = [];
@State myFileNames: string[] = [];
@State myFileTypes: number[] = [];
@StorageLink('myFileName') myFileName: string = '';
@StorageLink('myFileSize') myFileSize: number = 0;
@State myUris: string[] = router.getParams()['uris'];
@State uri: string = 'Hello World';
@StorageLink('showPauses') showPauses: Array<number> = [];
mediaFileUri: MediaFileUri = new MediaFileUri();
scroller: Scroller = new Scroller();
currentUri: string = '';
controllers: Array<VideoController> = [];
/**
* 拉起picker保存图片/视频
*/
async callFilePickerSaveImageVideo(): Promise<void> {
try {
let PhotoSaveOptions = new picker.PhotoSaveOptions();
PhotoSaveOptions.newFileNames = ['PhotoViewPicker01.jpg', 'PhotoViewPicker01.mp4'];
let photoPicker = new picker.PhotoViewPicker();
photoPicker.save(PhotoSaveOptions).then((PhotoSaveResult) => {
Logger.info(TAG, 'PhotoViewPicker.save successfully, PhotoSaveResult uri: ' + JSON.stringify(PhotoSaveResult));
if (PhotoSaveResult !== null && PhotoSaveResult !== undefined) {
PhotoSaveResult.forEach((value) => {
this.uri = value;
Logger.info(TAG, `save image/video uri: ${this.uri}`);
})
}
}).catch((err) => {
Logger.error(TAG, 'PhotoViewPicker.save failed with err: ' + err);
});
} catch (err) {
Logger.error(TAG, 'PhotoViewPicker failed with err: ' + err);
}
}
onPageShow() {
this.getImagesInfo();
this.myFileName = this.myFileNames[0];
this.myFileSize = this.myFileSizes[0];
Logger.info(TAG, 'onPageShow getFilenameByUriForMedia this.myFileName ' + this.myFileName);
Logger.info(TAG, 'onPageShow getFilenameByUriForMedia begin' + this.myFileSize);
AppStorage.SetOrCreate('myFileName', this.myFileName);
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
}
getMediaNameByUri(myUri: string, index: number) {
Logger.info(TAG, 'getMediaNameByUri getFilenameByUriForMedia begin');
// 创建文件获取选项此处参数为获取image类型的文件资源
let imagesFetchOp = {
selections: mediaLibrary.FileKey.MEDIA_TYPE + '= ? OR ' + mediaLibrary.FileKey.MEDIA_TYPE + '= ?',
selectionArgs: [mediaLibrary.MediaType.IMAGE.toString(), mediaLibrary.MediaType.VIDEO.toString()],
uri: myUri
};
let media = mediaLibrary.getMediaLibrary(getContext(this));
// 获取文件资源使用callback方式返回异步结果
media.getFileAssets(imagesFetchOp, async (error, fetchFileResult) => {
// 判断获取的文件资源的检索结果集是否为undefined若为undefined则接口调用失败
Logger.info(TAG, 'getFilenameByUriForMedia getMediaLibrary is ok');
if (fetchFileResult === undefined) {
Logger.error(TAG, 'get fetchFileResult failed with error: ' + error);
return;
}
// 获取文件检索结果集中的总数
const count = fetchFileResult.getCount();
Logger.info(TAG, 'getFilenameByUriForMedia count is: ' + count);
// 判断结果集中的数量是否小于0小于0时表示接口调用失败
if (count < 0) {
Logger.error(TAG, 'get count from fetchFileResult failed, count: ' + count);
return;
}
// 判断结果集中的数量是否等于0等于0时表示接口调用成功但是检索结果集为空请检查文件获取选项参数配置是否有误和设备中是否存在相应文件
if (count === 0) {
Logger.info(TAG, 'The count of fetchFileResult is zero');
return;
}
Logger.info(TAG, 'Get fetchFileResult successfully, count: ' + count);
// 获取文件检索结果集中的第一个资源使用callback方式返回异步结果文件数量较多时请使用getAllObject接口
fetchFileResult.getFirstObject(async (error, fileAsset) => {
// 检查获取的第一个资源是否为undefined若为undefined则接口调用失败
if (fileAsset === undefined) {
Logger.error(TAG, 'get first object failed with error: ' + error);
return;
}
Logger.info(TAG, 'fileAsset.displayName ' + '0 : ' + fileAsset.displayName);
Logger.info(TAG, 'fileAsset.uri 0:' + fileAsset.uri);
Logger.info(TAG, 'myUri: ' + myUri);
this.myFileTypes[index] = fileAsset.mediaType
this.myFileName = fileAsset.displayName;
this.myFileNames[index] = this.myFileName;
AppStorage.SetOrCreate('myFileName', this.myFileName);
AppStorage.SetOrCreate('myFileTypes', this.myFileTypes);
if (this.myFileTypes[index] === mediaLibrary.MediaType.VIDEO) {
Logger.info(TAG, 'getMediaNameByUri set showPauses for VIDEO');
this.showPauses[index] = 1;
}
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo this.myFileName ' + this.myFileName);
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo index ' + index);
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo this.myFileTypes[index] ' + this.myFileTypes[index]);
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo this.myFileNames[index] ' + this.myFileNames[index]);
fetchFileResult.close();
});
});
}
getImagesInfo() {
for (let index = 0; index < this.myUris.length; index++) {
Logger.info(TAG, 'getFilenameByUriForMedia getImagesInfo index: ' + index);
this.controllers[index] = new VideoController();
this.getMediaNameByUri(this.myUris[index], index);
this.myFileSizes[index] = this.mediaFileUri.myGetFileSize(this.myUris[index], fs.OpenMode.READ_ONLY);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileNames[index]: ' + this.myFileNames[index] + ' index ' + index);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileSizes[index]' + this.myFileSizes[index]);
Logger.info(TAG, 'getFilenameByUriForMedia getVideosInfo this.myFileTypes[index] cc' + this.myFileTypes[index]);
}
}
build() {
Column() {
// 顶部的行容器
Row() {
// 后退箭头
Row() {
Image($r('app.media.ic_back'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.align(Alignment.Start)
.id('back2Index')
.onClick(() => {
router.back();
})
}
.width('12.8%')
.padding({ left: '7.2%' })
// 文件名及信息
Column() {
Row() {
Text(this.myFileName)
.focusable(true)
.focusOnTouch(true)
.fontSize(20)
.fontFamily('HarmonyHeiTi-Bold')
.fontColor('#182431')
.textAlign(TextAlign.Start)
.fontWeight(700)
.lineHeight(28)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.align(Alignment.Start)
.margin({ top: '0.4%', bottom: '0.3%' })
Row() {
Text('size: ' + JSON.stringify(this.myFileSize) + 'B')
.focusable(true)
.focusOnTouch(true)
.opacity(0.6)
.fontFamily('HarmonyHeiTi')
.fontSize(14)
.fontColor('#182431')
.textAlign(TextAlign.Start)
.lineHeight(19)
.fontWeight(400)
}
.width('100%')
.margin({ top: '0.3%', bottom: '0.5%' })
.align(Alignment.Start)
}
.width('45%')
.margin({ left: '5%' })
// 右边一个图标,另存为
Row() {
Image($r('app.media.ic_saveas'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.visibility(Visibility.Hidden)
.onClick(() => {
// 另存为点击事件
})
}
.height('100%')
.width('37.2%')
.padding({ right: '7.2%' })
.justifyContent(FlexAlign.End)
}
.height('7.4%')
.width('100%')
Scroll(this.scroller) {
// 显示媒体文件的容器
Column() {
List({ space: 20, initialIndex: 0 }) {
ForEach(this.myUris, (uri, index) => {
ListItem() {
Column() {
Image(uri)
.borderRadius(24)
.visibility(this.myFileTypes[index] === mediaLibrary.MediaType.IMAGE ? Visibility.Visible : Visibility.Hidden)
.onClick(() => {
this.myFileSize = this.myFileSizes[index];
this.myFileName = this.myFileNames[index];
AppStorage.SetOrCreate('myFileName', this.myFileName);
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
Logger.info(TAG, 'Image onClick index is ' + index);
Logger.info(TAG, 'Image onClick this.myFileNames[index] is ' + this.myFileNames[index]);
Logger.info(TAG, 'Image onClick myFileName is ' + this.myFileName);
Logger.info(TAG, 'Image onClick myFileName is ' + this.myFileSize);
})
Stack({ alignContent: Alignment.Center }) {
Video({
src: uri,
controller: this.controllers[index]
})
.autoPlay(false)
.controls(true)
.borderRadius(24)
//.height('22.7%')
.visibility(this.myFileTypes[index] === mediaLibrary.MediaType.VIDEO ? Visibility.Visible : Visibility.Hidden)
Image($r('app.media.ic_PAUSE'))
.width(25)
.height(25)
.onClick(() => {
this.controllers[index].start();
this.showPauses[index] = 0;
})
.visibility(this.showPauses[index] === 0 ? Visibility.Hidden : Visibility.Visible)
}
.onClick(() => {
this.myFileSize = this.myFileSizes[index];
this.myFileName = this.myFileNames[index];
AppStorage.SetOrCreate('myFileName', this.myFileName);
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
})
}
.height('100%')
}
.height('25%')
}, item => item)
}
.id('picScroller')
.scrollBar(BarState.Auto)
}
}
.padding({ top: '1.5%', left: '6.7%', right: '6.7%' })
}
.backgroundColor('#f1f3f5')
.height('100%')
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ts",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:app_name",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"visible": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"ohos.want.action.sendData"
],
"uris": [
{
"scheme": "file",
"type": "application/txt"
}
]
}
]
}
],
"requestPermissions":[
{
"name": "ohos.permission.MEDIA_LOCATION",
"reason": "$string:read_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.READ_MEDIA",
"reason": "$string:read_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.WRITE_MEDIA",
"reason": "$string:write_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name" : "ohos.permission.WRITE_IMAGEVIDEO",
"reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.READ_IMAGEVIDEO",
"reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"always"
}
}
]
}
}

View File

@ -0,0 +1,80 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "call_photo",
"value": "调用Photo获取FileUri"
},
{
"name": "call_file_picker_select_file",
"value": "调用picker获取文件"
},
{
"name": "call_file_picker_save_file",
"value": "调用picker保存文件"
},
{
"name": "call_file_picker_select_audio",
"value": "获取media file"
},
{
"name": "call_file_picker_save_audio",
"value": "调用picker保存音频"
},
{
"name": "call_file_picker_select_image_video",
"value": "调用picker获取图片/视频"
},
{
"name": "call_file_picker_save_image_video",
"value": "调用picker保存图片/视频"
},
{
"name": "read_permission",
"value": "user read file permission"
},
{
"name": "write_permission",
"value": "user write file permission"
},
{
"name": "write_image_video_permission",
"value": "user write image video permission"
},
{
"name": "open_file",
"value": "openFile"
},
{
"name": "get_log",
"value": "获取log"
},
{
"name": "clear_log",
"value": "清除log"
},
{
"name": "last_open",
"value": "最近打开"
},
{
"name": "editable",
"value": "进入编辑状态"
},
{
"name": "saved",
"value": "已保存"
}
]
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_PAUSE</title>
<defs>
<path d="M12,1 C18.0751322,1 23,5.92486775 23,12 C23,18.0751322 18.0751322,23 12,23 C5.92486775,23 1,18.0751322 1,12 C1,5.92486775 5.92486775,1 12,1 Z M12,2.5 C6.75329488,2.5 2.5,6.75329488 2.5,12 C2.5,17.2467051 6.75329488,21.5 12,21.5 C17.2467051,21.5 21.5,17.2467051 21.5,12 C21.5,6.75329488 17.2467051,2.5 12,2.5 Z M16.1490452,13.0797236 L10.8798388,16.1534274 C10.2835239,16.5012777 9.51812673,16.2998574 9.17027637,15.7035425 C9.0587605,15.5123725 9,15.295022 9,15.0737038 L9,8.92629625 C9,8.23594031 9.55964406,7.67629625 10.25,7.67629625 C10.4713183,7.67629625 10.6886687,7.73505675 10.8798388,7.84657262 L16.1490452,10.9202764 C16.7453601,11.2681267 16.9467804,12.0335239 16.5989301,12.6298388 C16.4902816,12.8160933 16.3352998,12.9710751 16.1490452,13.0797236 Z" id="path-1"></path>
</defs>
<g id="ic_PAUSE" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_back</title>
<defs>
<path d="M5.56079777,13.7499686 L11.5303301,19.7196699 L11.5640714,19.7556673 C11.8227547,20.0502619 11.8115076,20.4991526 11.5303301,20.7803301 C11.2491526,21.0615076 10.8002619,21.0727547 10.5056673,20.8140714 L10.4696699,20.7803301 L3.43929777,13.7499686 L5.56079777,13.7499686 Z M10.4696699,3.21966991 C10.7625631,2.9267767 11.2374369,2.9267767 11.5303301,3.21966991 C11.8115076,3.5008474 11.8227547,3.94973814 11.5640714,4.24433269 L11.5303301,4.28033009 L4.5605,11.25 L21.25,11.25 C21.6494202,11.25 21.9759152,11.56223 21.9987268,11.9559318 L22,12 C22,12.3994202 21.68777,12.7259152 21.2940682,12.7487268 L21.25,12.75 L2.75,12.75 C2.09603793,12.75 1.76158663,11.9761547 2.19060357,11.5002723 L2.21966991,11.4696699 L10.4696699,3.21966991 Z" id="path-1"></path>
</defs>
<g id="ic_back" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="symbol/frame/symbol_grid24-copy" transform="translate(-0.017678, -0.017678)"></g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_docs</title>
<defs>
<path d="M14.75,1 L14.75,1.001 L21,7.25 L21,20 C21,21.6568542 19.6568542,23 18,23 L6,23 C4.34314575,23 3,21.6568542 3,20 L3,4 C3,2.34314575 4.34314575,1 6,1 L14.75,1 Z M13.25,2.499 L6,2.5 C5.17157288,2.5 4.5,3.17157288 4.5,4 L4.5,20 C4.5,20.8284271 5.17157288,21.5 6,21.5 L18,21.5 C18.8284271,21.5 19.5,20.8284271 19.5,20 L19.5,8.75 L15.5,8.75 C14.2573593,8.75 13.25,7.74264069 13.25,6.5 L13.25,2.499 Z M16.5,14.75 C16.9142136,14.75 17.25,15.0857864 17.25,15.5 C17.25,15.9142136 16.9142136,16.25 16.5,16.25 L7.5,16.25 C7.08578644,16.25 6.75,15.9142136 6.75,15.5 C6.75,15.0857864 7.08578644,14.75 7.5,14.75 L16.5,14.75 Z M11.5,10.5 C11.9142136,10.5 12.25,10.8357864 12.25,11.25 C12.25,11.6642136 11.9142136,12 11.5,12 L7.5,12 C7.08578644,12 6.75,11.6642136 6.75,11.25 C6.75,10.8357864 7.08578644,10.5 7.5,10.5 L11.5,10.5 Z M14.75,3.121 L14.75,6.5 C14.75,6.91421356 15.0857864,7.25 15.5,7.25 L18.879,7.25 L14.75,3.121 Z" id="path-1"></path>
</defs>
<g id="ic_docs" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill-opacity="0.6" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_folder</title>
<defs>
<path d="M8.09016905,3 L9.072,4.005 L18.7543478,4.00576923 C20.2731309,4.00576923 21.5043478,5.23698617 21.5043478,6.75576923 L21.5047569,7.40410415 C22.398835,7.92349194 23,8.89154117 23,10 L23,18.0300725 C23,19.6869267 21.6568542,21.0300725 20,21.0300725 L4,21.0300725 C2.34314575,21.0300725 1,19.6869267 1,18.0300725 L1,6 C1,4.34314575 2.34314575,3 4,3 L8.09016905,3 Z M7.45880872,4.5 L4,4.5 C3.17157288,4.5 2.5,5.17157288 2.5,6 L2.5,18.0300725 C2.5,18.8584996 3.17157288,19.5300725 4,19.5300725 L20,19.5300725 C20.8284271,19.5300725 21.5,18.8584996 21.5,18.0300725 L21.5,10 C21.5,9.17157288 20.8284271,8.5 20,8.5 L12,8.5 C11.5962468,8.5 11.2095421,8.33723333 10.9273184,8.04850093 L8.27087558,5.33280382 C8.22847391,5.29755785 8.19001909,5.25772693 8.15627192,5.21407187 L7.45880872,4.5 Z M20.004,7 L20.0043478,6.75576923 C20.0043478,6.06541329 19.4447038,5.50576923 18.7543478,5.50576923 L10.538,5.505 L12,7 L20.004,7 Z" id="path-1"></path>
</defs>
<g id="ic_folder" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Combined-Shape" fill-opacity="1" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_picture</title>
<defs>
<path d="M18.9585062,2.01869159 C20.6153605,2.01869159 21.9585062,3.36183734 21.9585062,5.01869159 L21.9584938,17.0416916 L21.9652216,18.9654155 L21.9534135,19.1326591 C21.8621671,20.7074663 20.5561871,21.9563863 18.9585062,21.9563863 L5.04149378,21.9563863 C3.38463953,21.9563863 2.04149378,20.6132405 2.04149378,18.9563863 L2.04149378,5.01869159 C2.04149378,3.36183734 3.38463953,2.01869159 5.04149378,2.01869159 L18.9585062,2.01869159 Z M14.1128103,12.0182811 L5.68349378,20.4556916 L18.9585062,20.4563863 C19.7869333,20.4563863 20.4585062,19.7848134 20.4585062,18.9563863 L20.4584938,17.6626916 L14.8202839,12.0182811 C14.6245535,11.8227533 14.3079711,11.8229176 14.1128103,12.0182811 Z M18.9585062,3.51869159 L5.04149378,3.51869159 C4.21306665,3.51869159 3.54149378,4.19026446 3.54149378,5.01869159 L3.54149378,18.9563863 C3.54149378,19.3761836 3.71394404,19.755703 3.99186752,20.0279675 L13.0515998,10.9581715 C13.832243,10.1767177 15.0985728,10.1760605 15.8800266,10.9567037 L20.4584938,15.5396916 L20.4585062,5.01869159 C20.4585062,4.19026446 19.7869333,3.51869159 18.9585062,3.51869159 Z M7.5186722,6.00623053 C8.34348548,6.00623053 9.01244813,6.67563863 9.01244813,7.50155763 C9.01244813,8.32722741 8.34348548,8.99688474 7.5186722,8.99688474 C6.69385892,8.99688474 6.02489627,8.32722741 6.02489627,7.50155763 C6.02489627,6.67563863 6.69385892,6.00623053 7.5186722,6.00623053 Z" id="path-1"></path>
</defs>
<g id="ic_picture" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="symbol/frame/symbol_grid24"></g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Combined-Shape" fill="#182431" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_refresh</title>
<defs>
<path d="M22.3414769,15.7576235 C22.3414769,15.7576235 22.3414769,15.7576235 22.3414769,15.7576235 C22.7675941,14.58516 23,13.3197207 23,12 L21.8970644,12 C21.083171,12 20.42338,12.659791 20.42338,13.4736844 C20.42338,13.7479861 20.4999371,14.016844 20.6444353,14.25 L21.6247463,15.831787 C21.7412468,16.0197728 21.9880826,16.0777198 22.1760669,15.9612167 C22.2524981,15.9138485 22.3107624,15.8421345 22.3414769,15.7576235 Z M22.823695,13.9714637 C22.9406935,13.3251822 23,12.6661847 23,12 C23,5.92486775 18.0751322,1 12,1 C11.2174632,1 10.44502,1.08183322 9.69172269,1.24274766 C4.65590569,2.31846601 1,6.78563595 1,12 C1,18.0751322 5.92486775,23 12,23 C13.0917435,23 14.1629676,22.8407032 15.1884731,22.530585 C16.7020101,22.0728837 18.0947944,21.2926603 19.2766337,20.2494437 C19.5871723,19.9753294 19.6167001,19.5013746 19.3425858,19.190836 C19.0684716,18.8802974 18.5945167,18.8507696 18.2839781,19.1248839 C17.2629258,20.0261728 16.0603686,20.6998329 14.7542841,21.0947995 C13.8691955,21.3624549 12.9442454,21.5 12,21.5 C6.75329488,21.5 2.5,17.2467051 2.5,12 C2.5,7.496884 5.65786226,3.63827588 10.0050734,2.70965302 C10.6555297,2.57070679 11.322948,2.5 12,2.5 C17.2467051,2.5 21.5,6.75329488 21.5,12 C21.5,12.5764741 21.4487412,13.1460473 21.3476867,13.7042571 C21.2738996,14.1118455 21.544499,14.5020775 21.9520875,14.5758645 C22.3596759,14.6496516 22.7499079,14.3790522 22.823695,13.9714637 Z" id="path-1"></path>
</defs>
<g id="ic_refresh" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_save</title>
<defs>
<path d="M19,2 C20.65675,2 22,3.34325 22,5 L22,19 C22,20.65675 20.65675,22 19,22 L5,22 C3.34325,22 2,20.65675 2,19 L2,5 C2,3.34325 3.34325,2 5,2 Z M6.5,3.5 L5,3.5 C4.17275,3.5 3.5,4.17275 3.5,5 L3.5,19 C3.5,19.82725 4.17275,20.5 5,20.5 L19,20.5 C19.82725,20.5 20.5,19.82725 20.5,19 L20.5,5 C20.5,4.17275 19.82725,3.5 19,3.5 L17.5,3.5 L17.5,7.75 C17.5,8.85275 16.57175,9.75 15.43075,9.75 L8.56925,9.75 C7.42825,9.75 6.5,8.85275 6.5,7.75 L6.5,3.5 Z M16.75,15.75 C17.16425,15.75 17.5,16.08575 17.5,16.5 C17.5,16.91425 17.16425,17.25 16.75,17.25 L7.25,17.25 C6.83575,17.25 6.5,16.91425 6.5,16.5 C6.5,16.08575 6.83575,15.75 7.25,15.75 Z M16,3.5 L8,3.5 L8,7.75 C8,8.02575 8.25525,8.25 8.56925,8.25 L15.43075,8.25 C15.74475,8.25 16,8.02575 16,7.75 L16,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_save" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_saveas</title>
<defs>
<path d="M19,2 C20.6568542,2 22,3.34314575 22,5 L22,16 C22,17.486255 20.9192103,18.7200781 19.5006962,18.9584039 L19.5,19 C19.5,20.6568542 18.1568542,22 16.5,22 L5,22 C3.34314575,22 2,20.6568542 2,19 L2,7.5 C2,5.84314575 3.34314575,4.5 5,4.5 L5.0414298,4.50029469 C5.27934741,3.08129303 6.51339894,2 8,2 L19,2 Z M16.5,6 L5,6 C4.17157288,6 3.5,6.67157288 3.5,7.5 L3.5,19 C3.5,19.8284271 4.17157288,20.5 5,20.5 L16.5,20.5 C17.3284271,20.5 18,19.8284271 18,19 L18,7.5 C18,6.67157288 17.3284271,6 16.5,6 Z M10.75,8.5 C11.1642136,8.5 11.5,8.83578644 11.5,9.25 L11.5,12.5 L14.75,12.5 C15.1642136,12.5 15.5,12.8357864 15.5,13.25 C15.5,13.6642136 15.1642136,14 14.75,14 L11.5,14 L11.5,17.25 C11.5,17.6642136 11.1642136,18 10.75,18 C10.3357864,18 10,17.6642136 10,17.25 L10,14 L6.75,14 C6.33578644,14 6,13.6642136 6,13.25 C6,12.8357864 6.33578644,12.5 6.75,12.5 L10,12.5 L10,9.25 C10,8.83578644 10.3357864,8.5 10.75,8.5 Z M19,3.5 L8,3.5 C7.37858219,3.5 6.84542259,3.87787826 6.6177703,4.41638567 L6.446,4.5 L16.5,4.5 C18.1568542,4.5 19.5,5.84314575 19.5,7.5 L19.5018115,17.5524263 C19.5298841,17.4954305 19.5574163,17.4381207 19.5844015,17.3805035 C20.1225957,17.1539084 20.5,16.621028 20.5,16 L20.5,5 C20.5,4.17157288 19.8284271,3.5 19,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_saveas" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_share</title>
<defs>
<path d="M12.25,2 C13.9068542,2 15.25,3.34314575 15.25,5 C15.25,6.65685425 13.9068542,8 12.25,8 C11.9804725,8 11.7192467,7.96445647 11.4707541,7.89780096 L5.93201456,16.2048482 C6.40136404,16.6003451 6.74770229,17.1371819 6.90542312,17.7497523 L17.0945769,17.7497523 C17.4276951,16.4559576 18.6022096,15.5 20,15.5 C21.6568542,15.5 23,16.8431458 23,18.5 C23,20.1568542 21.6568542,21.5 20,21.5 C18.6025704,21.5 17.4283015,20.5445359 17.094835,19.2512495 L6.90516499,19.2512495 C6.57169851,20.5445359 5.39742955,21.5 4,21.5 C2.34314575,21.5 1,20.1568542 1,18.5 C1,16.8431458 2.34314575,15.5 4,15.5 C4.1922717,15.5 4.38031877,15.5180878 4.56253245,15.5526546 L10.1618944,7.15402617 C9.59951533,6.60875215 9.25,5.84519291 9.25,5 C9.25,3.34314575 10.5931458,2 12.25,2 Z M4,17 C3.17157288,17 2.5,17.6715729 2.5,18.5 C2.5,19.3284271 3.17157288,20 4,20 C4.82842712,20 5.5,19.3284271 5.5,18.5 C5.5,17.6715729 4.82842712,17 4,17 Z M20,17 C19.1715729,17 18.5,17.6715729 18.5,18.5 C18.5,19.3284271 19.1715729,20 20,20 C20.8284271,20 21.5,19.3284271 21.5,18.5 C21.5,17.6715729 20.8284271,17 20,17 Z M12.25,3.5 C11.4215729,3.5 10.75,4.17157288 10.75,5 C10.75,5.82842712 11.4215729,6.5 12.25,6.5 C13.0784271,6.5 13.75,5.82842712 13.75,5 C13.75,4.17157288 13.0784271,3.5 12.25,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_share" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_writting</title>
<defs>
<path d="M19.2071068,2.95710678 L21.0428932,4.79289322 C21.4334175,5.18341751 21.4334175,5.81658249 21.0428932,6.20710678 L5.83578643,21.4142136 C5.46071368,21.7892863 4.95200586,22.0000001 4.42157289,22.0000001 L2.99999994,22.0000001 C2.44771521,22.0000001 1.99999994,21.5522848 1.99999994,21.0000001 L1.99999994,19.5784271 C1.99999994,19.0479941 2.21071368,18.5392863 2.58578643,18.1642136 L17.7928932,2.95710678 C18.1834175,2.56658249 18.8165825,2.56658249 19.2071068,2.95710678 Z M21.6089984,20.5 C22.023212,20.5 22.3589984,20.8357864 22.3589984,21.25 C22.3589984,21.6642136 22.023212,22 21.6089984,22 L11.6089984,22 C11.1947849,22 10.8589984,21.6642136 10.8589984,21.25 C10.8589984,20.8357864 11.1947849,20.5 11.6089984,20.5 L21.6089984,20.5 Z M16.2139999,6.65721356 L3.6464466,19.2248737 C3.55267841,19.3186419 3.49999996,19.4458189 3.49999996,19.5784271 L3.49999996,20.5 L4.42157287,20.5 C4.55418111,20.5 4.68135807,20.4473216 4.77512625,20.3535534 L17.3419999,7.78521356 L16.2139999,6.65721356 Z M18.5,4.37132034 L17.2749999,5.59621356 L18.4029999,6.72421356 L19.6286797,5.5 L18.5,4.37132034 Z" id="path-1"></path>
</defs>
<g id="ic_writting" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,7 @@
{
"src": [
"pages/Index",
"pages/EditFile",
"pages/ViewMedia"
]
}

View File

@ -0,0 +1,80 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "call_photo",
"value": "getFileUriFromPhoto"
},
{
"name": "call_file_picker_select_file",
"value": "call filePicker select file"
},
{
"name": "call_file_picker_save_file",
"value": "call filePicker save file "
},
{
"name": "call_file_picker_select_audio",
"value": "call filePicker select audio"
},
{
"name": "call_file_picker_save_audio",
"value": "call filePicker save audio "
},
{
"name": "call_file_picker_select_image_video",
"value": "call filePicker select image/video"
},
{
"name": "call_file_picker_save_image_video",
"value": "call filePicker save image/video"
},
{
"name": "read_permission",
"value": "user read file permission"
},
{
"name": "write_permission",
"value": "user write file permission"
},
{
"name": "write_image_video_permission",
"value": "user write image video permission"
},
{
"name": "open_file",
"value": "openFile"
},
{
"name": "get_log",
"value": "get log"
},
{
"name": "clear_log",
"value": "clear log"
},
{
"name": "last_open",
"value": "Recently Opened"
},
{
"name": "editable",
"value": "Editable"
},
{
"name": "saved",
"value": "Saved"
}
]
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_PAUSE</title>
<defs>
<path d="M12,1 C18.0751322,1 23,5.92486775 23,12 C23,18.0751322 18.0751322,23 12,23 C5.92486775,23 1,18.0751322 1,12 C1,5.92486775 5.92486775,1 12,1 Z M12,2.5 C6.75329488,2.5 2.5,6.75329488 2.5,12 C2.5,17.2467051 6.75329488,21.5 12,21.5 C17.2467051,21.5 21.5,17.2467051 21.5,12 C21.5,6.75329488 17.2467051,2.5 12,2.5 Z M16.1490452,13.0797236 L10.8798388,16.1534274 C10.2835239,16.5012777 9.51812673,16.2998574 9.17027637,15.7035425 C9.0587605,15.5123725 9,15.295022 9,15.0737038 L9,8.92629625 C9,8.23594031 9.55964406,7.67629625 10.25,7.67629625 C10.4713183,7.67629625 10.6886687,7.73505675 10.8798388,7.84657262 L16.1490452,10.9202764 C16.7453601,11.2681267 16.9467804,12.0335239 16.5989301,12.6298388 C16.4902816,12.8160933 16.3352998,12.9710751 16.1490452,13.0797236 Z" id="path-1"></path>
</defs>
<g id="ic_PAUSE" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_back</title>
<defs>
<path d="M5.56079777,13.7499686 L11.5303301,19.7196699 L11.5640714,19.7556673 C11.8227547,20.0502619 11.8115076,20.4991526 11.5303301,20.7803301 C11.2491526,21.0615076 10.8002619,21.0727547 10.5056673,20.8140714 L10.4696699,20.7803301 L3.43929777,13.7499686 L5.56079777,13.7499686 Z M10.4696699,3.21966991 C10.7625631,2.9267767 11.2374369,2.9267767 11.5303301,3.21966991 C11.8115076,3.5008474 11.8227547,3.94973814 11.5640714,4.24433269 L11.5303301,4.28033009 L4.5605,11.25 L21.25,11.25 C21.6494202,11.25 21.9759152,11.56223 21.9987268,11.9559318 L22,12 C22,12.3994202 21.68777,12.7259152 21.2940682,12.7487268 L21.25,12.75 L2.75,12.75 C2.09603793,12.75 1.76158663,11.9761547 2.19060357,11.5002723 L2.21966991,11.4696699 L10.4696699,3.21966991 Z" id="path-1"></path>
</defs>
<g id="ic_back" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="symbol/frame/symbol_grid24-copy" transform="translate(-0.017678, -0.017678)"></g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_docs</title>
<defs>
<path d="M14.75,1 L14.75,1.001 L21,7.25 L21,20 C21,21.6568542 19.6568542,23 18,23 L6,23 C4.34314575,23 3,21.6568542 3,20 L3,4 C3,2.34314575 4.34314575,1 6,1 L14.75,1 Z M13.25,2.499 L6,2.5 C5.17157288,2.5 4.5,3.17157288 4.5,4 L4.5,20 C4.5,20.8284271 5.17157288,21.5 6,21.5 L18,21.5 C18.8284271,21.5 19.5,20.8284271 19.5,20 L19.5,8.75 L15.5,8.75 C14.2573593,8.75 13.25,7.74264069 13.25,6.5 L13.25,2.499 Z M16.5,14.75 C16.9142136,14.75 17.25,15.0857864 17.25,15.5 C17.25,15.9142136 16.9142136,16.25 16.5,16.25 L7.5,16.25 C7.08578644,16.25 6.75,15.9142136 6.75,15.5 C6.75,15.0857864 7.08578644,14.75 7.5,14.75 L16.5,14.75 Z M11.5,10.5 C11.9142136,10.5 12.25,10.8357864 12.25,11.25 C12.25,11.6642136 11.9142136,12 11.5,12 L7.5,12 C7.08578644,12 6.75,11.6642136 6.75,11.25 C6.75,10.8357864 7.08578644,10.5 7.5,10.5 L11.5,10.5 Z M14.75,3.121 L14.75,6.5 C14.75,6.91421356 15.0857864,7.25 15.5,7.25 L18.879,7.25 L14.75,3.121 Z" id="path-1"></path>
</defs>
<g id="ic_docs" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill-opacity="0.6" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_folder</title>
<defs>
<path d="M8.09016905,3 L9.072,4.005 L18.7543478,4.00576923 C20.2731309,4.00576923 21.5043478,5.23698617 21.5043478,6.75576923 L21.5047569,7.40410415 C22.398835,7.92349194 23,8.89154117 23,10 L23,18.0300725 C23,19.6869267 21.6568542,21.0300725 20,21.0300725 L4,21.0300725 C2.34314575,21.0300725 1,19.6869267 1,18.0300725 L1,6 C1,4.34314575 2.34314575,3 4,3 L8.09016905,3 Z M7.45880872,4.5 L4,4.5 C3.17157288,4.5 2.5,5.17157288 2.5,6 L2.5,18.0300725 C2.5,18.8584996 3.17157288,19.5300725 4,19.5300725 L20,19.5300725 C20.8284271,19.5300725 21.5,18.8584996 21.5,18.0300725 L21.5,10 C21.5,9.17157288 20.8284271,8.5 20,8.5 L12,8.5 C11.5962468,8.5 11.2095421,8.33723333 10.9273184,8.04850093 L8.27087558,5.33280382 C8.22847391,5.29755785 8.19001909,5.25772693 8.15627192,5.21407187 L7.45880872,4.5 Z M20.004,7 L20.0043478,6.75576923 C20.0043478,6.06541329 19.4447038,5.50576923 18.7543478,5.50576923 L10.538,5.505 L12,7 L20.004,7 Z" id="path-1"></path>
</defs>
<g id="ic_folder" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Combined-Shape" fill-opacity="1" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_picture</title>
<defs>
<path d="M18.9585062,2.01869159 C20.6153605,2.01869159 21.9585062,3.36183734 21.9585062,5.01869159 L21.9584938,17.0416916 L21.9652216,18.9654155 L21.9534135,19.1326591 C21.8621671,20.7074663 20.5561871,21.9563863 18.9585062,21.9563863 L5.04149378,21.9563863 C3.38463953,21.9563863 2.04149378,20.6132405 2.04149378,18.9563863 L2.04149378,5.01869159 C2.04149378,3.36183734 3.38463953,2.01869159 5.04149378,2.01869159 L18.9585062,2.01869159 Z M14.1128103,12.0182811 L5.68349378,20.4556916 L18.9585062,20.4563863 C19.7869333,20.4563863 20.4585062,19.7848134 20.4585062,18.9563863 L20.4584938,17.6626916 L14.8202839,12.0182811 C14.6245535,11.8227533 14.3079711,11.8229176 14.1128103,12.0182811 Z M18.9585062,3.51869159 L5.04149378,3.51869159 C4.21306665,3.51869159 3.54149378,4.19026446 3.54149378,5.01869159 L3.54149378,18.9563863 C3.54149378,19.3761836 3.71394404,19.755703 3.99186752,20.0279675 L13.0515998,10.9581715 C13.832243,10.1767177 15.0985728,10.1760605 15.8800266,10.9567037 L20.4584938,15.5396916 L20.4585062,5.01869159 C20.4585062,4.19026446 19.7869333,3.51869159 18.9585062,3.51869159 Z M7.5186722,6.00623053 C8.34348548,6.00623053 9.01244813,6.67563863 9.01244813,7.50155763 C9.01244813,8.32722741 8.34348548,8.99688474 7.5186722,8.99688474 C6.69385892,8.99688474 6.02489627,8.32722741 6.02489627,7.50155763 C6.02489627,6.67563863 6.69385892,6.00623053 7.5186722,6.00623053 Z" id="path-1"></path>
</defs>
<g id="ic_picture" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="symbol/frame/symbol_grid24"></g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Combined-Shape" fill="#182431" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_refresh</title>
<defs>
<path d="M22.3414769,15.7576235 C22.3414769,15.7576235 22.3414769,15.7576235 22.3414769,15.7576235 C22.7675941,14.58516 23,13.3197207 23,12 L21.8970644,12 C21.083171,12 20.42338,12.659791 20.42338,13.4736844 C20.42338,13.7479861 20.4999371,14.016844 20.6444353,14.25 L21.6247463,15.831787 C21.7412468,16.0197728 21.9880826,16.0777198 22.1760669,15.9612167 C22.2524981,15.9138485 22.3107624,15.8421345 22.3414769,15.7576235 Z M22.823695,13.9714637 C22.9406935,13.3251822 23,12.6661847 23,12 C23,5.92486775 18.0751322,1 12,1 C11.2174632,1 10.44502,1.08183322 9.69172269,1.24274766 C4.65590569,2.31846601 1,6.78563595 1,12 C1,18.0751322 5.92486775,23 12,23 C13.0917435,23 14.1629676,22.8407032 15.1884731,22.530585 C16.7020101,22.0728837 18.0947944,21.2926603 19.2766337,20.2494437 C19.5871723,19.9753294 19.6167001,19.5013746 19.3425858,19.190836 C19.0684716,18.8802974 18.5945167,18.8507696 18.2839781,19.1248839 C17.2629258,20.0261728 16.0603686,20.6998329 14.7542841,21.0947995 C13.8691955,21.3624549 12.9442454,21.5 12,21.5 C6.75329488,21.5 2.5,17.2467051 2.5,12 C2.5,7.496884 5.65786226,3.63827588 10.0050734,2.70965302 C10.6555297,2.57070679 11.322948,2.5 12,2.5 C17.2467051,2.5 21.5,6.75329488 21.5,12 C21.5,12.5764741 21.4487412,13.1460473 21.3476867,13.7042571 C21.2738996,14.1118455 21.544499,14.5020775 21.9520875,14.5758645 C22.3596759,14.6496516 22.7499079,14.3790522 22.823695,13.9714637 Z" id="path-1"></path>
</defs>
<g id="ic_refresh" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_save</title>
<defs>
<path d="M19,2 C20.65675,2 22,3.34325 22,5 L22,19 C22,20.65675 20.65675,22 19,22 L5,22 C3.34325,22 2,20.65675 2,19 L2,5 C2,3.34325 3.34325,2 5,2 Z M6.5,3.5 L5,3.5 C4.17275,3.5 3.5,4.17275 3.5,5 L3.5,19 C3.5,19.82725 4.17275,20.5 5,20.5 L19,20.5 C19.82725,20.5 20.5,19.82725 20.5,19 L20.5,5 C20.5,4.17275 19.82725,3.5 19,3.5 L17.5,3.5 L17.5,7.75 C17.5,8.85275 16.57175,9.75 15.43075,9.75 L8.56925,9.75 C7.42825,9.75 6.5,8.85275 6.5,7.75 L6.5,3.5 Z M16.75,15.75 C17.16425,15.75 17.5,16.08575 17.5,16.5 C17.5,16.91425 17.16425,17.25 16.75,17.25 L7.25,17.25 C6.83575,17.25 6.5,16.91425 6.5,16.5 C6.5,16.08575 6.83575,15.75 7.25,15.75 Z M16,3.5 L8,3.5 L8,7.75 C8,8.02575 8.25525,8.25 8.56925,8.25 L15.43075,8.25 C15.74475,8.25 16,8.02575 16,7.75 L16,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_save" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_saveas</title>
<defs>
<path d="M19,2 C20.6568542,2 22,3.34314575 22,5 L22,16 C22,17.486255 20.9192103,18.7200781 19.5006962,18.9584039 L19.5,19 C19.5,20.6568542 18.1568542,22 16.5,22 L5,22 C3.34314575,22 2,20.6568542 2,19 L2,7.5 C2,5.84314575 3.34314575,4.5 5,4.5 L5.0414298,4.50029469 C5.27934741,3.08129303 6.51339894,2 8,2 L19,2 Z M16.5,6 L5,6 C4.17157288,6 3.5,6.67157288 3.5,7.5 L3.5,19 C3.5,19.8284271 4.17157288,20.5 5,20.5 L16.5,20.5 C17.3284271,20.5 18,19.8284271 18,19 L18,7.5 C18,6.67157288 17.3284271,6 16.5,6 Z M10.75,8.5 C11.1642136,8.5 11.5,8.83578644 11.5,9.25 L11.5,12.5 L14.75,12.5 C15.1642136,12.5 15.5,12.8357864 15.5,13.25 C15.5,13.6642136 15.1642136,14 14.75,14 L11.5,14 L11.5,17.25 C11.5,17.6642136 11.1642136,18 10.75,18 C10.3357864,18 10,17.6642136 10,17.25 L10,14 L6.75,14 C6.33578644,14 6,13.6642136 6,13.25 C6,12.8357864 6.33578644,12.5 6.75,12.5 L10,12.5 L10,9.25 C10,8.83578644 10.3357864,8.5 10.75,8.5 Z M19,3.5 L8,3.5 C7.37858219,3.5 6.84542259,3.87787826 6.6177703,4.41638567 L6.446,4.5 L16.5,4.5 C18.1568542,4.5 19.5,5.84314575 19.5,7.5 L19.5018115,17.5524263 C19.5298841,17.4954305 19.5574163,17.4381207 19.5844015,17.3805035 C20.1225957,17.1539084 20.5,16.621028 20.5,16 L20.5,5 C20.5,4.17157288 19.8284271,3.5 19,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_saveas" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_share</title>
<defs>
<path d="M12.25,2 C13.9068542,2 15.25,3.34314575 15.25,5 C15.25,6.65685425 13.9068542,8 12.25,8 C11.9804725,8 11.7192467,7.96445647 11.4707541,7.89780096 L5.93201456,16.2048482 C6.40136404,16.6003451 6.74770229,17.1371819 6.90542312,17.7497523 L17.0945769,17.7497523 C17.4276951,16.4559576 18.6022096,15.5 20,15.5 C21.6568542,15.5 23,16.8431458 23,18.5 C23,20.1568542 21.6568542,21.5 20,21.5 C18.6025704,21.5 17.4283015,20.5445359 17.094835,19.2512495 L6.90516499,19.2512495 C6.57169851,20.5445359 5.39742955,21.5 4,21.5 C2.34314575,21.5 1,20.1568542 1,18.5 C1,16.8431458 2.34314575,15.5 4,15.5 C4.1922717,15.5 4.38031877,15.5180878 4.56253245,15.5526546 L10.1618944,7.15402617 C9.59951533,6.60875215 9.25,5.84519291 9.25,5 C9.25,3.34314575 10.5931458,2 12.25,2 Z M4,17 C3.17157288,17 2.5,17.6715729 2.5,18.5 C2.5,19.3284271 3.17157288,20 4,20 C4.82842712,20 5.5,19.3284271 5.5,18.5 C5.5,17.6715729 4.82842712,17 4,17 Z M20,17 C19.1715729,17 18.5,17.6715729 18.5,18.5 C18.5,19.3284271 19.1715729,20 20,20 C20.8284271,20 21.5,19.3284271 21.5,18.5 C21.5,17.6715729 20.8284271,17 20,17 Z M12.25,3.5 C11.4215729,3.5 10.75,4.17157288 10.75,5 C10.75,5.82842712 11.4215729,6.5 12.25,6.5 C13.0784271,6.5 13.75,5.82842712 13.75,5 C13.75,4.17157288 13.0784271,3.5 12.25,3.5 Z" id="path-1"></path>
</defs>
<g id="ic_share" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_writting</title>
<defs>
<path d="M19.2071068,2.95710678 L21.0428932,4.79289322 C21.4334175,5.18341751 21.4334175,5.81658249 21.0428932,6.20710678 L5.83578643,21.4142136 C5.46071368,21.7892863 4.95200586,22.0000001 4.42157289,22.0000001 L2.99999994,22.0000001 C2.44771521,22.0000001 1.99999994,21.5522848 1.99999994,21.0000001 L1.99999994,19.5784271 C1.99999994,19.0479941 2.21071368,18.5392863 2.58578643,18.1642136 L17.7928932,2.95710678 C18.1834175,2.56658249 18.8165825,2.56658249 19.2071068,2.95710678 Z M21.6089984,20.5 C22.023212,20.5 22.3589984,20.8357864 22.3589984,21.25 C22.3589984,21.6642136 22.023212,22 21.6089984,22 L11.6089984,22 C11.1947849,22 10.8589984,21.6642136 10.8589984,21.25 C10.8589984,20.8357864 11.1947849,20.5 11.6089984,20.5 L21.6089984,20.5 Z M16.2139999,6.65721356 L3.6464466,19.2248737 C3.55267841,19.3186419 3.49999996,19.4458189 3.49999996,19.5784271 L3.49999996,20.5 L4.42157287,20.5 C4.55418111,20.5 4.68135807,20.4473216 4.77512625,20.3535534 L17.3419999,7.78521356 L16.2139999,6.65721356 Z M18.5,4.37132034 L17.2749999,5.59621356 L18.4029999,6.72421356 L19.6286797,5.5 L18.5,4.37132034 Z" id="path-1"></path>
</defs>
<g id="ic_writting" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="合并形状" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,80 @@
{
"string": [
{
"name": "module_desc",
"value": "模块描述"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
},
{
"name": "call_photo",
"value": "调用Photo获取FileUri"
},
{
"name": "call_file_picker_select_file",
"value": "调用picker获取文件"
},
{
"name": "call_file_picker_save_file",
"value": "调用picker保存文件"
},
{
"name": "call_file_picker_select_audio",
"value": "调用picker获取音频"
},
{
"name": "call_file_picker_save_audio",
"value": "调用picker保存音频"
},
{
"name": "call_file_picker_select_image_video",
"value": "调用picker获取图片/视频"
},
{
"name": "call_file_picker_save_image_video",
"value": "调用picker保存图片/视频"
},
{
"name": "read_permission",
"value": "user read file permission"
},
{
"name": "write_permission",
"value": "user write file permission"
},
{
"name": "write_image_video_permission",
"value": "user write image video permission"
},
{
"name": "open_file",
"value": "openFile"
},
{
"name": "get_log",
"value": "获取log"
},
{
"name": "clear_log",
"value": "清除log"
},
{
"name": "last_open",
"value": "最近打开"
},
{
"name": "editable",
"value": "进入编辑状态"
},
{
"name": "saved",
"value": "已保存"
}
]
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
let abilityDelegator = undefined;
let abilityDelegatorArguments = undefined;
async function onAbilityCreateCallback(): Promise<void> {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err: object): Promise<void> {
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare ');
}
async onRun(): Promise<void> {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
let testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility';
let lMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback);
let cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName;
let debug = abilityDelegatorArguments.parameters['-D'];
if (debug == 'true') {
cmd += ' -D';
}
hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd);
abilityDelegator.executeShellCommand(cmd,
(err: object, d: object) => {
hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', JSON.stringify(d) ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.hilog';
import { describe, it, expect } from '@ohos/hypium';
import { Driver, ON} from '@ohos.UiTest';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
const TAG = '[Sample_Picker]';
const DOMAIN = 0xF811;
const BUNDLE = 'JSPicker_';
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
// 资源本地化
async function getResourceString(resource: Resource): Promise<string> {
let manage = abilityDelegator.getAppContext().resourceManager;
let text = await manage.getStringValue(resource);
return text;
}
export default function abilityTest() {
describe('abilityTest', function () {
it('StartAbilityFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbilityFunction_001 begin');
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
try {
await abilityDelegator.startAbility({
bundleName: "com.samples.picker",
abilityName: "EntryAbility"
});
done();
} catch (err) {
expect(err.code).assertEqual(0);
done();
}
hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbilityFunction_001 end');
})
/**
* Picker 赋权限
*/
// 点击允许
it('RequestPermissionFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'RequestPermissionFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(2000);
let permit = await getResourceString($r('app.string.permit'));
await driver.assertComponentExist(ON.text(permit));
let permit1 = await driver.findComponent(ON.text(permit));
await permit1.click();
await driver.delayMs(200);
let permit2 = await driver.findComponent(ON.text(permit));
await permit2.click();
await driver.delayMs(200);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'RequestPermissionFunction_001 end');
})
/**
* Picker 增加文件、文件夹
*/
// 点击增加文件、文件夹图标
it('NewFileFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'NewFileFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(200);
await driver.assertComponentExist(ON.id('newFile'));
let newFile = await driver.findComponent(ON.id('newFile'));
await newFile.click();
await driver.delayMs(3000);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(570, 116); // 新建文件夹
await driver.delayMs(1000);
let newDir = await getResourceString($r('app.string.new_dir'));
let confirm = await getResourceString($r('app.string.label_confirm'));
await driver.assertComponentExist(ON.text(newDir));
await driver.assertComponentExist(ON.text(confirm));
await driver.delayMs(2000);
// 使用text找到组件后点击不生效因此采用坐标
await driver.click(511, 1040); // 新建文件夹-点击确定图标
await driver.delayMs(2000);
await driver.click(655, 110); //新建文件并保存-点击保存图标
await driver.delayMs(500);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'NewFileFunction_001 end');
})
/**
* Picker 编辑文件
*/
// 编辑文件并保存
it('EditFileFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'EditFileFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(200);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(470, 210);
await driver.delayMs(500);
await driver.assertComponentExist(ON.id('editable'));
let editable = await driver.findComponent(ON.id('editable'));
await editable.click();
await driver.delayMs(200);
await driver.assertComponentExist(ON.id('textArea'));
let textArea = await driver.findComponent(ON.id('textArea'));
await textArea.inputText('File Content');
await driver.delayMs(500);
await driver.assertComponentExist(ON.id('save'));
let save = await driver.findComponent(ON.id('save'));
await save.click();
await driver.delayMs(200);
await driver.assertComponentExist(ON.id('backIndex'));
let backIndex = await driver.findComponent(ON.id('backIndex'));
await backIndex.click();
await driver.delayMs(200);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'EditFileFunction_001 end');
})
/**
* Picker 另存为
*/
// 点击文件另存为
it('SaveAsFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'SaveAsFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(200);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(470, 210);
await driver.delayMs(500);
await driver.assertComponentExist(ON.id('saveAs'));
let editable = await driver.findComponent(ON.id('saveAs'));
await editable.click();
await driver.delayMs(2000);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(570, 116); // 新建文件夹
await driver.delayMs(1000);
let newDir = await getResourceString($r('app.string.new_dir'));
let confirm = await getResourceString($r('app.string.label_confirm'));
await driver.assertComponentExist(ON.text(newDir));
await driver.assertComponentExist(ON.text(confirm));
await driver.delayMs(2000);
// 使用text找到组件后点击不生效因此采用坐标
await driver.click(511, 1040); // 新建文件夹-点击确定图标
await driver.delayMs(2000);
await driver.click(655, 110); //新建文件并保存-点击保存图标
await driver.delayMs(200);
await driver.pressBack();
await driver.delayMs(200);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'SaveAsFunction_001 end');
})
/**
* Picker 选择图片
*/
// 选择图片并查看
it('SelectPictureFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'SelectPictureFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(200);
await driver.assertComponentExist(ON.id('picture'));
let picture = await driver.findComponent(ON.id('picture'));
await picture.click();
await driver.delayMs(8000);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(653, 264);
await driver.click(49, 570);
await driver.click(675, 570);
await driver.delayMs(500);
let finishText = await getResourceString($r('app.string.finish'));
await driver.assertComponentExist(ON.text(finishText));
let finish = await driver.findComponent(ON.text(finishText));
await finish.click();
await driver.delayMs(1000);
await driver.assertComponentExist(ON.id('back2Index'));
let back2Index = await driver.findComponent(ON.id('back2Index'));
await back2Index.click();
await driver.delayMs(200);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'SelectPictureFunction_001 end');
})
/**
* Picker 选择视频
*/
// 选择视频并查看
it('SelectVideoFunction_001', 0, async function (done) {
hilog.info(DOMAIN, TAG, BUNDLE + 'SelectVideoFunction_001 begin');
let driver = await Driver.create();
await driver.delayMs(200);
await driver.assertComponentExist(ON.id('picture'));
let picture = await driver.findComponent(ON.id('picture'));
await picture.click();
await driver.delayMs(6000);
// 系统 picker 拉起的页面无法通过自定义id找到组件因此采用坐标
await driver.click(657, 41);
await driver.delayMs(1000);
await driver.click(355, 200);
await driver.delayMs(1000);
await driver.click(653, 264);
await driver.click(49, 570);
await driver.delayMs(2000);
let finishText = await getResourceString($r('app.string.finish'));
await driver.assertComponentExist(ON.text(finishText));
let finish = await driver.findComponent(ON.text(finishText));
await finish.click();
await driver.delayMs(1500);
await driver.click(357, 292);
await driver.delayMs(200);
await driver.click(355, 576);
await driver.delayMs(200);
await driver.click(491, 576);
await driver.delayMs(1000);
await driver.assertComponentExist(ON.id('back2Index'));
let back2Index = await driver.findComponent(ON.id('back2Index'));
await back2Index.click();
await driver.delayMs(200);
done();
hilog.info(DOMAIN, TAG, BUNDLE + 'SelectVideoFunction_001 end');
})
})
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 UIAbility from '@ohos.app.ability.UIAbility';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import hilog from '@ohos.hilog';
import { Hypium } from '@ohos/hypium';
import testsuite from '../test/List.test';
import window from '@ohos.window';
export default class TestAbility extends UIAbility {
onCreate(want, launchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
let abilityDelegator: any;
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
let abilityDelegatorArguments: any;
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments();
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
}
onDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
windowStage.loadContent('testability/pages/Index', (err, data) => {
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. Data: %{public}s',
JSON.stringify(data) ?? '');
});
}
onWindowStageDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
}
onForeground(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
}
onBackground(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.hilog';
@Entry
@Component
struct Index {
aboutToAppear() {
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear');
}
@State message: string = 'Hello World';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text('next page')
.fontSize(20)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('35%')
.height('5%')
.onClick(() => {
})
}
.width('100%')
}
.height('100%')
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"default"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:test_pages",
"abilities": [
{
"name": "TestAbility",
"srcEntry": "./ets/testability/TestAbility.ets",
"description": "$string:TestAbility_desc",
"icon": "$media:icon",
"label": "$string:TestAbility_label",
"exported": true,
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"actions": [
"action.system.home"
],
"entities": [
"entity.system.home"
]
}
]
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
},
{
"name": "permit",
"value": "permit"
},
{
"name": "new_dir",
"value": "New Dir"
},
{
"name": "label_confirm",
"value": "Label Confirm"
},
{
"name": "finish",
"value": "Finish"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
},
{
"name": "permit",
"value": "permit"
},
{
"name": "new_dir",
"value": "New Dir"
},
{
"name": "label_confirm",
"value": "Label Confirm"
},
{
"name": "finish",
"value": "Finish"
}
]
}

View File

@ -0,0 +1,32 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
},
{
"name": "permit",
"value": "允许"
},
{
"name": "new_dir",
"value": "新建文件夹"
},
{
"name": "label_confirm",
"value": "确定"
},
{
"name": "finish",
"value": "完成"
}
]
}

View File

@ -0,0 +1,6 @@
{
"hvigorVersion": "2.3.0",
"dependencies": {
"@ohos/hvigor-ohos-plugin": "2.3.0"
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
export { appTasks } from '@ohos/hvigor-ohos-plugin';

View File

@ -0,0 +1,61 @@
#!/bin/bash
# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.
# ----------------------------------------------------------------------------
# Hvigor startup script, version 1.0.0
#
# Required ENV vars:
# ------------------
# NODE_HOME - location of a Node home dir
# or
# Add /usr/local/nodejs/bin to the PATH environment variable
# ----------------------------------------------------------------------------
HVIGOR_APP_HOME=$(dirname $(readlink -f $0))
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
warn() {
echo ""
echo -e "\033[1;33m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
}
error() {
echo ""
echo -e "\033[1;31m`date '+[%Y-%m-%d %H:%M:%S]'`$@\033[0m"
}
fail() {
error "$@"
exit 1
}
# Determine node to start hvigor wrapper script
if [ -n "${NODE_HOME}" ];then
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
if [ ! -x "$EXECUTABLE_NODE" ];then
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
fi
else
EXECUTABLE_NODE="node"
which ${EXECUTABLE_NODE} > /dev/null 2>&1 || fail "ERROR: NODE_HOME is not set and not 'node' command found in your path"
fi
# Check hvigor wrapper script
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ];then
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
fi
# start hvigor-wrapper script
exec "${EXECUTABLE_NODE}" \
"${HVIGOR_WRAPPER_SCRIPT}" "$@"

View File

@ -0,0 +1,72 @@
:: Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.
@echo off
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Hvigor startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
set NODE_EXE=node.exe
goto start
:start
@rem Find node.exe
if defined NODE_HOME goto findNodeFromNodeHome
%NODE_EXE% --version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
echo.
echo Please set the NODE_HOME variable in your environment to match the
echo location of your NodeJs installation.
goto fail
:findNodeFromNodeHome
set NODE_HOME=%NODE_HOME:"=%
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
if exist "%NODE_EXE_PATH%" goto execute
echo.
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
echo.
echo Please set the NODE_HOME variable in your environment to match the
echo location of your NodeJs installation.
goto fail
:execute
@rem Execute hvigor
"%NODE_EXE%" %WRAPPER_MODULE_PATH% %*
:fail
exit /b 1

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.
*/
{
"license": "",
"devDependencies": {
"@ohos/hypium": "1.0.6"
},
"author": "",
"name": "mediafileuridemo",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {}
}

View File

@ -0,0 +1,13 @@
# Picker 测试用例归档
## 用例表
|测试功能|预置条件|输入|预期输出|是否自动|测试结果|
|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|
|拉起应用| 设备正常运行| |成功拉起应用|是|Pass|
|申请权限| 成功拉起应用 | | 弹出提示框 |是|Pass|
|增加文件、文件夹| 进入首页 | 点击新增文件文件夹图标Picker拉起文档 | 成功在系统中新增文件夹,并在新增文件夹中新增文件,完成之后返回首页 | 是 |Pass|
|编辑新增文件| 进入首页 | 点击List中新增的文件 | 成功编辑文件内容并保存,然后返回首页 |是|Pass|
|另存为| 进入首页 | 点击List中新增的文件进入编辑页面 | 点击另存为拉起picker文件另存在新增文件夹中 |是|Pass|
|picker拉起图片查看| 进入首页,系统相册中预制至少三张图片 | 点击picker图标并选择系统相册中的图片 | 选择完成之后成功显示图片,点击图片显示其详细信息 |是|Pass|
|picker拉起视频并播放| 进入首页,系统相册中预制至少两个视频 | 点击picker图标并选择系统相册中的视频并点击播放 | 选择完成之后成功显示视频,点击播放之后开始播放,点击视频显示其详细信息 |是|Pass|

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -0,0 +1,11 @@
/node_modules
/oh_modules
/local.properties
/.idea
**/build
/.hvigor
.cxx
/.clangd
/.clang-format
/.clang-tidy
**/.test

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.sandbox_share",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name"
}
}

View File

@ -0,0 +1,8 @@
{
"string": [
{
"name": "app_name",
"value": "SandboxShare"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,81 @@
# 为应用之间分享和文件访问提供统一的入口能力
### 介绍
本示例主要展示了沙箱文件分享相关的功能,使用 [@ohos.file.fileuri](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fileuri.md) 、[@ohos.file.fs](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fs.md)、[@ohos.ability.wantConstant](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-wantConstant.md)、[@ohos.application.Want](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-app-ability-want.md) 等接口实现了获取文件uri、创建沙箱文件、提供want中操作want常数和解释Flags说、应用组件间的信息传递的功能。
### 效果预览
|首页|分享界面| 分享至picker后的编辑界面 |
|--------------------------------|--------------------------------|--------------------------------|
|![](./screenshots/device/index.jpg)|![](./screenshots/device/share.jpg)|![](./screenshots/device/edit.jpg)|
使用说明:
1. 因本应用的功能依赖Picker应用在使用本应用之前首先应安装[Picker](code/BasicFeature/FileManagement/FileShare/Picker)应用;
2. 在主界面,可以点击沙箱文件夹列出文件夹中的文件,同时也可以直接点击沙箱目录下的文件进入文件分享界面;
3. 点击沙箱文件进入文件分享界面点击分享图标文件将以picker方式打开文件点击编辑图标文件进入可编辑模式在textArea中输入内容然后点击保存文件内容更新返回沙箱应用首页文件修改成功。
### 工程目录
```
entry/src/main/ets/
|---Application
|---Common
| |---Common.ts // 公共方法
| |---Utils.ts
| |---Logger.ts // 日志工具
|---MainAbility
| |---EntryAbility.ts // Ability类
|---fileFs
| |---fileFs.ts // 创建沙箱文件
|---pages
| |---Index.ets // 首页
| |---Show.ets // 文件分享页面
```
### 具体实现
* 增添文件、查找指定类型文件、获取文件uri、传递want信息启动ability的功能接口封装在fileFs.ts源码参考[fileFs.ts](src/main/ets/fileFs/fileFs.ts)
* 使用fs.mkdirSync、fs.openSync、fs.writeSync、fs.readSync、fs.closeSync分别用来来创建文件夹、打开文件、写文件、读文件、关闭文件接口参考[@ohos.file.fs](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fs.md)
* 使用fileUri.getUriFromPath来获取文件uri接口参考[@ohos.file.fileuri](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-file-fileuri.md)
* 分享文件至picker应用打开并编辑在分享页面[show.ets](src/main/ets/pages/Show.ets)
调用 implicitStartAbility 方法传递want参数启动新的ability接口参考[@ohos.ability.wantConstant](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-ability-wantConstant.md)、[@ohos.application.Want](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-app-ability-want.md)
### 相关权限
| 权限名 | 权限说明 | 级别 |
| ------------------------------------------ | ---------------------------------------- | ------------ |
| ohos.permission.GET_BUNDLE_INFO_PRIVILEGED | 允许查询应用的基本信息和其他敏感信息。 | system_basic |
| ohos.permission.MEDIA_LOCATION | 允许应用访问用户媒体文件中的地理位置信息 | normal |
| ohos.permission.READ_MEDIA | 允许应用读取用户外部存储中的媒体文件信息 | normal |
| ohos.permission.WRITE_MEDIA | 允许应用读写用户外部存储中的媒体文件信息 | normal |
### 依赖
本应用需要依赖[Picker](code/BasicFeature/FileManagement/FileShare/Picker)应用沙箱文件需分享至Picker应用打开并编辑保存
### 约束与限制
1.本示例仅支持标准系统上运行支持设备RK3568;
2.本示例为Stage模型仅支持API9版本SDK版本号3.2.12.2镜像版本号OpenHarmony 4.0.9.1。
3.本示例需要使用DevEco Studio 3.1 Release (Build Version: 3.1.0.500, built on April 28, 2023)及以上版本才可编译运行。
4.本示例涉及部分接口需要配置系统应用签名,可以参考[特殊权限配置方法](https://docs.openharmony.cn/pages/v3.2/zh-cn/application-dev/security/hapsigntool-overview.md/) 把配置文件中的“apl”字段信息改为“system_basic”。
### 下载
如需单独下载本工程,执行如下命令:
```
git init
git config core.sparsecheckout true
echo code/BasicFeature/FileManagement/FileShare/SandboxShare > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master
```

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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": {
"signingConfigs": [
],
"compileSdkVersion": 9,
"compatibleSdkVersion": 9,
"products": [
{
"name": "default",
"signingConfig": "default"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

View File

@ -0,0 +1,6 @@
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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": {
},
"targets": [
{
"name": "default",
"runtimeOS": "OpenHarmony"
},
{
"name": "ohosTest",
}
]
}

View File

@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
export { hapTasks } from '@ohos/hvigor-ohos-plugin';

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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.
*/
{
"license": "",
"devDependencies": {},
"author": "",
"name": "entry",
"description": "Please describe the basic information.",
"main": "",
"version": "1.0.0",
"dependencies": {}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import type { Permissions } from '@ohos.abilityAccessCtrl';
import { describe, it, expect } from '@ohos/hypium';
import util from '@ohos.util';
import Logger from '../common/Logger';
const INDEX: number = 2; // 序号
const SLEEP_TIME: number = 10; // 睡眠时间
const RADIX: number = 16; // parInt第二个参数值
// ############################################# 应用授权 ##########################################################
/*
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
},
* */
export function reqPermissions(context): void {
let atManager = abilityAccessCtrl.createAtManager();
const permissions: Array<Permissions> = [
'ohos.permission.READ_MEDIA',
'ohos.permission.WRITE_MEDIA',
'ohos.permission.MEDIA_LOCATION',
'ohos.permission.DISTRIBUTED_DATASYNC'
];
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
console.info(`[requestPermissions] data: ${JSON.stringify(data)}`);
let grantStatus: Array<number> = data.authResults;
if (grantStatus[0] === 0 && grantStatus[1] === 0 && grantStatus[INDEX] === 0) {
// 授权成功
Logger.info('[requestPermissions] Success to start request permissions.');
} else {
// 授权失败
Logger.info('[requestPermissions] Do not have permissions.');
}
}).catch((err) => {
Logger.error(`[requestPermissions] Failed to start request permissions. Error: ${JSON.stringify(err)}`);
});
}
export function strToUtf8Bytes(content: string | number | boolean): Array<number> {
const code = encodeURIComponent(content);
let bytes = [];
for (let i = 0; i < code.length; i++) {
const char = code.charAt(i);
if (char === '%') {
const hex = code.charAt(i + 1) + code.charAt(i + INDEX);
const hexValue = parseInt(hex, RADIX);
bytes.push(hexValue);
i += INDEX;
} else {
bytes.push(char.charCodeAt(0));
}
}
return bytes;
}
export function strToArrayBuffer(text: string): ArrayBuffer {
const bytes = this.strToUtf8Bytes(text);
const buffer = new ArrayBuffer(bytes.length);
const bufView = new DataView(buffer);
for (let i = 0; i < bytes.length; i++) {
bufView.setUint8(i, bytes[i]);
}
return buffer;
}
export async function sleep(times: number): Promise<void> {
if (!times) {
times = SLEEP_TIME;
}
await new Promise((res) => setTimeout(res, times));
}
export function randomString(num: number, chars: string): string {
let len = num;
let maxPos = chars.length;
let pwd = '';
for (let i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
export function bufferToString(buffer: ArrayBuffer): string {
let textDecoder = new util.TextDecoder('utf-8', {
ignoreBOM: true
});
let resultPut = textDecoder.decodeWithStream(new Uint8Array(buffer), {
stream: true
});
return resultPut;
}
export function stringToBuffer(content: string): Uint8Array {
let textEncoder = new util.TextEncoder('utf-8');
let resultBuf = textEncoder.encodeInto(content);
return resultBuf;
}
export {
describe, it, expect, Logger
};

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.hilog';
/**
* Common log for all features.
*/
export class Logger {
private domain: number;
private prefix: string;
private format: string = '%{public}s, %{public}s';
constructor(prefix: string) {
this.prefix = prefix;
this.domain = 0xFF00;
}
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('[SandboxShare]');

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 router from '@ohos.router';
import hilog from '@ohos.hilog';
import prompt from '@ohos.prompt';
let log = '';
const TIMEOUT_MAX = 10;
export class DocFileInfo {
constructor(public filename: string, public size: number) {
this.filename = filename;
this.size = size;
}
}
export default class Utils {
/**
*
*/
clearLog(): void {
log = '';
}
/**
*
* @param message
*/
setLog(message: string): void {
if (log === null || log === undefined) {
log = message;
} else {
log += '\n' + message;
}
}
/**
*
* @returns
*/
getLog(): string {
return log;
}
/**
*
* @param str
*/
myLog(info: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, tag, hilog.LogLevel.INFO);
hilog.info(0x0000, tag, '%{public}s', info);
this.setLog('[info]' + info);
}
/**
*
* @param str
*/
myWarnLog(warn: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.WARN);
hilog.warn(0x0000, 'testTag', 'Failed Cause: %{public}s', warn);
this.setLog('[warn]' + warn);
}
/**
*
* @param str
*/
myErrLog(err: string, tag: string = 'testTag'): void {
hilog.isLoggable(0x0000, tag, hilog.LogLevel.ERROR);
hilog.error(0x0000, tag, 'Failed Cause: %{public}s', err);
this.setLog('[error]' + err);
}
/**
* Toast提示
* @param info
*/
showInfo(info: string): void {
prompt.showToast({
message: info,
duration: 2000
});
}
/**
*
* @param toAbility
* @param mParams
*/
myBack(toAbility: string = '', mParams: { [key: string]: string } = null): void {
let options = {
url: toAbility,
params: mParams
};
router.back(options);
}
/**
*
* @param toAbility
* @param mParams
*/
async goToPage(toAbility: string, mParams: { [key: string]: string }): Promise<void> {
let options = {
url: toAbility,
params: mParams
};
try {
await router.pushUrl(options);
} catch (err) {
hilog.error(0x0000, 'testTag', ` fail callback, code: ${err.code}, msg: ${err.msg}`);
}
}
/**
*
* @param times
*/
async sleep(times: number): Promise<void> {
if (!times) {
times = TIMEOUT_MAX;
}
await new Promise((res) => setTimeout(res, times));
};
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import type { Permissions } from '@ohos.abilityAccessCtrl';
let myContext = null;
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
let applicationContext = this.context.getApplicationContext();
let filesDir = applicationContext.filesDir;
myContext = this.context;
AppStorage.SetOrCreate('filesDir', filesDir);
this.getResourceStr();
try {
this.getPermission();
} catch (err) {
hilog.info(0x0000, 'testTag', '%{public}s', 'err is ' + err);
}
}
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, data) => {
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. Data: %{public}s', JSON.stringify(data) ?? '');
});
}
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');
}
getResourceStr(): void {
try {
myContext.resourceManager.getStringValue($r('app.string.fileContent1').id)
.then(value => {
AppStorage.SetOrCreate('fileContent1', value);
hilog.info(0x0000, 'testTag', '%{public}s', 'getStringValue value' + value);
})
.catch(error => {
hilog.error(0x0000, 'testTag', 'Failed to getStringValue. Cause: %{public}s', error ?? '');
});
myContext.resourceManager.getStringValue($r('app.string.fileContent2').id)
.then(value => {
AppStorage.SetOrCreate('fileContent2', value);
hilog.info(0x0000, 'testTag', '%{public}s', 'getStringValue value' + value);
})
.catch(error => {
hilog.error(0x0000, 'testTag', 'Failed to getStringValue. Cause: %{public}s', error ?? '');
});
myContext.resourceManager.getStringValue($r('app.string.fileContent3').id)
.then(value => {
AppStorage.SetOrCreate('fileContent3', value);
hilog.info(0x0000, 'testTag', '%{public}s', 'getStringValue value' + value);
})
.catch(error => {
hilog.error(0x0000, 'testTag', 'Failed to getStringValue. Cause: %{public}s', error ?? '');
});
myContext.resourceManager.getStringValue($r('app.string.fileContent4').id)
.then(value => {
AppStorage.SetOrCreate('fileContent4', value);
hilog.info(0x0000, 'testTag', '%{public}s', 'getStringValue value' + value);
})
.catch(error => {
hilog.error(0x0000, 'testTag', 'Failed to getStringValue. Cause: %{public}s', error ?? '');
});
myContext.resourceManager.getStringValue($r('app.string.subFilenames').id)
.then(value => {
AppStorage.SetOrCreate('subFilenames', value);
hilog.info(0x0000, 'testTag', '%{public}s', 'getStringValue value' + value);
})
.catch(error => {
hilog.error(0x0000, 'testTag', 'Failed to getStringValue. Cause: %{public}s', error ?? '');
});
} catch (error) {
hilog.error(0x0000, 'testTag', 'callback getStringValue failed. Cause: %{public}s', error.message ?? '');
}
}
getPermission(): void {
let array: Array<Permissions> = [
'ohos.permission.READ_MEDIA',
'ohos.permission.WRITE_MEDIA',
'ohos.permission.MEDIA_LOCATION',
'ohos.permission.GET_BUNDLE_INFO',
'ohos.permission.DISTRIBUTED_DATASYNC',
'ohos.permission.START_ABILITIES_FROM_BACKGROUND',
'ohos.permission.START_INVISIBLE_ABILITY',
'ohos.permission.GRANT_SENSITIVE_PERMISSIONS',
'ohos.permission.GET_DISTRIBUTED_ACCOUNTS',
'ohos.permission.MANAGE_LOCAL_ACCOUNTS'
];
let atManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
atManager.requestPermissionsFromUser(this.context, array).then(function (data) {
hilog.info(0x0000, 'testTag', '%{public}s', 'data type:' + typeof (data));
hilog.info(0x0000, 'testTag', '%{public}s', 'data:' + data);
hilog.info(0x0000, 'testTag', '%{public}s', 'data permissions:' + data.permissions);
hilog.info(0x0000, 'testTag', '%{public}s', 'data result:' + data.authResults);
}, (err) => {
hilog.error(0x0000, 'Failed to start ability', err.code);
});
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 { bufferToString, Logger } from '../common/Common';
import fs from '@ohos.file.fs';
import fileUri from '@ohos.file.fileuri';
import wantConstant from '@ohos.ability.wantConstant';
import type Want from '@ohos.application.Want';
let fileContent = '';
const BUFFER_SIZE = 4096; // 读写文件缓冲区大小
const FILE_NUM = 3; // 沙箱目录预制文件个数
const DIR_FILE_NUM = 10; // 沙箱目录文件夹中预制文件个数
const TAG: string = '[File].[SandboxShare]';
export default class FileFs {
public fileSize: number = 0;
private baseDir: string = '';
private dmClass: Object = null;
public log: string[] = [];
public fileInfo = {
path: [],
size: 0
};
constructor() {
let content1: string = AppStorage.Get('fileContent1');
let content2: string = AppStorage.Get('fileContent2');
let content3: string = AppStorage.Get('fileContent3');
let content4: string = AppStorage.Get('fileContent4');
fileContent = content1 + '\r\n\n' + content2 + '\r\n\n' + content3 + '\r\n\n' + content4;
}
readyFilesToTestDir(filesDir: string): void {
let content = fileContent;
this.baseDir = filesDir + '/TestDir';
try {
let flag = TAG;
if (!fs.accessSync(this.baseDir)) {
fs.mkdirSync(this.baseDir);
}
let dpath = this.baseDir;
Logger.info(TAG, 'readyFileToWatcher dpath = ' + dpath);
for (let i = 0; i < DIR_FILE_NUM; i++) {
let myFile = dpath + `/testFile_${i}.txt`;
Logger.info(TAG, 'readyFileToWatcher myFile = ' + myFile);
let file = fs.openSync(myFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
fs.writeSync(file.fd, content);
fs.closeSync(file);
}
Logger.info(TAG, 'readyFileToWatcher successful');
} catch (e) {
Logger.error(TAG, `readyFileToWatcher has failed for: {message: ${e.message}, code: ${e.code}}`);
}
}
readyFilesToCurDir(filesDir: string): void {
let content = fileContent;
this.baseDir = filesDir;
try {
let flag = TAG;
if (!fs.accessSync(this.baseDir)) {
fs.mkdirSync(this.baseDir);
}
let dpath = this.baseDir;
Logger.info(TAG, 'readyFileToWatcher dpath = ' + dpath);
for (let i = 0; i < FILE_NUM; i++) {
let myFile = dpath + `/myFile_${i}.txt`;
Logger.info(TAG, 'readyFileToWatcher myFile = ' + myFile);
let file = fs.openSync(myFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
fs.writeSync(file.fd, content);
fs.closeSync(file);
}
Logger.info(TAG, 'readyFileToWatcher successful');
} catch (e) {
Logger.error(TAG, `readyFileToWatcher has failed for: {message: ${e.message}, code: ${e.code}}`);
}
}
getFileContent(path: string): string {
let resultPut = '';
try {
Logger.info(TAG, 'modifyFileToWatcher getFileContent filePath = ' + path);
let file = fs.openSync(path, fs.OpenMode.READ_WRITE);
let buf = new ArrayBuffer(BUFFER_SIZE);
let num = fs.readSync(file.fd, buf);
Logger.info(TAG, 'modifyFileToWatcher getFileContent read num = ' + num);
resultPut = bufferToString(buf);
Logger.info(TAG, 'modifyFileToWatcher getFileContent read resultPut = ' + resultPut);
fs.closeSync(file);
return resultPut;
} catch (e) {
Logger.error(TAG, `modifyFileToWatcher getFileContent has failed for: {message: ${e.message}, code: ${e.code}}`);
return resultPut;
}
}
implicitStartAbility(context, fileName: string, fileSize: number, fileFd: number, filePath: string): void {
let buf = new ArrayBuffer(BUFFER_SIZE);
let num = fs.readSync(fileFd, buf);
Logger.info(TAG, 'modifyFileToWatcher getFileContent read num = ' + num);
let content = bufferToString(buf);
let myUri: string = fileUri.getUriFromPath(filePath);
Logger.info(TAG, 'implicitStartAbility myUri is: ' + myUri);
let mode = wantConstant.Flags.FLAG_AUTH_WRITE_URI_PERMISSION | wantConstant.Flags.FLAG_AUTH_READ_URI_PERMISSION;
let uris: string[] = [myUri];
let want: Want = {
action: 'ohos.want.action.sendData',
parameters: {
'keyFd': {
'type': 'txt',
'value': fileFd,
'name': fileName,
'size': fileSize,
'content': content
},
'stream': uris
},
flags: mode,
type: 'application/txt',
uri: myUri,
};
context.startAbility(want).then(() => {
Logger.info(TAG, 'startAbility success');
}).catch((err) => {
Logger.info(TAG, 'startAbility err:' + err);
});
}
}

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 fs from '@ohos.file.fs';
import router from '@ohos.router';
import fileUri from '@ohos.file.fileuri';
import Logger from '../common/Logger';
import fileFs from '../fileFs/fileFs';
const TAG = 'ShareIndex: ';
@Entry
@Component
struct Index {
fileFs: fileFs = new fileFs();
scroller: Scroller = new Scroller();
@State uri: string = '';
@State fileSizeList: Array<number> = [];
@State fileNameList: Array<string> = [];
@State fileUriList: Array<string> = [];
@State fileInfoList: Array<string> = [];
@State filePathDir: string = '';
@State dirFlag: boolean = false;
@StorageLink('filesDir') filesDir: string = '';
@State listPosition: number = 0; // 0 indicates scrolling to the top of the list, 1 indicates scrolling to the middle of the list, and 2 indicates scrolling to the bottom of the list.
aboutToAppear() {
this.fileFs.readyFilesToTestDir(this.filesDir);
this.fileFs.readyFilesToCurDir(this.filesDir);
}
onPageShow() {
if (this.filePathDir !== '') {
this.getFileList(this.filePathDir);
} else {
this.getFileList();
}
}
getFileList(filesDir: string = this.filesDir) {
let options = {
'recursion': false,
'listNum': 0,
'filter': {
'suffix': ['.txt'],
}
};
let filenames = fs.listFileSync(filesDir, options);
Logger.info(TAG, 'listFile succeed');
for (let i = 0; i < filenames.length; i++) {
Logger.info(TAG, 'filename: %s', filenames[i]);
let filename = filenames[i];
this.fileNameList[i] = filename;
let filePath = filesDir + '/' + filename;
this.filePathDir = filesDir;
if (filename.indexOf('.') != -1) {
let sta = fs.statSync(filePath);
this.fileSizeList[i] = sta.size;
this.fileInfoList[i] = JSON.stringify(sta.size) + 'B';
} else {
let subFilenames = fs.listFileSync(filePath, options);
let subFileStr = AppStorage.Get('subFilenames');
this.fileInfoList[i] = JSON.stringify(subFilenames.length) + subFileStr;
}
}
}
build() {
Flex() {
Scroll(this.scroller) {
Row() {
Column() {
Row() {
Column() {
Text($r('app.string.sandboxFile'))
.fontSize(30)
.fontFamily('HarmonyHeiTi-Bold')
.fontColor('#182431')
.textAlign(TextAlign.Start)
.lineHeight(41)
.fontWeight(700)
}
}
.padding({ left: '6.7%', right: '6.7%', top: '0.9%', bottom: '1%' })
.height('7.2%')
.width('100%')
.backgroundColor('#f1f3f5')
Flex({ direction: FlexDirection.Column }) {
// list
Column() {
List({ space: 12, initialIndex: 0 }) {
ForEach(this.fileNameList, (item, index) => {
ListItem() {
Row() {
Image($r('app.media.ic_docs'))
.width('5%')
.height(22)
.margin({ left: '3%', right: 0 })
Text('item' + item)
.fontSize(16)
.fontFamily('HarmonyHeiTi-Medium')
.fontColor('#182431')
.lineHeight(22)
.fontWeight(500)
.textAlign(TextAlign.Start)
.width('60%')
.margin({ left: 19, right: 0 })
Text(this.fileInfoList[index])
.fontSize(14)
.fontFamily('HarmonyHeiTi-Medium')
.lineHeight(19)
.fontColor('#182431')
.textAlign(TextAlign.End)
.opacity(0.6)
.width('22%')
.margin({ left: '12%', right: 0 })
}
.padding({right: '3%' })
.borderRadius(24)
.width('100%')
.height(64)
.backgroundColor('#FFFFFF')
}
.onClick(() => {
let filePath = this.filesDir + '/' + item;
let index = filePath.indexOf('.');
if (index <= 0) {
// 分享目录处理逻辑
Logger.info(TAG, 'getFileList Dir existed :' + filePath);
this.getFileList(filePath);
this.dirFlag = true;
} else {
let fileTestDirPath = this.filePathDir + '/' + item;
let content = '';
let myUri = '';
if (fs.accessSync(fileTestDirPath) && this.dirFlag) {
content = this.fileFs.getFileContent(fileTestDirPath);
myUri = fileUri.getUriFromPath(fileTestDirPath);
router.pushUrl({
url: 'pages/Show',
params: {
fileName: item,
fileContent: content,
path: fileTestDirPath
}
}, router.RouterMode.Standard);
} else {
content = this.fileFs.getFileContent(filePath);
myUri = fileUri.getUriFromPath(filePath);
router.pushUrl({
url: 'pages/Show',
params: {
fileName: item,
fileContent: content,
path: filePath
}
}, router.RouterMode.Standard);
}
}
})
}, item => item)
}
.margin({ top: '1%', left: 12, right: 12 })
.listDirection(Axis.Vertical) // 排列方向
.id('sandboxFileList')
.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果
.scrollBar(BarState.Auto)
.alignListItem(ListItemAlign.Center)
}
.height('100%')
.width('100%')
}
.height('90%')
.width('100%')
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Start)
}
.height('100%')
.backgroundColor('#f1f3f5')
}
}
.width("100%").height("100%")
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';
import fileFs from '../fileFs/fileFs';
import Logger from '../common/Logger';
const TAG = 'show';
@Entry
@Component
struct Show {
@State myContext: Context = getContext(this) as common.UIAbilityContext;
@State myFileName: string = router.getParams()['fileName'];
@StorageLink('myFileSize') myFileSize: number = 0;
@StorageLink('myFileContent') myFileContent: string = router.getParams()['fileContent'];
@State path: string = router.getParams()['path'];
@State opacityValue: number = 0.6;
@State fileFs: fileFs = new fileFs();
scroller: Scroller = new Scroller();
onPageShow() {
this.myFileContent = this.fileFs.getFileContent(this.path);
this.myFileSize = fs.statSync(this.path).size;
}
aboutToDisappear() {
}
onPageHide() {
}
build() {
Column() {
// 第一行
Row() {
// 后退箭头
Row() {
Image($r('app.media.ic_back'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.id('back')
.align(Alignment.Start)
.onClick(() => {
router.back();
})
}
.margin({ right: '5%' })
// 文件名及信息
Column() {
Row() { // 文件名
Text(this.myFileName)
.focusable(true)
.focusOnTouch(true)
.fontSize(20)
.fontFamily('HarmonyHeiTi-Bold')
.fontColor('#182431')
.textAlign(TextAlign.Start)
.fontWeight(700)
.lineHeight(28)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.align(Alignment.Start)
.margin({ top: '0.4%', bottom: '0.3%' })
.width('100%')
Row() { // 文件大小
Text('size: ' + JSON.stringify(this.myFileSize) + 'B')
.focusable(true)
.focusOnTouch(true)
.opacity(0.6)
.fontFamily('HarmonyHeiTi')
.fontSize(14)
.fontColor('#182431')
.textAlign(TextAlign.Start)
.lineHeight(19)
.fontWeight(400)
}
.margin({ top: '0.3%', bottom: '0.5%' })
.align(Alignment.Start)
.width('100%')
}
.width('45%')
// 右边两个图标
Row() {
Image($r('app.media.ic_refresh'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.margin({ right: '12%' })
.id('refresh')
.onClick(() => {
let sta = fs.statSync(this.path);
this.myFileSize = sta.size;
this.myFileContent = this.fileFs.getFileContent(this.path);
AppStorage.SetOrCreate('myFileSize', this.myFileSize);
AppStorage.SetOrCreate('myFileContent', this.myFileContent);
promptAction.showToast({ message: $r('app.string.refresh') });
})
Image($r('app.media.ic_share'))
.focusable(true)
.focusOnTouch(true)
.width(25)
.height(25)
.id('share')
.margin({ right: '5%' })
.onClick(() => {
let file = fs.openSync(this.path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let context = getContext(this);
Logger.info(TAG, "context this "+ context);
this.fileFs.implicitStartAbility(context, this.myFileName, this.myFileSize, file.fd, this.path);
})
}
.height('100%')
.width('50%')
.padding({ right: '6%' })
.justifyContent(FlexAlign.End)
}
.height('7.4%')
.width('100%')
Scroll(this.scroller) {
// TextArea的行容器
Row() {
TextArea({ text: this.myFileContent })
.id('textArea')
.fontSize(16)
.fontColor('#182431')
.opacity(this.opacityValue)
.fontWeight(400)
.align(Alignment.Center)
.textAlign(TextAlign.Start)
.backgroundColor('#f1f3f5')
.fontFamily('HarmonyHeiTi')
.focusable(false)
.focusOnTouch(true)
.defaultFocus(false)
.padding({
top: 8,
right: 0,
left: 0,
bottom: 8
}) // 默认为top: 8 vp, right: 16 vp, bottom: 8 vp, left: 16 vp需要更改
}
.padding({ top: 8 })
}
.margin({ top: 8 })
}
.backgroundColor('#f1f3f5')
.height('100%')
.width('100%')
.padding({ left: '6.7%', right: '6.7%' })
}
}

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ts",
"description": "$string:EntryAbility_desc",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
//申请权限
"requestPermissions":[
{
"name": "ohos.permission.MEDIA_LOCATION",
//"reason": "$string:read_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name" : "ohos.permission.READ_MEDIA",
//"reason": "$string:read_permission",
"usedScene": {
"abilities": [
"MainAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.WRITE_MEDIA",
//"reason": "$string:write_permission",
"usedScene": {
"abilities": [
"MainAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.GET_BUNDLE_INFO",
//"reason": "$string:get_bundle_info",
"usedScene": {
"abilities": [
"MainAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.WRITE_IMAGEVIDEO",
// "reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.READ_IMAGEVIDEO",
// "reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"always"
}
},
{
"name" : "ohos.permission.READ_AUDIO",
//"reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when":"always"
}
},
{
"name": "ohos.permission.WRITE_AUDIO",
//"reason": "$string:write_image_video_permission",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
}
]
}
}

View File

@ -0,0 +1,8 @@
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}

View File

@ -0,0 +1,44 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "SandboxShare"
},
{
"name": "refresh",
"value": "Refresh"
},
{
"name": "sandboxFile",
"value": "Sandbox File"
},
{
"name": "fileContent1",
"value": "File Content1"
},
{
"name": "fileContent2",
"value": "File Content2"
},
{
"name": "fileContent3",
"value": "File Content3"
},
{
"name": "fileContent4",
"value": "File Content4"
},
{
"name": "subFilenames",
"value": "SubFilenames"
}
]
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_PAUSE</title>
<defs>
<path d="M12,1 C18.0751322,1 23,5.92486775 23,12 C23,18.0751322 18.0751322,23 12,23 C5.92486775,23 1,18.0751322 1,12 C1,5.92486775 5.92486775,1 12,1 Z M12,2.5 C6.75329488,2.5 2.5,6.75329488 2.5,12 C2.5,17.2467051 6.75329488,21.5 12,21.5 C17.2467051,21.5 21.5,17.2467051 21.5,12 C21.5,6.75329488 17.2467051,2.5 12,2.5 Z M16.1490452,13.0797236 L10.8798388,16.1534274 C10.2835239,16.5012777 9.51812673,16.2998574 9.17027637,15.7035425 C9.0587605,15.5123725 9,15.295022 9,15.0737038 L9,8.92629625 C9,8.23594031 9.55964406,7.67629625 10.25,7.67629625 C10.4713183,7.67629625 10.6886687,7.73505675 10.8798388,7.84657262 L16.1490452,10.9202764 C16.7453601,11.2681267 16.9467804,12.0335239 16.5989301,12.6298388 C16.4902816,12.8160933 16.3352998,12.9710751 16.1490452,13.0797236 Z" id="path-1"></path>
</defs>
<g id="ic_PAUSE" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>ic_back</title>
<defs>
<path d="M5.56079777,13.7499686 L11.5303301,19.7196699 L11.5640714,19.7556673 C11.8227547,20.0502619 11.8115076,20.4991526 11.5303301,20.7803301 C11.2491526,21.0615076 10.8002619,21.0727547 10.5056673,20.8140714 L10.4696699,20.7803301 L3.43929777,13.7499686 L5.56079777,13.7499686 Z M10.4696699,3.21966991 C10.7625631,2.9267767 11.2374369,2.9267767 11.5303301,3.21966991 C11.8115076,3.5008474 11.8227547,3.94973814 11.5640714,4.24433269 L11.5303301,4.28033009 L4.5605,11.25 L21.25,11.25 C21.6494202,11.25 21.9759152,11.56223 21.9987268,11.9559318 L22,12 C22,12.3994202 21.68777,12.7259152 21.2940682,12.7487268 L21.25,12.75 L2.75,12.75 C2.09603793,12.75 1.76158663,11.9761547 2.19060357,11.5002723 L2.21966991,11.4696699 L10.4696699,3.21966991 Z" id="path-1"></path>
</defs>
<g id="ic_back" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="symbol/frame/symbol_grid24-copy" transform="translate(-0.017678, -0.017678)"></g>
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="形状结合" fill="#182431" fill-rule="nonzero" xlink:href="#path-1"></use>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

Some files were not shown because too many files have changed in this diff Show More