!4533 【Sample】新增MindSporeLite C Demo
Merge pull request !4533 from 钱丹/master
7
OAT.xml
@ -271,6 +271,13 @@ Note:If the text contains special characters, please escape them according to th
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/AppScope/resources/base/media/app_icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo/screenshots/MindSporeLiteArkTSDemo.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteArkTSDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/ohosTest/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/startIcon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/background.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/foreground.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/AppScope/resources/base/media/app_icon.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/MindSporeLiteCDemo/screenshots/MindSporeLiteCDemoPic.png" desc="Provided by code/DocsSample/ApplicationModels/MindSporeLiteCDemo"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/entry/src/main/resources/base/media/icon.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/ImplicitStartByTypeRely/screenshots/newability.png" desc="Provided by code/DocsSample/ApplicationModels/ImplicitStartByTypeRely"/>
|
||||
<filteritem type="filepath" name="code/DocsSample/ApplicationModels/StageModelAbilityInteraction/screenshot/coldstartuppage.png" desc="Provided by code/DocsSample/ApplicationModels/StageModelAbilityInteraction"/>
|
||||
|
12
code/DocsSample/ApplicationModels/MindSporeLiteCDemo/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
/.appanalyzer
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.samples.mindsporelitecdemo",
|
||||
"vendor": "samples",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "MindSporeLiteCDemo"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,85 @@
|
||||
# **基于**Native**接口的MindSpore Lite应用开发**
|
||||
|
||||
### 介绍
|
||||
|
||||
本文基于MindSpore Lite提供的[Native API](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-mindspore-lite-kit/_mind_spore.md),实现“图像分类”示例程序,来演示端侧部署的流程。
|
||||
|
||||
1. 选择图像分类模型。
|
||||
2. 将模型转换成MindSpore Lite模型格式。
|
||||
3. 使用MindSpore Lite推理模型,显示出可能的分类结果。
|
||||
|
||||
### 效果预览
|
||||
|
||||
| 主页 |
|
||||
| -------------------------------------------------- |
|
||||
| <img src="screenshots/MindSporeLiteCDemoPic.png"/> |
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. 在主界面,可以点击photo按钮,进入相册选择图片界面;
|
||||
2. 在相册界面,选择图片,点击确定按钮;
|
||||
3. 自动进行选择图片的图像分类模型推理,部分推理结果显示在主界面。
|
||||
|
||||
### 工程目录
|
||||
|
||||
```
|
||||
entry
|
||||
├── src/main
|
||||
│ ├── etc
|
||||
| | └── pages
|
||||
| | └── Index.ets // 首页,获取图片及预处理
|
||||
│ ├── cpp
|
||||
| | └── mslite_napi.cpp // 推理函数
|
||||
| | └── CMakeLists.txt // 编译脚本
|
||||
| | └── types
|
||||
| | └── libentry
|
||||
| | └── Index.t.ts // 将C++动态库封装成JS模块
|
||||
│ ├── resources // 资源文件
|
||||
| | └── rawfile
|
||||
| | └── mobilenetv2.ms // 存放的模型文件
|
||||
```
|
||||
|
||||
### 具体实现
|
||||
|
||||
* 本示例程序中使用的终端图像分类模型文件为mobilenetv2.ms,放置在entry\src\main\resources\rawfile工程目录下。
|
||||
|
||||
注:可手工下载模型文件[mobilenetv2.ms](https://download.mindspore.cn/model_zoo/official/lite/mobilenetv2_openimage_lite/1.5/mobilenetv2.ms)。
|
||||
|
||||
* 调用[@ohos.file.picker](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-picker.md) (图片文件选择)、[@ohos.multimedia.image](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-image-kit/js-apis-image.md) (图片处理效果)、[@ohos.file.fs](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md) (基础文件操作) 等API实现相册图片获取及图片处理。完整代码请参见Index.ets。
|
||||
|
||||
* 调用[MindSpore Lite Native API](https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/reference/apis-mindspore-lite-kit/_mind_spore.md)实现推理。完整代码请参见mslite_napi.cpp。
|
||||
|
||||
* 编写CMake脚本。链接MindSpore Lite动态库,完整代码请参见CMakeLists.txt。
|
||||
|
||||
* 使用N-API将C++动态库封装成JS模块。在 entry/src/main/cpp/types/libentry/index.d.ts,定义JS接口`runDemo()` 。
|
||||
|
||||
* 调用推理函数并处理结果。完整代码请参见Index.ets
|
||||
|
||||
### 相关权限
|
||||
|
||||
无。
|
||||
|
||||
### 依赖
|
||||
|
||||
无。
|
||||
|
||||
### 约束与限制
|
||||
|
||||
1.本示例仅支持标准系统上运行,测试设备:RK3568;
|
||||
|
||||
2.本示例为Stage模型,已适配API version 11版本SDK;
|
||||
|
||||
3.本示例需要使用DevEco Studio 4.1 Release及以上版本才可编译运行。
|
||||
|
||||
### 下载
|
||||
|
||||
如需单独下载本工程,执行如下命令:
|
||||
|
||||
```
|
||||
git init
|
||||
git config core.sparsecheckout true
|
||||
echo code/BasicFeature/ApplicationModels/MindSporeLiteCDemo/ > .git/info/sparse-checkout
|
||||
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
|
||||
git pull origin master
|
||||
```
|
||||
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"app": {
|
||||
"signingConfigs": [
|
||||
],
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compatibleSdkVersion": 11,
|
||||
"compileSdkVersion": 11,
|
||||
"runtimeOS": "OpenHarmony"
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug",
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
6
code/DocsSample/ApplicationModels/MindSporeLiteCDemo/entry/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"externalNativeOptions": {
|
||||
"path": "./src/main/cpp/CMakeLists.txt",
|
||||
"abiFilters": ['arm64-v8a', 'armeabi-v7a', 'x86_64'],
|
||||
"arguments": "",
|
||||
"cppFlags": "",
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": true,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nativeLib": {
|
||||
"debugSymbol": {
|
||||
"strip": true,
|
||||
"exclude": []
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
# Define project specific obfuscation rules here.
|
||||
# You can include the obfuscation configuration files in the current module's build-profile.json5.
|
||||
#
|
||||
# For more details, see
|
||||
# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
|
||||
|
||||
# Obfuscation options:
|
||||
# -disable-obfuscation: disable all obfuscations
|
||||
# -enable-property-obfuscation: obfuscate the property names
|
||||
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
|
||||
# -compact: remove unnecessary blank spaces and all line feeds
|
||||
# -remove-log: remove all console.* statements
|
||||
# -print-namecache: print the name cache that contains the mapping from the old names to new names
|
||||
# -apply-namecache: reuse the given cache file
|
||||
|
||||
# Keep options:
|
||||
# -keep-property-name: specifies property names that you want to keep
|
||||
# -keep-global-name: specifies names that you want to keep in the global scope
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "entry",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
"libentry.so": "file:./src/main/cpp/types/libentry"
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
# the minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(MindSporeLiteCDemo)
|
||||
|
||||
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(DEFINED PACKAGE_FIND_FILE)
|
||||
include(${PACKAGE_FIND_FILE})
|
||||
endif()
|
||||
|
||||
include_directories(${NATIVERENDER_ROOT_PATH}
|
||||
${NATIVERENDER_ROOT_PATH}/include)
|
||||
|
||||
add_library(entry SHARED mslite_napi.cpp)
|
||||
target_link_libraries(entry PUBLIC mindspore_lite_ndk)
|
||||
target_link_libraries(entry PUBLIC hilog_ndk.z)
|
||||
target_link_libraries(entry PUBLIC rawfile.z)
|
||||
target_link_libraries(entry PUBLIC ace_napi.z)
|
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "napi/native_api.h"
|
||||
#include <hilog/log.h>
|
||||
#include <rawfile/raw_file_manager.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <mindspore/types.h>
|
||||
#include <mindspore/model.h>
|
||||
#include <mindspore/context.h>
|
||||
#include <mindspore/status.h>
|
||||
#include <mindspore/tensor.h>
|
||||
#include <sstream>
|
||||
|
||||
#define LOGI(...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||
#define LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||
#define LOGW(...) ((void)OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||
#define LOGE(...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "[MSLiteNapi]", __VA_ARGS__))
|
||||
|
||||
constexpr int K_NUM_PRINT_OF_OUT_DATA = 20;
|
||||
|
||||
int FillInputTensor(OH_AI_TensorHandle input, std::vector<float> input_data)
|
||||
{
|
||||
if (OH_AI_TensorGetDataType(input) == OH_AI_DATATYPE_NUMBERTYPE_FLOAT32) {
|
||||
float *data = (float *)OH_AI_TensorGetMutableData(input);
|
||||
for (size_t i = 0; i < OH_AI_TensorGetElementNum(input); i++) {
|
||||
data[i] = input_data[i];
|
||||
}
|
||||
return OH_AI_STATUS_SUCCESS;
|
||||
} else {
|
||||
return OH_AI_STATUS_LITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void *ReadModelFile(NativeResourceManager *nativeResourceManager, const std::string &modelName, size_t *modelSize)
|
||||
{
|
||||
auto rawFile = OH_ResourceManager_OpenRawFile(nativeResourceManager, modelName.c_str());
|
||||
if (rawFile == nullptr) {
|
||||
LOGE("MS_LITE_ERR: Open model file failed");
|
||||
return nullptr;
|
||||
}
|
||||
long fileSize = OH_ResourceManager_GetRawFileSize(rawFile);
|
||||
if (fileSize <= 0) {
|
||||
LOGE("MS_LITE_ERR: FileSize not correct");
|
||||
}
|
||||
void *modelBuffer = malloc(fileSize);
|
||||
if (modelBuffer == nullptr) {
|
||||
LOGE("MS_LITE_ERR: OH_ResourceManager_ReadRawFile failed");
|
||||
}
|
||||
int ret = OH_ResourceManager_ReadRawFile(rawFile, modelBuffer, fileSize);
|
||||
if (ret == 0) {
|
||||
LOGI("MS_LITE_LOG: OH_ResourceManager_ReadRawFile failed");
|
||||
OH_ResourceManager_CloseRawFile(rawFile);
|
||||
return nullptr;
|
||||
}
|
||||
OH_ResourceManager_CloseRawFile(rawFile);
|
||||
*modelSize = fileSize;
|
||||
return modelBuffer;
|
||||
}
|
||||
|
||||
void DestroyModelBuffer(void **buffer)
|
||||
{
|
||||
if (buffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
free(*buffer);
|
||||
*buffer = nullptr;
|
||||
}
|
||||
|
||||
OH_AI_ModelHandle CreateMSLiteModel(void *modelBuffer, size_t modelSize)
|
||||
{
|
||||
// Set executing context for model.
|
||||
auto context = OH_AI_ContextCreate();
|
||||
if (context == nullptr) {
|
||||
DestroyModelBuffer(&modelBuffer);
|
||||
LOGE("MS_LITE_ERR: Create MSLite context failed.\n");
|
||||
return nullptr;
|
||||
}
|
||||
auto cpu_device_info = OH_AI_DeviceInfoCreate(OH_AI_DEVICETYPE_CPU);
|
||||
OH_AI_DeviceInfoSetEnableFP16(cpu_device_info, true);
|
||||
OH_AI_ContextAddDeviceInfo(context, cpu_device_info);
|
||||
|
||||
// Create model
|
||||
auto model = OH_AI_ModelCreate();
|
||||
if (model == nullptr) {
|
||||
DestroyModelBuffer(&modelBuffer);
|
||||
LOGE("MS_LITE_ERR: Allocate MSLite Model failed.\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Build model object
|
||||
auto build_ret = OH_AI_ModelBuild(model, modelBuffer, modelSize, OH_AI_MODELTYPE_MINDIR, context);
|
||||
DestroyModelBuffer(&modelBuffer);
|
||||
if (build_ret != OH_AI_STATUS_SUCCESS) {
|
||||
OH_AI_ModelDestroy(&model);
|
||||
LOGE("MS_LITE_ERR: Build MSLite model failed.\n");
|
||||
return nullptr;
|
||||
}
|
||||
LOGI("MS_LITE_LOG: Build MSLite model success.\n");
|
||||
return model;
|
||||
}
|
||||
|
||||
int RunMSLiteModel(OH_AI_ModelHandle model, std::vector<float> input_data)
|
||||
{
|
||||
// Set input data for model.
|
||||
auto inputs = OH_AI_ModelGetInputs(model);
|
||||
auto ret = FillInputTensor(inputs.handle_list[0], input_data);
|
||||
if (ret != OH_AI_STATUS_SUCCESS) {
|
||||
LOGE("MS_LITE_ERR: RunMSLiteModel set input error.\n");
|
||||
return OH_AI_STATUS_LITE_ERROR;
|
||||
}
|
||||
|
||||
// Get model output.
|
||||
auto outputs = OH_AI_ModelGetOutputs(model);
|
||||
|
||||
// Predict model.
|
||||
auto predict_ret = OH_AI_ModelPredict(model, inputs, &outputs, nullptr, nullptr);
|
||||
if (predict_ret != OH_AI_STATUS_SUCCESS) {
|
||||
OH_AI_ModelDestroy(&model);
|
||||
LOGE("MS_LITE_ERR: MSLite Predict error.\n");
|
||||
return OH_AI_STATUS_LITE_ERROR;
|
||||
}
|
||||
LOGI("MS_LITE_LOG: Run MSLite model Predict success.\n");
|
||||
|
||||
// Print output tensor data.
|
||||
LOGI("MS_LITE_LOG: Get model outputs:\n");
|
||||
for (size_t i = 0; i < outputs.handle_num; i++) {
|
||||
auto tensor = outputs.handle_list[i];
|
||||
LOGI("MS_LITE_LOG: - Tensor %{public}d name is: %{public}s.\n", static_cast<int>(i),
|
||||
OH_AI_TensorGetName(tensor));
|
||||
LOGI("MS_LITE_LOG: - Tensor %{public}d size is: %{public}d.\n", static_cast<int>(i),
|
||||
(int)OH_AI_TensorGetDataSize(tensor));
|
||||
LOGI("MS_LITE_LOG: - Tensor data is:\n");
|
||||
auto out_data = reinterpret_cast<const float *>(OH_AI_TensorGetData(tensor));
|
||||
std::stringstream outStr;
|
||||
for (int i = 0; (i < OH_AI_TensorGetElementNum(tensor)) && (i <= K_NUM_PRINT_OF_OUT_DATA); i++) {
|
||||
outStr << out_data[i] << " ";
|
||||
}
|
||||
LOGI("MS_LITE_LOG: %{public}s", outStr.str().c_str());
|
||||
}
|
||||
return OH_AI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static napi_value RunDemo(napi_env env, napi_callback_info info)
|
||||
{
|
||||
// run demo
|
||||
napi_value error_ret;
|
||||
napi_create_int32(env, -1, &error_ret);
|
||||
// 传入数据处理
|
||||
size_t argc = 2;
|
||||
napi_value argv[2] = {nullptr};
|
||||
napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
|
||||
bool isArray = false;
|
||||
napi_is_array(env, argv[0], &isArray);
|
||||
uint32_t length = 0;
|
||||
// 获取数组的长度
|
||||
napi_get_array_length(env, argv[0], &length);
|
||||
std::vector<float> input_data;
|
||||
double param = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
napi_value value;
|
||||
napi_get_element(env, argv[0], i, &value);
|
||||
napi_get_value_double(env, value, ¶m);
|
||||
input_data.push_back(static_cast<float>(param));
|
||||
}
|
||||
std::stringstream outstr;
|
||||
for (int i = 0; i < K_NUM_PRINT_OF_OUT_DATA; i++) {
|
||||
outstr << input_data[i] << " ";
|
||||
}
|
||||
// Read model file
|
||||
const std::string modelName = "mobilenetv2.ms";
|
||||
size_t modelSize;
|
||||
auto resourcesManager = OH_ResourceManager_InitNativeResourceManager(env, argv[1]);
|
||||
auto modelBuffer = ReadModelFile(resourcesManager, modelName, &modelSize);
|
||||
if (modelBuffer == nullptr) {
|
||||
return error_ret;
|
||||
}
|
||||
auto model = CreateMSLiteModel(modelBuffer, modelSize);
|
||||
int ret = RunMSLiteModel(model, input_data);
|
||||
if (ret != OH_AI_STATUS_SUCCESS) {
|
||||
OH_AI_ModelDestroy(&model);
|
||||
return error_ret;
|
||||
}
|
||||
napi_value out_data;
|
||||
napi_create_array(env, &out_data);
|
||||
auto outputs = OH_AI_ModelGetOutputs(model);
|
||||
OH_AI_TensorHandle output_0 = outputs.handle_list[0];
|
||||
float *output0Data = reinterpret_cast<float *>(OH_AI_TensorGetMutableData(output_0));
|
||||
for (size_t i = 0; i < OH_AI_TensorGetElementNum(output_0); i++) {
|
||||
napi_value element;
|
||||
napi_create_double(env, static_cast<double>(output0Data[i]), &element);
|
||||
napi_set_element(env, out_data, i, element);
|
||||
}
|
||||
OH_AI_ModelDestroy(&model);
|
||||
return out_data;
|
||||
}
|
||||
|
||||
EXTERN_C_START
|
||||
static napi_value Init(napi_env env, napi_value exports)
|
||||
{
|
||||
napi_property_descriptor desc[] = {{"runDemo", nullptr, RunDemo, nullptr, nullptr, nullptr, napi_default, nullptr}};
|
||||
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
|
||||
return exports;
|
||||
}
|
||||
EXTERN_C_END
|
||||
|
||||
static napi_module demoModule = {
|
||||
.nm_version = 1,
|
||||
.nm_flags = 0,
|
||||
.nm_filename = nullptr,
|
||||
.nm_register_func = Init,
|
||||
.nm_modname = "entry",
|
||||
.nm_priv = ((void *)0),
|
||||
.reserved = {0},
|
||||
};
|
||||
|
||||
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export const runDemo: (a: number[], b:Object) => Array<number>;
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "libentry.so",
|
||||
"types": "./index.d.ts",
|
||||
"version": "",
|
||||
"description": "MindSpore Lite inference module"
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
// Main window is created, set main page for this ability
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||
|
||||
windowStage.loadContent('pages/Index', (err) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
// Main window is destroyed, release UI related resources
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
// Ability has brought to foreground
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
// Ability has back to background
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
|
||||
}
|
||||
};
|
@ -0,0 +1,264 @@
|
||||
import resourceManager from '@ohos.resourceManager'
|
||||
import fileIo from '@ohos.file.fs';
|
||||
import msliteNapi from 'libentry.so'
|
||||
import picker from '@ohos.file.picker';
|
||||
import { BusinessError } from '@ohos.base';
|
||||
import image from '@ohos.multimedia.image';
|
||||
|
||||
const TAG = 'MindSporeLite';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'MindSporeLite C Demo';
|
||||
@State modelName: string = 'mobilenetv2.ms';
|
||||
@State modelInputHeight: number = 224;
|
||||
@State modelInputWidth: number = 224;
|
||||
@State uris: Array<string> = [];
|
||||
@State max: number = 0;
|
||||
@State maxIndex: number = 0;
|
||||
@State maxArray: Array<number> = [];
|
||||
@State maxIndexArray: Array<number> = [];
|
||||
@State labelsNameMap: string[] = [
|
||||
'Herd', 'Safari', 'Bangle', 'Cushion', 'Countertop',
|
||||
'Prom', 'Branch', 'Sports', 'Sky', 'Community',
|
||||
'Wheel', 'Cola', 'Tuxedo', 'Flowerpot', 'Team',
|
||||
'Computer', 'Unicycle', 'Brig', 'Aerospace engineering', 'Scuba diving',
|
||||
'Goggles', 'Fruit', 'Badminton', 'Horse', 'Sunglasses',
|
||||
'Fun', 'Prairie', 'Poster', 'Flag', 'Speedboat',
|
||||
'Eyelash', 'Veil', 'Mobile phone', 'Wheelbarrow', 'Saucer',
|
||||
'Leather', 'Drawer', 'Paper', 'Pier', 'Waterfowl',
|
||||
'Tights', 'Rickshaw', 'Vegetable', 'Handrail', 'Ice',
|
||||
'Metal', 'Flower', 'Wing', 'Silverware', 'Event',
|
||||
'Skyline', 'Money', 'Comics', 'Handbag', 'Porcelain',
|
||||
'Rodeo', 'Curtain', 'Tile', 'Human mouth', 'Army',
|
||||
'Menu', 'Boat', 'Snowboarding', 'Cairn terrier', 'Net',
|
||||
'Pasteles', 'Cup', 'Rugby', 'Pho', 'Cap',
|
||||
'Human hair', 'Surfing', 'Loveseat', 'Museum', 'Shipwreck',
|
||||
'Trunk (Tree)', 'Plush', 'Monochrome', 'Volcano', 'Rock',
|
||||
'Pillow', 'Presentation', 'Nebula', 'Subwoofer', 'Lake',
|
||||
'Sledding', 'Bangs', 'Tablecloth', 'Necklace', 'Swimwear',
|
||||
'Standing', 'Jeans', 'Carnival', 'Softball', 'Centrepiece',
|
||||
'Skateboarder', 'Cake', 'Dragon', 'Aurora', 'Skiing',
|
||||
'Bathroom', 'Dog', 'Needlework', 'Umbrella', 'Church',
|
||||
'Fire', 'Piano', 'Denim', 'Bridle', 'Cabinetry',
|
||||
'Lipstick', 'Ring', 'Television', 'Roller', 'Seal',
|
||||
'Concert', 'Product', 'News', 'Fast food', 'Horn (Animal)',
|
||||
'Tattoo', 'Bird', 'Bridegroom', 'Love', 'Helmet',
|
||||
'Dinosaur', 'Icing', 'Miniature', 'Tire', 'Toy',
|
||||
'Icicle', 'Jacket', 'Coffee', 'Mosque', 'Rowing',
|
||||
'Wetsuit', 'Camping', 'Underwater', 'Christmas', 'Gelato',
|
||||
'Whiteboard', 'Field', 'Ragdoll', 'Construction', 'Lampshade',
|
||||
'Palace', 'Meal', 'Factory', 'Cage', 'Clipper (Boat)',
|
||||
'Gymnastics', 'Turtle', 'Human foot', 'Marriage', 'Web page',
|
||||
'Human beard', 'Fog', 'Wool', 'Cappuccino', 'Lighthouse',
|
||||
'Lego', 'Sparkler', 'Sari', 'Model', 'Temple',
|
||||
'Beanie', 'Building', 'Waterfall', 'Penguin', 'Cave',
|
||||
'Stadium', 'Smile', 'Human hand', 'Park', 'Desk',
|
||||
'Shetland sheepdog', 'Bar', 'Eating', 'Neon', 'Dalmatian',
|
||||
'Crocodile', 'Wakeboarding', 'Longboard', 'Road', 'Race',
|
||||
'Kitchen', 'Odometer', 'Cliff', 'Fiction', 'School',
|
||||
'Interaction', 'Bullfighting', 'Boxer', 'Gown', 'Aquarium',
|
||||
'Superhero', 'Pie', 'Asphalt', 'Surfboard', 'Cheeseburger',
|
||||
'Screenshot', 'Supper', 'Laugh', 'Lunch', 'Party ',
|
||||
'Glacier', 'Bench', 'Grandparent', 'Sink', 'Pomacentridae',
|
||||
'Blazer', 'Brick', 'Space', 'Backpacking', 'Stuffed toy',
|
||||
'Sushi', 'Glitter', 'Bonfire', 'Castle', 'Marathon',
|
||||
'Pizza', 'Beach', 'Human ear', 'Racing', 'Sitting',
|
||||
'Iceberg', 'Shelf', 'Vehicle', 'Pop music', 'Playground',
|
||||
'Clown', 'Car', 'Rein', 'Fur', 'Musician',
|
||||
'Casino', 'Baby', 'Alcohol', 'Strap', 'Reef',
|
||||
'Balloon', 'Outerwear', 'Cathedral', 'Competition', 'Joker',
|
||||
'Blackboard', 'Bunk bed', 'Bear', 'Moon', 'Archery',
|
||||
'Polo', 'River', 'Fishing', 'Ferris wheel', 'Mortarboard',
|
||||
'Bracelet', 'Flesh', 'Statue', 'Farm', 'Desert',
|
||||
'Chain', 'Aircraft', 'Textile', 'Hot dog', 'Knitting',
|
||||
'Singer', 'Juice', 'Circus', 'Chair', 'Musical instrument',
|
||||
'Room', 'Crochet', 'Sailboat', 'Newspaper', 'Santa claus',
|
||||
'Swamp', 'Skyscraper', 'Skin', 'Rocket', 'Aviation',
|
||||
'Airliner', 'Garden', 'Ruins', 'Storm', 'Glasses',
|
||||
'Balance', 'Nail (Body part)', 'Rainbow', 'Soil ', 'Vacation ',
|
||||
'Moustache', 'Doily', 'Food', 'Bride ', 'Cattle',
|
||||
'Pocket', 'Infrastructure', 'Train', 'Gerbil', 'Fireworks',
|
||||
'Pet', 'Dam', 'Crew', 'Couch', 'Bathing',
|
||||
'Quilting', 'Motorcycle', 'Butterfly', 'Sled', 'Watercolor paint',
|
||||
'Rafting', 'Monument', 'Lightning', 'Sunset', 'Bumper',
|
||||
'Shoe', 'Waterskiing', 'Sneakers', 'Tower', 'Insect',
|
||||
'Pool', 'Placemat', 'Airplane', 'Plant', 'Jungle',
|
||||
'Armrest', 'Duck', 'Dress', 'Tableware', 'Petal',
|
||||
'Bus', 'Hanukkah', 'Forest', 'Hat', 'Barn',
|
||||
'Tubing', 'Snorkeling', 'Cool', 'Cookware and bakeware', 'Cycling',
|
||||
'Swing (Seat)', 'Muscle', 'Cat', 'Skateboard', 'Star',
|
||||
'Toe', 'Junk', 'Bicycle', 'Bedroom', 'Person',
|
||||
'Sand', 'Canyon', 'Tie', 'Twig', 'Sphynx',
|
||||
'Supervillain', 'Nightclub', 'Ranch', 'Pattern', 'Shorts',
|
||||
'Himalayan', 'Wall', 'Leggings', 'Windsurfing', 'Deejay',
|
||||
'Dance', 'Van', 'Bento', 'Sleep', 'Wine',
|
||||
'Picnic', 'Leisure', 'Dune', 'Crowd', 'Kayak',
|
||||
'Ballroom', 'Selfie', 'Graduation', 'Frigate', 'Mountain',
|
||||
'Dude', 'Windshield', 'Skiff', 'Class', 'Scarf',
|
||||
'Bull', 'Soccer', 'Bag', 'Basset hound', 'Tractor',
|
||||
'Swimming', 'Running', 'Track', 'Helicopter', 'Pitch',
|
||||
'Clock', 'Song', 'Jersey', 'Stairs', 'Flap',
|
||||
'Jewellery', 'Bridge', 'Cuisine', 'Bread', 'Caving',
|
||||
'Shell', 'Wreath', 'Roof', 'Cookie', 'Canoe'
|
||||
];
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(30)
|
||||
.fontWeight(FontWeight.Bold);
|
||||
//图片显示
|
||||
Image(this.uris[0]).width(320).height(540).margin(15)
|
||||
//显示分类最大值
|
||||
if (this.max) {
|
||||
Text(this.labelsNameMap[this.maxIndexArray[0]] +
|
||||
': ' +
|
||||
(this.maxArray[0] / 100).toString() +
|
||||
'%\n' +
|
||||
this.labelsNameMap[this.maxIndexArray[1]] +
|
||||
': ' +
|
||||
(this.maxArray[1] / 100).toString() +
|
||||
'%\n' +
|
||||
this.labelsNameMap[this.maxIndexArray[2]] +
|
||||
': ' +
|
||||
(this.maxArray[2] / 100).toString() +
|
||||
'%\n' +
|
||||
this.labelsNameMap[this.maxIndexArray[3]] +
|
||||
': ' +
|
||||
(this.maxArray[3] / 100).toString() +
|
||||
'%').focusable(true).fontSize(20)
|
||||
}
|
||||
Button() {
|
||||
Text('photo')
|
||||
.fontSize(30)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.type(ButtonType.Capsule)
|
||||
.margin({
|
||||
top: 20
|
||||
})
|
||||
.backgroundColor('#0D9FFB')
|
||||
.width('40%')
|
||||
.height('5%')
|
||||
.onClick(() => {
|
||||
let resMgr: resourceManager.ResourceManager = getContext().getApplicationContext().resourceManager;
|
||||
|
||||
//获取相册图片
|
||||
//1.创建图片-视频类型文件选择选项实例
|
||||
let PhotoSelectOptions = new picker.PhotoSelectOptions();
|
||||
|
||||
//2.选择媒体文件类型和选择媒体文件的最大数目
|
||||
PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
|
||||
PhotoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目
|
||||
|
||||
//3.创建图库选择器实例,调用select()接口拉起图库界面进行文件选择。文件选择成功后,返回 photoSelectResult 结果集。
|
||||
let photoPicker = new picker.PhotoViewPicker();
|
||||
photoPicker.select(PhotoSelectOptions,
|
||||
async (err: BusinessError, photoSelectResult: picker.PhotoSelectResult) => {
|
||||
if (err) {
|
||||
console.error('MS_LITE_ERR: PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
|
||||
return;
|
||||
}
|
||||
console.info('MS_LITE_LOG: PhotoViewPicker.select successfully, photoSelectResult uri: ' +
|
||||
JSON.stringify(photoSelectResult));
|
||||
this.uris = photoSelectResult.photoUris;
|
||||
console.info('MS_LITE_LOG: uri: ' + this.uris);
|
||||
try {
|
||||
// 预处理图片数据
|
||||
// 1.使用fs.openSync接口,通过uri打开这个文件得到fd
|
||||
let file = fileIo.openSync(this.uris[0], fileIo.OpenMode.READ_ONLY);
|
||||
console.info('MS_LITE_LOG: file fd: ' + file.fd);
|
||||
|
||||
// 2.通过fd使用fs.readSync接口读取这个文件内的数据
|
||||
let inputBuffer = new ArrayBuffer(4096000);
|
||||
let readLen = fileIo.readSync(file.fd, inputBuffer);
|
||||
console.info('MS_LITE_LOG: readSync data to file succeed and inputBuffer size is:' + readLen);
|
||||
|
||||
// 3.通过 PixelMap 预处理
|
||||
let imageSource = image.createImageSource(file.fd);
|
||||
let pixelMap = await imageSource.createPixelMap({ editable: true });
|
||||
let info = await pixelMap.getImageInfo();
|
||||
console.info('MS_LITE_LOG: info.width = ' + info.size.width);
|
||||
console.info('MS_LITE_LOG: info.height = ' + info.size.height);
|
||||
|
||||
// 4. 获取图片buffer数据readBuffer,并进行处理
|
||||
pixelMap.scale(256.0 / info.size.width, 256.0 / info.size.height).then(() => {
|
||||
pixelMap.crop({
|
||||
x: 16,
|
||||
y: 16,
|
||||
size: { height: this.modelInputHeight, width: this.modelInputWidth }
|
||||
})
|
||||
.then(async () => {
|
||||
let info = await pixelMap.getImageInfo();
|
||||
console.info('MS_LITE_LOG: crop info.width = ' + info.size.width);
|
||||
console.info('MS_LITE_LOG: crop info.height = ' + info.size.height);
|
||||
// 需要创建的像素buffer大小
|
||||
let readBuffer = new ArrayBuffer(this.modelInputHeight * this.modelInputWidth * 4);
|
||||
await pixelMap.readPixelsToBuffer(readBuffer);
|
||||
console.info('MS_LITE_LOG: Succeeded in reading image pixel data, buffer: ' + readBuffer.byteLength);
|
||||
|
||||
// 处理readBuffer
|
||||
const imageArr =
|
||||
new Uint8Array(readBuffer.slice(0, this.modelInputHeight * this.modelInputWidth * 4));
|
||||
console.info('MS_LITE_LOG: imageArr length: ' + imageArr.length);
|
||||
let means = [0.485, 0.456, 0.406];
|
||||
let stds = [0.229, 0.224, 0.225];
|
||||
let float32View = new Float32Array(this.modelInputHeight * this.modelInputWidth * 3);
|
||||
let index = 0;
|
||||
for (let i = 0; i < imageArr.length; i++) {
|
||||
if ((i + 1) % 4 == 0) {
|
||||
float32View[index] = (imageArr[i - 3] / 255.0 - means[0]) / stds[0]; // B
|
||||
float32View[index+1] = (imageArr[i - 2] / 255.0 - means[1]) / stds[1]; // G
|
||||
float32View[index+2] = (imageArr[i - 1] / 255.0 - means[2]) / stds[2]; // R
|
||||
index += 3;
|
||||
}
|
||||
}
|
||||
console.info('MS_LITE_LOG: float32View length: ' + float32View.length);
|
||||
let printStr = 'float32View data:';
|
||||
for (let i = 0; i < 20; i++) {
|
||||
printStr += ' ' + float32View[i];
|
||||
}
|
||||
console.info('MS_LITE_LOG: float32View data: ' + printStr);
|
||||
|
||||
// 调用c++的runDemo
|
||||
console.info('MS_LITE_LOG: *** Start MSLite Demo ***');
|
||||
let output: Array<number> = msliteNapi.runDemo(Array.from(float32View), resMgr);
|
||||
console.warn('MS_LITE_WARN: output length = ', output.length, ';value = ', output.slice(0, 20));
|
||||
|
||||
// 取分类最大值top5
|
||||
let newArray = output.filter(value => value !== this.max);
|
||||
for (let n = 0; n < 5; n++) {
|
||||
this.max = output[0];
|
||||
this.maxIndex = 0;
|
||||
// 取最大值
|
||||
for (let m = 0; m < newArray.length; m++) {
|
||||
if (newArray[m] > this.max) {
|
||||
this.max = newArray[m];
|
||||
this.maxIndex = m;
|
||||
}
|
||||
}
|
||||
this.maxArray.push(Math.round(this.max * 10000));
|
||||
this.maxIndexArray.push(this.maxIndex);
|
||||
// filter函数 数组过滤函数
|
||||
newArray = newArray.filter(value => value !== this.max);
|
||||
}
|
||||
console.info('MS_LITE_LOG: max:' + this.maxArray);
|
||||
console.info('MS_LITE_LOG: maxIndex:' + this.maxIndexArray);
|
||||
console.info('MS_LITE_LOG: *** Finished MSLite Demo ***');
|
||||
})
|
||||
})
|
||||
// 5.关闭文件
|
||||
fileIo.closeSync(file);
|
||||
} catch (err) {
|
||||
console.error('MS_LITE_LOG: uri: open file fd failed.' + err);
|
||||
}
|
||||
})
|
||||
})
|
||||
}.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "MindSporeLiteC"
|
||||
},
|
||||
{
|
||||
"name": "completed",
|
||||
"value": "完成"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"layered-image": {
|
||||
"background": "$media:background",
|
||||
"foreground": "$media:foreground"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/Index"
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "MindSporeLiteC"
|
||||
},
|
||||
{
|
||||
"name": "completed",
|
||||
"value": "completed"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "MindSporeLiteC"
|
||||
},
|
||||
{
|
||||
"name": "completed",
|
||||
"value": "完成"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { describe, it, expect } from '@ohos/hypium';
|
||||
import Want from '@ohos.app.ability.Want';
|
||||
import Base from '@ohos.base';
|
||||
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
import { Driver, ON } from '@ohos.UiTest';
|
||||
import { getString } from '../utils/ResourceUtil';
|
||||
|
||||
const BUNDLE = 'MindSporeLiteCDemo_';
|
||||
const TAG = 'abilityTest';
|
||||
const DOMAIN: number = 0xF811;
|
||||
|
||||
export default function abilityTest() {
|
||||
let driver: Driver = Driver.create();
|
||||
describe('MindSporeLiteCDemoTest', () => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
/*
|
||||
* @tc.number: MindSporeLiteCDemoTest_000
|
||||
* @tc.name: Start Ability
|
||||
* @tc.desc: Start Ability
|
||||
* @tc.size: MediumTest
|
||||
* @tc.type: Function
|
||||
* @tc.level Level 1
|
||||
*/
|
||||
it('EntryAbility', 0, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'EntryAbility_001 begin');
|
||||
// Start Ability
|
||||
let want: Want = {
|
||||
bundleName: 'com.samples.mindsporelitecdemo',
|
||||
abilityName: 'EntryAbility'
|
||||
};
|
||||
let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
abilityDelegator.startAbility(want, (err: Base.BusinessError) => {
|
||||
hilog.info(DOMAIN, TAG, 'StartAbility get err ' + JSON.stringify(err));
|
||||
expect(err).assertNull();
|
||||
})
|
||||
await driver.delayMs(3000);
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'EntryAbility_001 end');
|
||||
done();
|
||||
})
|
||||
/**
|
||||
* @tc.number : MindSporeLiteCDemoTest_001
|
||||
* @tc.name : open photo
|
||||
* @tc.desc : open photo
|
||||
* @tc.size : MEDIUM
|
||||
* @tc.type : Function
|
||||
* @tc.level : Level 1
|
||||
*/
|
||||
it('IfExists', 0, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'IfExists_001 begin');
|
||||
await driver.delayMs(1000);
|
||||
await driver.assertComponentExist(ON.text('MindSporeLite C Demo'));
|
||||
await driver.assertComponentExist(ON.text('photo'));
|
||||
expect(true).assertTrue();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'IfExists_001 end');
|
||||
done();
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number : MindSporeLiteCDemoTest_002
|
||||
* @tc.name : open photo and predict
|
||||
* @tc.desc : open photo and predict
|
||||
* @tc.size : MEDIUM
|
||||
* @tc.type : Function
|
||||
* @tc.level : Level 1
|
||||
*/
|
||||
it('PhotoPredict', 0, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 begin');
|
||||
await driver.delayMs(1000);
|
||||
// click MindSporeLite C Demo
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 click photo button');
|
||||
await driver.assertComponentExist(ON.text('photo'));
|
||||
let msPhoto = await driver.findComponent(ON.text('photo'));
|
||||
await msPhoto.click();
|
||||
await driver.delayMs(1000);
|
||||
// chose a photo
|
||||
let gridItems = await driver.findComponents(ON.type('GridItem'));
|
||||
await gridItems[1].click();
|
||||
await driver.delayMs(5000);
|
||||
// click complete
|
||||
let tipCompleted: string = getString($r('app.string.completed'));
|
||||
await driver.assertComponentExist(ON.text(tipCompleted));
|
||||
let finish = await driver.findComponent(ON.text(tipCompleted));
|
||||
await driver.delayMs(5000);
|
||||
await finish.click();
|
||||
await driver.delayMs(5000);
|
||||
// predict
|
||||
await driver.assertComponentExist(ON.text('MindSporeLite C Demo'));
|
||||
await driver.assertComponentExist(ON.text('%', 1));
|
||||
await driver.delayMs(5000);
|
||||
expect(true).assertTrue();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'PhotoPredict_001 end');
|
||||
done();
|
||||
})
|
||||
})
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { abilityDelegatorRegistry } from '@kit.TestKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
import { Hypium } from '@ohos/hypium';
|
||||
import testsuite from '../test/List.test';
|
||||
|
||||
export default class TestAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
||||
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: abilityDelegatorRegistry.AbilityDelegator;
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator();
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments();
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
|
||||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
|
||||
windowStage.loadContent('testability/pages/Index', (err) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
|
||||
}
|
||||
|
||||
onBackground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
import { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit';
|
||||
import { UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { resourceManager } from '@kit.LocalizationKit';
|
||||
import { util } from '@kit.ArkTS';
|
||||
|
||||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
let jsonPath: string = 'mock/mock-config.json';
|
||||
let tag: string = 'testTag';
|
||||
|
||||
async function onAbilityCreateCallback(data: UIAbility) {
|
||||
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data));
|
||||
}
|
||||
|
||||
async function addAbilityMonitorCallback(err: BusinessError) {
|
||||
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
|
||||
}
|
||||
|
||||
export default class OpenHarmonyTestRunner implements TestRunner {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
onPrepare() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare');
|
||||
}
|
||||
|
||||
async onRun() {
|
||||
let tag = 'testTag';
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run');
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments()
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
|
||||
let moduleName = abilityDelegatorArguments.parameters['-m'];
|
||||
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName);
|
||||
let mResourceManager = context.resourceManager;
|
||||
await checkMock(abilityDelegator, mResourceManager);
|
||||
const bundleName = abilityDelegatorArguments.bundleName;
|
||||
const testAbilityName: string = 'TestAbility';
|
||||
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = {
|
||||
abilityName: testAbilityName,
|
||||
onAbilityCreate: onAbilityCreateCallback,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
|
||||
const want: Want = {
|
||||
bundleName: bundleName,
|
||||
abilityName: testAbilityName,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => {
|
||||
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
|
||||
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? '');
|
||||
})
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator,
|
||||
resourceManager: resourceManager.ResourceManager) {
|
||||
let rawFile: Uint8Array;
|
||||
try {
|
||||
rawFile = resourceManager.getRawFileContentSync(jsonPath);
|
||||
hilog.info(0x0000, tag, 'MockList file exists');
|
||||
let mockStr: string = util.TextDecoder.create('utf-8', { ignoreBOM: true }).decodeWithStream(rawFile);
|
||||
let mockMap: Record<string, string> = getMockList(mockStr);
|
||||
try {
|
||||
abilityDelegator.setMockList(mockMap)
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function getMockList(jsonStr: string) {
|
||||
let jsonObj: Record<string, Object> = JSON.parse(jsonStr);
|
||||
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
|
||||
let mockList: Record<string, string> = {};
|
||||
map.forEach((value: object, key: string) => {
|
||||
let realValue: string = value['source'].toString();
|
||||
mockList[key] = realValue;
|
||||
});
|
||||
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? '');
|
||||
return mockList;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hunan OpenValley 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 AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
|
||||
const delegator = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
|
||||
export function getString(resourceData: Resource): string {
|
||||
let manage = delegator.getAppContext().resourceManager;
|
||||
return manage.getStringSync(resourceData);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"module": {
|
||||
"name": "entry_test",
|
||||
"type": "feature",
|
||||
"description": "$string:module_test_desc",
|
||||
"mainElement": "TestAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
},
|
||||
{
|
||||
"name": "completed",
|
||||
"value": "完成"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 2.7 KiB |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
import localUnitTest from './LocalUnit.test';
|
||||
|
||||
export default function testsuite() {
|
||||
localUnitTest();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
|
||||
|
||||
export default function localUnitTest() {
|
||||
describe('localUnitTest',() => {
|
||||
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
|
||||
beforeAll(() => {
|
||||
// Presets an action, which is performed only once before all test cases of the test suite start.
|
||||
// This API supports only one parameter: preset action function.
|
||||
});
|
||||
beforeEach(() => {
|
||||
// Presets an action, which is performed before each unit test case starts.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: preset action function.
|
||||
});
|
||||
afterEach(() => {
|
||||
// Presets a clear action, which is performed after each unit test case ends.
|
||||
// The number of execution times is the same as the number of test cases defined by **it**.
|
||||
// This API supports only one parameter: clear action function.
|
||||
});
|
||||
afterAll(() => {
|
||||
// Presets a clear action, which is performed after all test cases of the test suite end.
|
||||
// This API supports only one parameter: clear action function.
|
||||
});
|
||||
it('assertContain', 0, () => {
|
||||
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
|
||||
let a = 'abc';
|
||||
let b = 'b';
|
||||
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
|
||||
expect(a).assertContain(b);
|
||||
expect(a).assertEqual(a);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"hvigorVersion": "4.1.2",
|
||||
"dependencies": {
|
||||
"@ohos/hvigor-ohos-plugin": "4.1.2"
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
|
||||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"logging": {
|
||||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||
},
|
||||
"debugging": {
|
||||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"nodeOptions": {
|
||||
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
||||
|
||||
export default {
|
||||
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
||||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"name": "mindsporelitecdemo",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.16",
|
||||
"@ohos/hamock": "1.0.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# MindSporeLiteCDemo 测试用例归档
|
||||
|
||||
## 用例表
|
||||
|
||||
|测试功能|预置条件|输入|预期输出|是否自动|测试结果|
|
||||
|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|
|
||||
|拉起应用| 设备正常运行| |成功拉起应用|是|Pass|
|
||||
|查看预览界面Text和Button| 进入预览界面 | |预览界面存在Text和Button|是|Pass|
|
||||
|选取图片推理功能测试| 进入预览界面 | 点击photo按钮 |选取图片后进行推理|是|Pass|
|
After Width: | Height: | Size: 383 KiB |