This commit is contained in:
wangzhongjie 2025-09-16 14:44:29 +08:00
commit c06ab7aba3
38 changed files with 1177 additions and 0 deletions

11
.gitignore vendored Normal file
View File

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

10
AppScope/app.json5 Normal file
View File

@ -0,0 +1,10 @@
{
"app": {
"bundleName": "com.example.upload",
"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": "upload"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

48
build-profile.json5 Normal file
View File

@ -0,0 +1,48 @@
{
"app": {
"signingConfigs": [
{
"name": "default",
"material": {
"certpath": "/Users/wangzhongjie/.ohos/config/openharmony/default_upload_BWmbloNkrkT2iy12C2klZarIu9514jjO0YAarnfah5M=.cer",
"storePassword": "0000001AC0D14A6CC409CB78A42B61F61B4B68F95F9C548AF44616BB0F63AF0374D2B9703F875C6B63D3",
"keyAlias": "debugKey",
"keyPassword": "0000001A0B203CD46F6D29C6B8AFA9B333A454565149F98F37951B2C91AEAF9D0BBA262FEB863D577BB5",
"profile": "/Users/wangzhongjie/.ohos/config/openharmony/default_upload_BWmbloNkrkT2iy12C2klZarIu9514jjO0YAarnfah5M=.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "/Users/wangzhongjie/.ohos/config/openharmony/default_upload_BWmbloNkrkT2iy12C2klZarIu9514jjO0YAarnfah5M=.p12"
}
}
],
"compileSdkVersion": 9,
"compatibleSdkVersion": 9,
"products": [
{
"name": "default",
"signingConfig": "default",
}
],
"buildModeSet": [
{
"name": "debug",
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

6
entry/.gitignore vendored Normal file
View File

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

14
entry/build-profile.json5 Normal file
View File

@ -0,0 +1,14 @@
{
"apiType": "stageMode",
"buildOption": {
},
"targets": [
{
"name": "default",
"runtimeOS": "HarmonyOS"
},
{
"name": "ohosTest",
}
]
}

6
entry/hvigorfile.ts Normal file
View File

@ -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. */
}

10
entry/oh-package.json5 Normal file
View File

@ -0,0 +1,10 @@
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {}
}

View File

@ -0,0 +1,56 @@
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import Want from '@ohos.app.ability.Want';
import window from '@ohos.window';
import appRecovery from '@ohos.app.ability.appRecovery';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
appRecovery.enableAppRecovery(
appRecovery.RestartFlag.ALWAYS_RESTART,
appRecovery.SaveOccasionFlag.SAVE_WHEN_ERROR,
appRecovery.SaveModeFlag.SAVE_WITH_FILE
)
// 获取want.parameters参数
let closedApp = want.parameters['closedApp'];
if (closedApp === '1') {
// 关闭app
this.context.terminateSelf()
}
}
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');
}
}

View File

@ -0,0 +1,172 @@
import Want from '@ohos.app.ability.Want';
import common from '@ohos.app.ability.common';
import pasteboard from '@ohos.pasteboard';
import request from './request';
import http from '@ohos.net.http';
@Entry
@Component
struct Index {
// 需要上传的数据
@State needUploadData: any[] = [];
// 已上传的数据
@State uploadedData: any[] = [];
// 定时任务
@State timer: number = -1;
// 是否正在上传,用于控制一次只允许一个上传任务
@State isUploading: boolean = false;
aboutToAppear(): void {
let context = getContext(this) as common.UIAbilityContext;
const info = context.abilityInfo
console.log("查看信息", info.bundleName, info.name, info.moduleName)
this.pullUp()
// 一秒获取一次数据
this.timer = setInterval(() => {
this.getData()
}, 1000);
}
async pullUp() {
let want: Want = {
bundleName: 'com.oh.dts', // 替换为你的应用包名
abilityName: 'EntryAbility', // 你的 Service Ability 名称
moduleName: 'entry', // 你的模块名称,通常是 'entry',
parameters: {}
};
try {
let context = getContext(this) as common.UIAbilityContext;
context.startAbility(want)
.then(() => {
})
.catch((error) => {
console.error(`拉起应用失败: ${error.code} - ${error.message}`);
});
} catch (error) {
console.error(`启动Ability异常: ${error.message}`);
}
}
// 读取剪切板数据
getData() {
let systemPasteboard = pasteboard.getSystemPasteboard()
systemPasteboard.getData().then(res => {
let pasteData = res.getPrimaryText()
if (pasteData) {
try {
let data = JSON.parse(pasteData)
// 避免重复添加相同数据,这里可以根据你的实际需求添加更复杂的去重逻辑
if (!this.uploadedData.some(item => JSON.stringify(item) === JSON.stringify(data)) && !this.needUploadData.some(item => JSON.stringify(item) === JSON.stringify(data))) {
this.needUploadData.push(data)
console.log("added data to needUploadData:", JSON.stringify(data));
}
// 清除剪切板
systemPasteboard.clear();
// 如果当前没有上传任务正在进行,则启动上传任务
if (!this.isUploading && this.needUploadData.length > 0) {
this.uploadTask();
}
} catch (e) {
console.error("failed to parse pasteboard data:", e);
}
}
}).catch(error => {
console.error("failed to get pasteboard data:", error);
});
}
// 轮询上传任务,request 返回code等于1为成功,不成功则继续上传这个任务,直到成功
async uploadTask() {
if (this.isUploading) {
console.log("already uploading, skipping new task initiation.");
return; // 如果正在上传,则不启动新的上传任务
}
if (this.needUploadData.length === 0) {
console.log("no pending tasks, waiting for new data.");
this.isUploading = false; // 确保在没有任务时将标志位重置
return;
}
this.isUploading = true; // 设置标志位,表示正在上传
let task = this.needUploadData[0];
console.log("starting upload for task:", JSON.stringify(task));
try {
let response: any = await request(task);
console.log("response for task", JSON.stringify(task), ":", JSON.stringify(response));
if (response.code === 1) {
this.uploadedData.push(task);
this.needUploadData.shift(); // 成功后移除任务
console.log("task uploaded successfully. Remaining tasks:", this.needUploadData.length);
} else {
console.warn("task upload failed, retrying later:", JSON.stringify(task));
// 失败不移除任务,等待下一次轮询重试
}
} catch (error) {
console.error("error during upload for task", JSON.stringify(task), ":", error);
// 捕获错误,任务不移除,等待下一次轮询重试
} finally {
this.isUploading = false; // 任务完成(无论成功或失败),重置标志位
// 无论任务成功失败,都尝试启动下一个任务(如果存在)
// 使用setTimeout确保不会阻塞UI线程并且给一点时间等待新数据或者防止过于频繁的请求
if (this.needUploadData.length > 0) {
setTimeout(() => this.uploadTask(), 1000); // 1秒后尝试启动下一个任务
} else {
console.log("all tasks processed for now.");
}
}
}
// 组件销毁时清除定时器
onDeactivate(): void {
if (this.timer !== -1) {
clearInterval(this.timer);
this.timer = -1;
}
}
build() {
Row() {
Column() {
Button() {
Text("拉起驾考")
}.width(200).height(100)
.onClick(async () => {
let want: Want = {
bundleName: 'com.oh.dts', // 替换为你的应用包名
abilityName: 'EntryAbility', // 你的 Service Ability 名称
moduleName: 'entry', // 你的模块名称,通常是 'entry',
parameters: {}
};
try {
let context = getContext(this) as common.UIAbilityContext;
context.startAbility(want)
.then(() => {
})
.catch((error) => {
console.error(`拉起应用失败: ${error.code} - ${error.message}`);
});
} catch (error) {
console.error(`启动Ability异常: ${error.message}`);
}
})
}
.width('100%')
Column() {
Button() {
Text("关闭次app")
}.onClick(() => {
(getContext(this) as common.UIAbilityContext).terminateSelf()
})
}.margin({
top: 20
})
}
.height('100%')
}
}

View File

@ -0,0 +1,240 @@
import http from '@ohos.net.http';
import Prompt from '@system.prompt';
import convertxml from '@ohos.convertxml';
export default async function request<T>(req: any): Promise<T> {
return new Promise((resolve, reject) => {
let httpRequest = http.createHttp();
const { url, params = {}, data = {}, xml, method = 'get', host, isNewCenter = false } = req;
try {
const options = {
method: http.RequestMethod[method.toUpperCase()],
header: {
'Content-Type': xml ? 'text/xml' : 'application/json'
},
extraData: xml ? data : JSON.stringify(data),
connectTimeout: 15 * 1000
}
let paramsStr = Reflect.ownKeys(params).reduce((p: string, n: string) => (`${p}${n}=${params[n]}&`), '?') || '';
paramsStr = paramsStr.toString();
paramsStr = paramsStr.substring(0, paramsStr.length - 1)
let baseUrl = host ? host : globalThis.host
// let baseUrl=host?config.csptHost:config.host'
console.log('响应头地址1' + baseUrl, url, options.extraData.length)
// const {result,responseCode} = await
httpRequest.request(`${baseUrl}${url}${paramsStr}`, {
...options
})
.then(async (data) => {
const result = data.result
console.log('响应头地址' + JSON.stringify(result))
let res: any = xml ? xmlToJson(result, url) : result;
console.log('响应头地址' + JSON.stringify(res))
let resObj = null;
if (typeof res === "string") {
res = JSON.parse(res)
}
if (res.code !== undefined) {
resolve(res)
return
}
//处理中心服务code
if (res.Envelope) {
const msgXml = res.Envelope.Body.writeObjectOutResponse.return;
const dd = handleCenterCode(msgXml, isNewCenter);
httpRequest.destroy();
// @ts-ignore
resolve(dd)
return
}
if (!xml) {
if (res.head.resultCode === '0') {
httpRequest.destroy();
resolve(res)
return
} else {
const resultMessage = res?.body?.resultMessage || res?.head?.resultMessage
Prompt.showToast({
message: decodeURIComponent(resultMessage),
duration: 3000
});
httpRequest.destroy();
reject(false)
}
}
for (let i in res) {
resObj = res[i].head
}
console.info('jiangsong:res in request' + url + JSON.stringify(resObj))
if (resObj.resultCode === '0') {
httpRequest.destroy();
resolve(res)
return
} else {
Prompt.showToast({
message: decodeURIComponent(resObj.resultMessage),
duration: 3000
});
httpRequest.destroy();
reject(res)
}
}).catch(Error => {
console.info('test-error0' + url + ' error:resp: ' + JSON.stringify(Error.message))
httpRequest.destroy();
Prompt.showToast({
message: Error?.message,
duration: 5000
});
reject(Error)
})
} catch (e) {
console.info('test-error' + url + ' error:resp: ' + JSON.stringify(e))
if (!e || !(e?.message)) {
httpRequest.destroy();
reject({
code: -1
})
}
Prompt.showToast({
message: e?.message,
duration: 5000
});
reject({
code: e.code
})
}
})
}
//xml格式转JSON
function xmlToJson(result, url) {
console.log("xmlToJson begin", url);
let xmlOptions = {
trim: false,
declarationKey: "_declaration",
instructionKey: "_instruction",
attributesKey: "_attributes",
textKey: "_text",
cdataKey: "_cdata",
doctypeKey: "_doctype",
commentKey: "_comment",
parentKey: "_parent",
typeKey: "_type",
nameKey: "_name",
elementsKey: "_elements",
"skipPreprocess": true
}
let strXml = result.toString();
let conv = new convertxml.ConvertXML();
console.log("xmlToJson result.length = " + result.length);
console.log("xmlToJson result content = " + result);
// @ts-ignore
let { _elements: xmlArr } = conv.convertToJSObject(strXml, xmlOptions);
console.log("xmlToJson deeml begin");
let res = deeml(xmlArr);
console.log("xmlToJson end", url);
return res
}
//处理中心服务code
function handleCenterCode(msgXml, isNewCenter) {
//新监管
if (isNewCenter) {
const msg = JSON.parse(msgXml);
const result = msg?.data[0]?.result;
if (result) {
const { code, message, retval } = result
if (code != '1') {
const rMessage = decodeURIComponent(message as string)
Prompt.showToast({
message: rMessage,
duration: 3000
});
return { code, message }
} else {
return { code, keystr: retval }
}
}
}
//正则匹配code message字段
const [code, message, keystr] = [/<code>(.*)<\/code>/i, /<message>(.*)<\/message>/i, /<keystr>(.*)<\/keystr>/i].map(pattern => {
const patternArr = pattern.exec(msgXml);
return patternArr && patternArr[1]
});
if (code != '1') {
Prompt.showToast({
message: decodeURIComponent(message as string),
duration: 3000
});
// globalThis.type='1'
// globalThis.title=decodeURIComponent(message as string)
// globalThis.errorDialog.open()
return { code, message: decodeURIComponent(message) }
} else {
return { code, keystr, message }
}
}
//JSON转xml格式
const deeml = (elements, _name?) => {
const json = {}
elements.map(ele => {
const _elements = ele._elements
if (ele._type === 'element') {
if (_elements == undefined) {
return
}
const thisJson = json[ele._name]
if (_elements && _elements.length === 1 && _elements[0]._type === 'text') {
// 如果值存在了
if (thisJson) {
handleCommonArr(_elements[0]._text)
} else {
json[ele._name] = _elements[0]._text
}
} else {
if (thisJson) {
handleCommonArr(deeml(ele._elements, ele._name))
} else {
json[ele._name] = deeml(ele._elements, ele._name)
}
}
//通用处理重复标签
function handleCommonArr(obj) {
if (thisJson) {
if (Array.isArray(thisJson)) {
json[ele._name].push(obj)
} else {
json[ele._name] = [json[ele._name], obj]
}
} else {
json[ele._name] = obj
}
}
0
} else {
//标签上有属性
if (ele._attributes) {
json[_name] = {
value: ele._text,
attributes: ele.__attributes
}
}
}
});
return json
};

View File

148
entry/src/main/module.json5 Normal file
View File

@ -0,0 +1,148 @@
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet"
],
"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:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions":[
{"name": "ohos.permission.CONNECTIVITY_INTERNAL"},
{"name": "ohos.permission.SET_TIME"},
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.CAMERA",
},
{
"name": "ohos.permission.GET_WIFI_INFO"
},
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC",
},
{
"name": "ohos.permission.GET_NETWORK_INFO",
},
{
"name": "ohos.permission.SET_NETWORK_INFO",
},
{
"name": "ohos.permission.REBOOT",
},
{
"name": "ohos.permission.MICROPHONE"
},
{
"name": "ohos.permission.READ_AUDIO"
},
{
"name": "ohos.permission.READ_DOCUMENT"
},
{
"name": "ohos.permission.WRITE_AUDIO"
},
{
"name": "ohos.permission.WRITE_DOCUMENT"
},
{
"name": "ohos.permission.MEDIA_LOCATION"
},
{
"name": "ohos.permission.WRITE_MEDIA"
},
{
"name": "ohos.permission.READ_MEDIA"
},
{
"name": "ohos.permission.WRITE_IMAGEVIDEO",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.READ_IMAGEVIDEO",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
// {
// "name": "ohos.permission.READ_MEDIA",
// "reason": "$string:module_desc",
// "usedScene": {
// "abilities": [
// "MainAbility"
// ],
// "when": "always"
// }
// },
// {
// "name": "ohos.permission.WRITE_MEDIA",
// "reason": "$string:module_desc",
// "usedScene": {
// "abilities": [
// "MainAbility"
// ],
// "when": "always"
// }
// },
{
"name": "ohos.permission.FILE_ACCESS_MANAGER",
"reason": "$string:module_desc",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.STORAGE_MANAGER"
},
{
"name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED",
"reason": "$string:module_desc",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
},
]
}
}

View File

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

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

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

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_desc",
"value": "模块描述"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}

View File

@ -0,0 +1,35 @@
import hilog from '@ohos.hilog';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// 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.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
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);
})
})
}

View File

@ -0,0 +1,5 @@
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}

View File

@ -0,0 +1,49 @@
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';
import Want from '@ohos.app.ability.Want';
import AbilityConstant from '@ohos.app.ability.AbilityConstant';
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');
}
}

View File

@ -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%')
}
}

View File

@ -0,0 +1,50 @@
import hilog from '@ohos.hilog';
import TestRunner from '@ohos.application.testRunner';
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import Want from '@ohos.app.ability.Want';
let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined
let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined
async function onAbilityCreateCallback() {
hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err : Error) {
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() {
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run');
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
const bundleName = abilityDelegatorArguments.bundleName;
const testAbilityName = 'TestAbility';
const moduleName = abilityDelegatorArguments.parameters['-m'];
let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
moduleName: moduleName
};
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
const want: Want = {
bundleName: bundleName,
abilityName: testAbilityName,
moduleName: moduleName
};
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
abilityDelegator.startAbility(want, (err, data) => {
hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? '');
})
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end');
}
}

View File

@ -0,0 +1,37 @@
{
"module": {
"name": "entry_test",
"type": "feature",
"description": "$string:module_test_desc",
"mainElement": "TestAbility",
"deviceTypes": [
"phone",
"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"
]
}
]
}
]
}
}

View File

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

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "module_test_desc",
"value": "test ability description"
},
{
"name": "TestAbility_desc",
"value": "the test ability"
},
{
"name": "TestAbility_label",
"value": "test label"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,5 @@
{
"src": [
"testability/pages/Index"
]
}

View File

@ -0,0 +1,22 @@
{
"hvigorVersion": "3.2.4",
"dependencies": {
"@ohos/hvigor-ohos-plugin": "3.2.4"
},
"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 */
}
}

1
hvigor/hvigor-wrapper.js Normal file

File diff suppressed because one or more lines are too long

6
hvigorfile.ts Normal file
View File

@ -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. */
}

54
hvigorw Normal file
View File

@ -0,0 +1,54 @@
#!/bin/bash
# ----------------------------------------------------------------------------
# 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="`pwd -P`"
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
#NODE_OPTS="--max-old-space-size=4096"
fail() {
echo "$*"
exit 1
}
set_executable_node() {
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
if [ -x "$EXECUTABLE_NODE" ]; then
return
fi
EXECUTABLE_NODE="${NODE_HOME}/node"
if [ -x "$EXECUTABLE_NODE" ]; then
return
fi
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"
}
# Determine node to start hvigor wrapper script
if [ -n "${NODE_HOME}" ]; then
set_executable_node
else
EXECUTABLE_NODE="node"
command -v ${EXECUTABLE_NODE} &> /dev/null || fail "ERROR: NODE_HOME not set and 'node' command not found"
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
if [ -z "${NODE_OPTS}" ]; then
NODE_OPTS="--"
fi
# start hvigor-wrapper script
exec "${EXECUTABLE_NODE}" "${NODE_OPTS}" \
"${HVIGOR_WRAPPER_SCRIPT}" "$@"

54
hvigorw.bat Normal file
View File

@ -0,0 +1,54 @@
@rem
@rem ----------------------------------------------------------------------------
@rem Hvigor startup script for Windows, version 1.0.0
@rem
@rem Required ENV vars:
@rem ------------------
@rem NODE_HOME - location of a Node home dir
@rem or
@rem Add %NODE_HOME%/bin to the PATH environment variable
@rem ----------------------------------------------------------------------------
@rem
@echo off
@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%
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
set NODE_EXE=node.exe
@rem set NODE_OPTS="--max-old-space-size=4096"
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
if not defined NODE_OPTS set NODE_OPTS="--"
@rem Find node.exe
if defined NODE_HOME (
set NODE_HOME=%NODE_HOME:"=%
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
)
%NODE_EXE% --version >NUL 2>&1
if "%ERRORLEVEL%" == "0" (
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
) else if exist "%NODE_EXE_PATH%" (
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
) else (
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.
)
if "%ERRORLEVEL%" == "0" (
if "%OS%" == "Windows_NT" endlocal
) else (
exit /b %ERRORLEVEL%
)

15
oh-package-lock.json5 Normal file
View File

@ -0,0 +1,15 @@
{
"lockfileVersion": 2,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@ohos/hypium@1.0.13": "@ohos/hypium@1.0.13"
},
"packages": {
"@ohos/hypium@1.0.13": {
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.13.tgz",
"integrity": "sha512-d0+XvDeAYk5Vgl6JQ8Q1G+NPmTyJI8qgZ1PwPfcUbx/dfyKVAAv9lz1XtVNhYypyWEKqAzu8zMAC9GuHo2Y53Q==",
"registryType": "ohpm",
"shasum": "88d8dda420097efb98d770bf59616faef4682f06"
}
}
}

13
oh-package.json5 Normal file
View File

@ -0,0 +1,13 @@
{
"name": "upload",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
},
"devDependencies": {
"@ohos/hypium": "1.0.13"
}
}