diff --git a/input/ArkTSInputConsumer/.gitignore b/input/ArkTSInputConsumer/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/input/ArkTSInputConsumer/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/input/ArkTSInputConsumer/AppScope/app.json5 b/input/ArkTSInputConsumer/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8f72f4ff960952151a06c479c9ef4e56a3a8868c --- /dev/null +++ b/input/ArkTSInputConsumer/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.arktsinputconsumer", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/input/ArkTSInputConsumer/AppScope/resources/base/element/string.json b/input/ArkTSInputConsumer/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..811cfd0fa85b52f7a10aecc0a763b289a1010ab8 --- /dev/null +++ b/input/ArkTSInputConsumer/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ArkTSInputConsumer" + } + ] +} diff --git a/input/ArkTSInputConsumer/AppScope/resources/base/media/background.png b/input/ArkTSInputConsumer/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTSInputConsumer/AppScope/resources/base/media/background.png differ diff --git a/input/ArkTSInputConsumer/AppScope/resources/base/media/foreground.png b/input/ArkTSInputConsumer/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/input/ArkTSInputConsumer/AppScope/resources/base/media/foreground.png differ diff --git a/input/ArkTSInputConsumer/AppScope/resources/base/media/layered_image.json b/input/ArkTSInputConsumer/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTSInputConsumer/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/README_zh.md b/input/ArkTSInputConsumer/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..dc81a5310b3bd112f19091062e82b06f57d0b923 --- /dev/null +++ b/input/ArkTSInputConsumer/README_zh.md @@ -0,0 +1,68 @@ +# 优先响应系统功能键(ArkTS) + +## 介绍 + +本工程主要实现了对以下指南文档[优先响应系统功能键开发指导](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/device/input/keypressed-guidelines.md) +中示例代码片段的工程化,通过该工程可以添加和取消对音量上下键的拦截监听。 + +## 效果预览 + +| ![](screenshot/inputConsumer.png) | +|-----------------------------------| + +使用说明: + +1. 安装编译生成的hap包,打开应用时会自动添加对音量上下键的拦截监听。 +2. 使用音量上下键,按键事件会被拦截并在页面弹出提示,无法正常调节音量。 +3. 点击对应按钮取消对音量上下键的拦截监听,再次使用音量上下键,可以正常调节音量。 +4. 点击对应按钮重新添加对音量上下键的拦截监听,再次使用音量上下键,无法正常调节音量。 +5. 进入"DocsSample/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/Ability.test.ets"文件,可以对本项目进行UI的自动化测试。 + +## 工程目录 + +``` +ArkTSInputConsumer +├──entry/src/main +│ ├──ets +│ │ ├──entryability +| | ├──entrybackupability +│ │ └──pages +│ │ └──Index.ets // 示例代码 +| ├──resources + ├── ohosTest + │ ├── ets + │ │ └── test + │ │ └── Ability.test.ets // 自动化测试代码 +``` + +### 具体实现 + +1. 在[Index.ets](entry/src/main/ets/pages/Index.ets)文件中,通过点击按钮取消监听音量按键上/下的监听。 +2. 在[Ability.test.ets](entry/src/ohosTest/ets/test/Ability.test.ets)文件中,通过自动化对取消音量上/下键的监听测试。 + +## 相关权限 + +无。 + +## 依赖 + +不涉及。 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:Phone、Tablet。 +2. 本示例支持API20版本SDK,版本号:6.0.0.36。 +3. 本示例已支持使DevEco Studio 5.1.1 Release (构建版本:5.1.1.840,构建 2025年9月20日)编译运行。 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/input/ArkTSInputConsumer > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/input/ArkTSInputConsumer/build-profile.json5 b/input/ArkTSInputConsumer/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b4c76119a50cee21e3a9edbb58ebed7905e7c08e --- /dev/null +++ b/input/ArkTSInputConsumer/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "targetSdkVersion": 20, + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/code-linter.json5 b/input/ArkTSInputConsumer/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/input/ArkTSInputConsumer/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/.gitignore b/input/ArkTSInputConsumer/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/build-profile.json5 b/input/ArkTSInputConsumer/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f --- /dev/null +++ b/input/ArkTSInputConsumer/entry/build-profile.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/hvigorfile.ts b/input/ArkTSInputConsumer/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/obfuscation-rules.txt b/input/ArkTSInputConsumer/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/input/ArkTSInputConsumer/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/oh-package.json5 b/input/ArkTSInputConsumer/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/input/ArkTSInputConsumer/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/input/ArkTSInputConsumer/entry/src/main/ets/entryability/EntryAbility.ets b/input/ArkTSInputConsumer/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/input/ArkTSInputConsumer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/ets/pages/Index.ets b/input/ArkTSInputConsumer/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..1075f7730e126ef9caf53183b2cc11b47d4291c3 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start input_monitor] +import { inputConsumer, KeyEvent } from '@kit.InputKit'; +import hilog from '@ohos.hilog'; +import { KeyCode } from '@kit.InputKit'; + +const DOMAIN = 0x0000; + +@Entry +@Component +struct TestDemo14 { + @State text: string = "Default monitoring for Volume Up and Down keys has been added." + private volumeUpCallBackFunc: (event: KeyEvent) => void = () => { + } + private volumeDownCallBackFunc: (event: KeyEvent) => void = () => { + } + options1: inputConsumer.KeyPressedConfig = { + key: KeyCode.KEYCODE_VOLUME_UP, + action: 1, // 按下按键的行为 + isRepeat: false, // 优先消费掉按键事件,不上报 + } + options2: inputConsumer.KeyPressedConfig = { + key: KeyCode.KEYCODE_VOLUME_DOWN, + action: 1, // 按下按键的行为 + isRepeat: false, // 优先消费掉按键事件,不上报 + } + + aboutToAppear(): void { + try { + // 点击了音量按键上事件回调 + this.volumeUpCallBackFunc = (event: KeyEvent) => { + this.getUIContext().getPromptAction().showToast({ message: 'Volume Up key pressed' }) + // do something + } + + // 点击了音量按键下事件回调 + this.volumeDownCallBackFunc = (event: KeyEvent) => { + this.getUIContext().getPromptAction().showToast({ message: 'Volume Down key pressed' }) + // do something + } + // 注册监听事件 + inputConsumer.on('keyPressed', this.options1, this.volumeUpCallBackFunc); + inputConsumer.on('keyPressed', this.options2, this.volumeDownCallBackFunc); + } catch (error) { + hilog.error(DOMAIN, 'InputConsumer', `Subscribe execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + } + } + + build() { + Column() { + Row() { + Button('Add monitoring for Volume Up key') + .onClick(() => { + try { + // 添加指定回调函数 + inputConsumer.on('keyPressed', this.options1, this.volumeUpCallBackFunc); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Successfully added monitoring for Volume Up key!' }) + this.text = "Monitoring for Volume Up key has been added." + } catch (error) { + hilog.error(DOMAIN, 'InputConsumer', `Unsubscribe execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Failed to add monitoring for Volume Up key!' }) + this.text = `Failed to add monitoring for Volume Up key: ${JSON.stringify(error, ["code", "message"])}` + } + }) + }.width('100%') + .justifyContent(FlexAlign.Center) + .margin({ top: 20, bottom: 50 }) + + Row() { + Button('Remove monitoring for Volume Up key') + .onClick(() => { + try { + // 取消指定回调函数 + inputConsumer.off('keyPressed', this.volumeUpCallBackFunc); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Successfully removed monitoring for Volume Up key!' }) + this.text = "Monitoring for Volume Up key has been removed." + } catch (error) { + hilog.error(DOMAIN, 'InputConsumer', `Unsubscribe execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Failed to remove monitoring for Volume Up key!' }) + this.text = `Failed to remove monitoring for Volume Up key: ${JSON.stringify(error, ["code", "message"])}` + } + }) + }.width('100%') + .justifyContent(FlexAlign.Center) + .margin({ top: 20, bottom: 50 }) + + Row() { + Button('Add monitoring for Volume Down key') + .onClick(() => { + try { + // 添加指定回调函数 + inputConsumer.on('keyPressed', this.options2, this.volumeDownCallBackFunc); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Successfully added monitoring for Volume Down key!' }) + this.text = "Monitoring for Volume Down key has been added." + } catch (error) { + hilog.error(DOMAIN, 'InputConsumer', `Unsubscribe execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Failed to add monitoring for Volume Down key!' }) + this.text = `Failed to add monitoring for Volume Down key: ${JSON.stringify(error, ["code", "message"])}` + } + }) + }.width('100%') + .justifyContent(FlexAlign.Center) + .margin({ top: 20, bottom: 50 }) + + Row() { + Button('Remove monitoring for Volume Down key') + .onClick(() => { + try { + // 取消指定回调函数 + inputConsumer.off('keyPressed', this.volumeDownCallBackFunc); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Successfully removed monitoring for Volume Down key!' }) + this.text = "Monitoring for Volume Down key has been removed." + } catch (error) { + hilog.error(DOMAIN, 'InputConsumer', `Unsubscribe execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + this.getUIContext() + .getPromptAction() + .showToast({ message: 'Failed to remove monitoring for Volume Down key!' }) + this.text = + `Failed to remove monitoring for Volume Down key: ${JSON.stringify(error, ["code", "message"])}` + } + }) + }.width('100%') + .justifyContent(FlexAlign.Center) + .margin({ top: 20, bottom: 50 }) + + Row() { + Text(this.text) + } + .width('100%') + .justifyContent(FlexAlign.Center) + }.width('100%').height('100%') + } +} + +// [End input_monitor] \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/module.json5 b/input/ArkTSInputConsumer/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..476f4f508edb44dc9edfe115808545c33b284e0b --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/module.json5 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/element/color.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/element/float.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/element/string.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/media/background.png b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/background.png differ diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/media/foreground.png b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/foreground.png differ diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/media/layered_image.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/media/startIcon.png b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/input/ArkTSInputConsumer/entry/src/main/resources/base/media/startIcon.png differ diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/backup_config.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/main_pages.json b/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/input/ArkTSInputConsumer/entry/src/main/resources/dark/element/color.json b/input/ArkTSInputConsumer/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/mock/mock-config.json5 b/input/ArkTSInputConsumer/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/Ability.test.ets b/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0353819e040cac171dac1080ba992e77d311658f --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import hilog from '@ohos.hilog'; + +const TAG = '[Sample_ArkTSInputConsumerAPI]'; +const DOMAIN = 0xF811; +const BUNDLE = 'ArkTSInputConsumerAPI_'; + + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + /** + * 打开应用 + */ + it('ArkTSInputConsumerAPI_StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputconsumer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add monitoring for Volume Up key')); + await driver.assertComponentExist(ON.text('Remove monitoring for Volume Up key')); + await driver.assertComponentExist(ON.text('Add monitoring for Volume Down key')); + await driver.assertComponentExist(ON.text('Remove monitoring for Volume Down key')); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 取消音量上键的监听 + */ + it('ArkTSInputConsumerAPI_off_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'CancelMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputconsumer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `CancelMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove monitoring for Volume Up key')); + let button = await driver.findComponent(ON.text('Remove monitoring for Volume Up key')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'CancelMonitor_001 end') + }) + + /** + * 取消音量下键的监听 + */ + it('ArkTSInputConsumerAPI_off_002', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'CancelMonitor_002, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputconsumer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `CancelMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove monitoring for Volume Down key')); + let button = await driver.findComponent(ON.text('Remove monitoring for Volume Down key')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'CancelMonitor_002 end') + }) + + /** + * 添加音量下键的监听 + */ + it('ArkTSInputConsumerAPI_on_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'AddMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputconsumer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `CancelMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add monitoring for Volume Up key')); + let button = await driver.findComponent(ON.text('Add monitoring for Volume Up key')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'AddMonitor_002 end') + }) + + /** + * 添加音量下键的监听 + */ + it('ArkTSInputConsumerAPI_on_002', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'AddMonitor_002, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputconsumer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `CancelMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add monitoring for Volume Down key')); + let button = await driver.findComponent(ON.text('Add monitoring for Volume Down key')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'AddMonitor_002 end') + }) + }) +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/List.test.ets b/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/ohosTest/module.json5 b/input/ArkTSInputConsumer/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/input/ArkTSInputConsumer/entry/src/test/List.test.ets b/input/ArkTSInputConsumer/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/entry/src/test/LocalUnit.test.ets b/input/ArkTSInputConsumer/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/input/ArkTSInputConsumer/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/hvigor/hvigor-config.json5 b/input/ArkTSInputConsumer/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/input/ArkTSInputConsumer/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/input/ArkTSInputConsumer/hvigorfile.ts b/input/ArkTSInputConsumer/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/input/ArkTSInputConsumer/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTSInputConsumer/oh-package.json5 b/input/ArkTSInputConsumer/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd654848c4bea70abddc158d02b3057a0164413c --- /dev/null +++ b/input/ArkTSInputConsumer/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.23", + "@ohos/hamock": "1.0.0" + } +} diff --git a/input/ArkTSInputConsumer/ohosTest.md b/input/ArkTSInputConsumer/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..8d911b89de84fa6917a251fc7a28a4cb8f1eaffa --- /dev/null +++ b/input/ArkTSInputConsumer/ohosTest.md @@ -0,0 +1,16 @@ +# 按键拦截监听(ArkTS) + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|--------------|----------------|---------------------------------------------|--------------------------------------------------------------|------|------| +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 音量上键按键事件拦截监听 | 音量上键按键事件拦截监听开启 | 点击音量上键 | 弹窗显示**点击了音量键上**,音量不被调节 | 否 | Pass | +| 音量下键按键事件拦截监听 | 音量下键按键事件拦截监听开启 | 点击音量下键 | 弹窗显示**点击了音量键下**,音量不被调节 | 否 | Pass | +| 取消音量上键的拦截监听 | 音量上键按键事件拦截监听开启 | 点击**Remove monitoring for Volume Up key** | 弹窗显示**Successfully removed monitoring for Volume UP key!** | 是 | Pass | +| 取消音量下键的拦截监听 | 音量下键按键事件拦截监听开启 | 点击**Remove monitoring for Volume Down key** | 弹窗显示**Successfully removed monitoring for Volume Down key!** | 是 | Pass | +| 取消音量上键拦截监听 | 已取消音量上键的拦截监听 | 点击音量上键 | 无弹窗,音量增加 | 否 | Pass | +| 取消音量下键拦截监听 | 已取消音量下键的拦截监听 | 点击音量下键 | 无弹窗,音量减小 | 否 | Pass | +| 添加音量上键的拦截监听 | 无 | 点击**Add monitoring for Volume Up key** | 弹窗显示**Successfully added monitoring for Volume UP key!** | 是 | Pass | +| 添加音量下键的拦截监听 | 无 | 点击**Add monitoring for Volume Down key** | 弹窗显示**Successfully added monitoring for Volume Down key!** | 是 | Pass | + diff --git a/input/ArkTSInputConsumer/screenshot/inputConsumer.png b/input/ArkTSInputConsumer/screenshot/inputConsumer.png new file mode 100644 index 0000000000000000000000000000000000000000..f598470443a7d2c412a6adc516c79a7485c23a88 Binary files /dev/null and b/input/ArkTSInputConsumer/screenshot/inputConsumer.png differ diff --git a/input/ArkTSInputDevice/.gitignore b/input/ArkTSInputDevice/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/input/ArkTSInputDevice/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/input/ArkTSInputDevice/AppScope/app.json5 b/input/ArkTSInputDevice/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ef7b3c233b05903146e7577960f762961a860f88 --- /dev/null +++ b/input/ArkTSInputDevice/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.arktsinputdevice", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/input/ArkTSInputDevice/AppScope/resources/base/element/string.json b/input/ArkTSInputDevice/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..233d0c0bd4dae2a858111c82fdb63bc4f5c1143d --- /dev/null +++ b/input/ArkTSInputDevice/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ArkTSInputDevice" + } + ] +} diff --git a/input/ArkTSInputDevice/AppScope/resources/base/media/background.png b/input/ArkTSInputDevice/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTSInputDevice/AppScope/resources/base/media/background.png differ diff --git a/input/ArkTSInputDevice/AppScope/resources/base/media/foreground.png b/input/ArkTSInputDevice/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/input/ArkTSInputDevice/AppScope/resources/base/media/foreground.png differ diff --git a/input/ArkTSInputDevice/AppScope/resources/base/media/layered_image.json b/input/ArkTSInputDevice/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTSInputDevice/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/README_zh.md b/input/ArkTSInputDevice/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..84fe0ef2dd3bdac627e6ef933cde21872770535e --- /dev/null +++ b/input/ArkTSInputDevice/README_zh.md @@ -0,0 +1,64 @@ +# 物理键盘插入检测(ArkTS) + +## 介绍 + +本工程主要实现了对以下指南文档[输入设备开发指导](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/device/input/inputdevice-guidelines.md)中示例代码片段的工程化,通过该工程可以添加对物理键盘插入的检测。 + +## 效果预览 + +| ![](screenshot/inputDevice.png) | +|---------------------------------| + +使用说明: +1. 安装编译生成的hap包,在生成的应用中点击对应的按钮添加对物理键盘插入的检测。 +2. 进行物理键盘热拔插,页面会实时刷新设备的物理键盘连接状态。 +3. 进入"DocsSample/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/InputDeviceAbility.test.ets"文件,可以对本项目进行UI的自动化测试。 + +## 工程目录 + +``` +ArkTSInputDevice +├──entry/src/main +│ ├──ets +│ │ ├──entryability +| | ├──entrybackupability +│ │ └──pages +│ │ └──Index.ets // 示例代码 +| ├──resources + ├── ohosTest + │ ├── ets + │ │ └── test + │ │ └── InputDeviceAbility.test.ets // 自动化测试代码 +``` + +### 具体实现 + +1. 在[Index.ets](entry/src/main/ets/pages/Index.ets)文件中,获取设备列表以及监听设备热插拔。 +2. 在[InputDeviceAbility.test.ets](entry/src/ohosTest/ets/test/InputDeviceAbility.test.ets)文件中,通过自动化对获取设备列表以及监听设备热插拔进行测试。 + +## 相关权限 + +无。 + +## 依赖 + +不涉及。 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:RK3568等。 +2. 本示例支持API20版本SDK,版本号:6.0.0.36。 +3. 本示例已支持使DevEco Studio 5.1.1 Release (构建版本:5.1.1.840,构建 2025年9月20日)编译运行。 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/input/ArkTSInputDevice > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/input/ArkTSInputDevice/build-profile.json5 b/input/ArkTSInputDevice/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b4c76119a50cee21e3a9edbb58ebed7905e7c08e --- /dev/null +++ b/input/ArkTSInputDevice/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "targetSdkVersion": 20, + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/code-linter.json5 b/input/ArkTSInputDevice/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/input/ArkTSInputDevice/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/.gitignore b/input/ArkTSInputDevice/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/input/ArkTSInputDevice/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/build-profile.json5 b/input/ArkTSInputDevice/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f --- /dev/null +++ b/input/ArkTSInputDevice/entry/build-profile.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/hvigorfile.ts b/input/ArkTSInputDevice/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/input/ArkTSInputDevice/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/obfuscation-rules.txt b/input/ArkTSInputDevice/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/input/ArkTSInputDevice/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/oh-package.json5 b/input/ArkTSInputDevice/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/input/ArkTSInputDevice/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/input/ArkTSInputDevice/entry/src/main/ets/entryability/EntryAbility.ets b/input/ArkTSInputDevice/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/input/ArkTSInputDevice/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/ets/pages/Index.ets b/input/ArkTSInputDevice/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..a83c440c7ecdd3e03113aa304bc28b2ed102c520 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start input_device] +import { inputDevice } from '@kit.InputKit'; +import hilog from '@ohos.hilog'; + +const DOMAIN = 0x0000; + +@Entry +@Component +struct Index { + @State isPhysicalKeyboardExist: boolean = false; + @State message: string = "Click to obtain the device list and monitor device hot-plug events"; + keyBoards: Map = new Map(); + + // [StartExclude input_device] + // 结果展示 + @Builder + ResultDisplay() { + Column() { + Text(`The current physical keyboard connection status is: ${this.isPhysicalKeyboardExist}`) + .fontSize(14) + .width('100%') + .wordBreak(WordBreak.NORMAL) + .fontWeight(FontWeight.Medium) + .textAlign(TextAlign.Center) + .padding(12) + } + .width('100%') + .backgroundColor('#F5F5F5') + .borderRadius(8) + .margin({ top: 20, bottom: 20 }) + .padding(0) + } + + aboutToDisappear(): void { + inputDevice.off("change"); + } + + // [EndExclude input_device] + + build() { + RelativeContainer() { + Column() { + // [StartExclude input_device] + this.ResultDisplay() + // [EndExclude input_device] + + Text(this.message) + .onClick(() => { + try { + // 1.获取设备列表,判断是否有物理键盘连接 + inputDevice.getDeviceList().then(data => { + for (let i = 0; i < data.length; ++i) { + inputDevice.getKeyboardType(data[i]).then(type => { + if (type === inputDevice.KeyboardType.ALPHABETIC_KEYBOARD) { + // 物理键盘已连接 + this.isPhysicalKeyboardExist = true; + this.keyBoards.set(data[i], type); + } + }); + } + }); + // 2.监听设备热插拔 + inputDevice.on("change", (data) => { + hilog.info(DOMAIN, 'InputDevice', `Device event info: %{public}s`, JSON.stringify(data)); + inputDevice.getKeyboardType(data.deviceId).then((type) => { + hilog.info(DOMAIN, 'InputDevice', 'The keyboard type is: %{public}d', type); + if (type === inputDevice.KeyboardType.ALPHABETIC_KEYBOARD && data.type === 'add') { + // 物理键盘已插入 + this.isPhysicalKeyboardExist = true; + this.keyBoards.set(data.deviceId, type); + } + }); + if (this.keyBoards.get(data.deviceId) === inputDevice.KeyboardType.ALPHABETIC_KEYBOARD && + data.type === 'remove') { + // 物理键盘已拔掉 + this.isPhysicalKeyboardExist = false; + this.keyBoards.delete(data.deviceId); + } + }); + this.message = "Device monitoring enabled successfully" + } catch (error) { + hilog.error(DOMAIN, 'InputDevice', `Execute failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + this.message = `Failed to enable device monitoring. Click to retry. Error message:${JSON.stringify(error, + ["code", "message"])}` + } + }) + // [StartExclude input_device] + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Center) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.NORMAL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + // [EndExclude input_device] + } + // [StartExclude input_device] + .height('100%') + .width('80%') + .alignItems(HorizontalAlign.Center) + .position({ left: '10%', right: '10%' }) + .margin({ bottom: 200 }) + + // [EndExclude input_device] + } + } +} + +// [End input_device] diff --git a/input/ArkTSInputDevice/entry/src/main/module.json5 b/input/ArkTSInputDevice/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..476f4f508edb44dc9edfe115808545c33b284e0b --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/module.json5 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/element/color.json b/input/ArkTSInputDevice/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/element/float.json b/input/ArkTSInputDevice/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/element/string.json b/input/ArkTSInputDevice/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/media/background.png b/input/ArkTSInputDevice/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTSInputDevice/entry/src/main/resources/base/media/background.png differ diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/media/foreground.png b/input/ArkTSInputDevice/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/input/ArkTSInputDevice/entry/src/main/resources/base/media/foreground.png differ diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/media/layered_image.json b/input/ArkTSInputDevice/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/media/startIcon.png b/input/ArkTSInputDevice/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/input/ArkTSInputDevice/entry/src/main/resources/base/media/startIcon.png differ diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/profile/backup_config.json b/input/ArkTSInputDevice/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/main/resources/base/profile/main_pages.json b/input/ArkTSInputDevice/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/input/ArkTSInputDevice/entry/src/main/resources/dark/element/color.json b/input/ArkTSInputDevice/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/mock/mock-config.json5 b/input/ArkTSInputDevice/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/InputDeviceAbility.test.ets b/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/InputDeviceAbility.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7b17d90900a450195e7c713f261c65957d5419e5 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/InputDeviceAbility.test.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import hilog from '@ohos.hilog'; + +const TAG = '[Sample_ArkTSInputDeviceAPI]'; +const DOMAIN = 0xF811; +const BUNDLE = 'ArkTSInputDeviceAPI_'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + /** + * 打开应用 + */ + it('ArkTSInputDeviceAPI_StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputdevice', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Click to obtain the device list and monitor device hot-plug events')); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 获取设备列表并添加监听 + */ + it('ArkTSInputDeviceAPI_InputDevice_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'InputDevice_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktsinputdevice', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `InputDevice_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Click to obtain the device list and monitor device hot-plug events')); + let button = await driver.findComponent(ON.text('Click to obtain the device list and monitor device hot-plug events')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'InputDevice_001 end') + }) + }) +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/List.test.ets b/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..221380bfeea0f7cc19d046397b5e693c71fe47b3 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './InputDeviceAbility.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/ohosTest/module.json5 b/input/ArkTSInputDevice/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/input/ArkTSInputDevice/entry/src/test/List.test.ets b/input/ArkTSInputDevice/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/entry/src/test/LocalUnit.test.ets b/input/ArkTSInputDevice/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/input/ArkTSInputDevice/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/hvigor/hvigor-config.json5 b/input/ArkTSInputDevice/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/input/ArkTSInputDevice/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/input/ArkTSInputDevice/hvigorfile.ts b/input/ArkTSInputDevice/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/input/ArkTSInputDevice/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTSInputDevice/oh-package.json5 b/input/ArkTSInputDevice/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd654848c4bea70abddc158d02b3057a0164413c --- /dev/null +++ b/input/ArkTSInputDevice/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.23", + "@ohos/hamock": "1.0.0" + } +} diff --git a/input/ArkTSInputDevice/ohosTest.md b/input/ArkTSInputDevice/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..054852ce82b95ab79e6aa51feb28d98640a36efd --- /dev/null +++ b/input/ArkTSInputDevice/ohosTest.md @@ -0,0 +1,9 @@ +# 物理键盘插入检测(ArkTS) + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|------------|------------|------------------------|------------------|------|------| +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 添加物理键盘拔插监听 | 设备热拔插监听未开启 | 点击**Click to obtain the device list and monitor device hot-plug events** | 页面显示**Device monitoring enabled successfully** | 是 | Pass | + diff --git a/input/ArkTSInputDevice/screenshot/inputDevice.png b/input/ArkTSInputDevice/screenshot/inputDevice.png new file mode 100644 index 0000000000000000000000000000000000000000..7a0d9ec6be53626506525106cf09912db2a7168d Binary files /dev/null and b/input/ArkTSInputDevice/screenshot/inputDevice.png differ diff --git a/input/ArkTsPointer/.gitignore b/input/ArkTsPointer/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/input/ArkTsPointer/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/input/ArkTsPointer/AppScope/app.json5 b/input/ArkTsPointer/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4cf7a95b53007f6ef43cf44e5c69242fdbd56a0b --- /dev/null +++ b/input/ArkTsPointer/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.arktspointer", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/input/ArkTsPointer/AppScope/resources/base/element/string.json b/input/ArkTsPointer/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..8c9a89098285330355cae935d67d47c9a2264dfc --- /dev/null +++ b/input/ArkTsPointer/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ArkTsPointer" + } + ] +} diff --git a/input/ArkTsPointer/AppScope/resources/base/media/background.png b/input/ArkTsPointer/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTsPointer/AppScope/resources/base/media/background.png differ diff --git a/input/ArkTsPointer/AppScope/resources/base/media/foreground.png b/input/ArkTsPointer/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/input/ArkTsPointer/AppScope/resources/base/media/foreground.png differ diff --git a/input/ArkTsPointer/AppScope/resources/base/media/layered_image.json b/input/ArkTsPointer/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTsPointer/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/README_zh.md b/input/ArkTsPointer/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..417ac075da1bac322473e87251a70fd847325ff0 --- /dev/null +++ b/input/ArkTsPointer/README_zh.md @@ -0,0 +1,62 @@ +# 鼠标光标设置(ArkTS) + +## 介绍 + +本工程主要实现了对以下指南文档[鼠标光标开发指导](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/device/input/pointerstyle-guidelines.md) +中示例代码片段的工程化,通过该工程可以设置光标的隐藏和显示,设置光标样式为取色器样式和默认样式。 + +## 效果预览 + +| ![](screenshot/pointer.png) | +|-----------------------------| + +使用说明: + +1. 安装编译生成的hap包,打开应用。 +2. 点击对应按键显示和隐藏光标。 +3. 点击对应按钮设置光标的样式为取色器样式和默认样式。 +4. 进入"DocsSample/input/ArkTSPointer/entry/src/ohosTest/ets/test/Ability.test.ets"文件,可以对本项目进行UI的自动化测试。 + +## 工程目录 + +``` +ArkTSPointer +├──entry/src/main +│ ├──ets +│ │ ├──entryability +| | ├──entrybackupability +│ │ └──pages +│ │ └──Index.ets // 示例代码 +| ├──resources + ├── ohosTest + │ ├── ets + │ │ └── test + │ │ └── Ability.test.ets // 自动化测试代码 +``` + +## 相关权限 + +无。 + +## 依赖 + +不涉及。 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:RK3568等。 +2. 本示例支持API20版本SDK,版本号:6.0.0.36。 +3. 本示例已支持使DevEco Studio 5.1.1 Release (构建版本:5.1.1.840,构建 2025年9月20日)编译运行。 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/input/ArkTSPointer > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/input/ArkTsPointer/build-profile.json5 b/input/ArkTsPointer/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b4c76119a50cee21e3a9edbb58ebed7905e7c08e --- /dev/null +++ b/input/ArkTsPointer/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "targetSdkVersion": 20, + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/ArkTsPointer/code-linter.json5 b/input/ArkTsPointer/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/input/ArkTsPointer/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/.gitignore b/input/ArkTsPointer/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/input/ArkTsPointer/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/input/ArkTsPointer/entry/build-profile.json5 b/input/ArkTsPointer/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016faf39f8a65cf648bae246a53575510fe8b9f --- /dev/null +++ b/input/ArkTsPointer/entry/build-profile.json5 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/hvigorfile.ts b/input/ArkTsPointer/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/input/ArkTsPointer/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/obfuscation-rules.txt b/input/ArkTsPointer/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/input/ArkTsPointer/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/input/ArkTsPointer/entry/oh-package.json5 b/input/ArkTsPointer/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/input/ArkTsPointer/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/input/ArkTsPointer/entry/src/main/ets/entryability/EntryAbility.ets b/input/ArkTsPointer/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/input/ArkTsPointer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/ets/pages/Index.ets b/input/ArkTsPointer/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..47822e4672d4b8a24b8cd7f312dfecf2adec8d25 --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { pointer } from '@kit.InputKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { window } from '@kit.ArkUI'; +import hilog from '@ohos.hilog'; + +const DOMAIN = 0x0000; + +@Entry +@Component +struct Index { + build() { + RelativeContainer() { + Column() { + // [Start pointer_visible] + Text("Click to hide pointer") + .onClick(() => { + // 1.应用切换到全屏播放 + // 2.调用鼠标光标隐藏接口隐藏光标 + try { + pointer.setPointerVisible(false, (error: Error) => { + if (error) { + hilog.error(DOMAIN, 'Pointer', `Set pointer visible failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + return; + } + hilog.info(DOMAIN, 'Pointer', 'Set pointer visible success.'); + }); + } catch (error) { + hilog.error(DOMAIN, 'Pointer', `The mouse pointer hide attributes is failed. %{public}s`, + JSON.stringify(error, ["code", "message"])); + } + }) + // [StartExclude pointer_visible] + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.BREAK_ALL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + // [EndExclude pointer_visible] + + // 3.应用退出全屏播放 + // 4.调用鼠标光标显示接口显示光标 + Text("Click to display pointer") + .onClick(() => { + try { + pointer.setPointerVisible(true, (error: Error) => { + if (error) { + hilog.error(DOMAIN, 'Pointer', `Set pointer visible failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + return; + } + hilog.info(DOMAIN, 'Pointer', 'Set pointer visible success.'); + }); + } catch (error) { + hilog.error(DOMAIN, 'Pointer', `Set pointer visible failed, error: %{public}s`, + JSON.stringify(error, ["code", "message"])); + } + }) + // [StartExclude pointer_visible] + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.BREAK_ALL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + // [EndExclude pointer_visible] + // [End pointer_visible] + + // [Start pointer_style] + Text(`Click to set the mouse pointer style to the color picker style`) + .onClick(() => { + // 1.开发者使能取色功能 + // 2.调用窗口实例获取对应的窗口id + window.getLastWindow(this.getUIContext().getHostContext(), + (error: BusinessError, windowClass: window.Window) => { + if (error.code) { + hilog.error(DOMAIN, 'Pointer', 'Failed to obtain the top window. Cause: %{public}s', + JSON.stringify(error)); + return; + } + let windowId = windowClass.getWindowProperties().id; + if (windowId < 0) { + hilog.info(DOMAIN, 'Pointer', 'Invalid windowId'); + return; + } + try { + // 3.设置鼠标光标样式为取色器样式 + pointer.setPointerStyle(windowId, pointer.PointerStyle.COLOR_SUCKER).then(() => { + hilog.info(DOMAIN, 'Pointer', 'Successfully set mouse pointer style'); + }); + } catch (error) { + hilog.error(DOMAIN, 'Pointer', `Failed to set the pointer style, error=%{public}s, msg=%{public}s`, + JSON.stringify(error), error.message); + } + }); + }) + // [StartExclude pointer_style] + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.BREAK_ALL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + .wordBreak(WordBreak.NORMAL) + // [EndExclude pointer_style] + + + Text(`Click to set the mouse pointer style to default style`) + .onClick(() => { + // 4.取色结束 + window.getLastWindow(this.getUIContext().getHostContext(), + (error: BusinessError, windowClass: window.Window) => { + if (error.code) { + hilog.error(DOMAIN, 'Pointer', 'Failed to obtain the top window. Cause: %{public}s', + JSON.stringify(error)); + return; + } + let windowId = windowClass.getWindowProperties().id; + if (windowId < 0) { + hilog.info(DOMAIN, 'Pointer', 'Invalid windowId'); + return; + } + try { + // 5.设置鼠标光标样式为默认样式 + pointer.setPointerStyle(windowId, pointer.PointerStyle.DEFAULT).then(() => { + hilog.info(DOMAIN, 'Pointer', 'Successfully set mouse pointer style'); + }); + } catch (error) { + hilog.error(DOMAIN, 'Pointer', `Failed to set the pointer style, error=%{public}s, msg=%{public}s`, + JSON.stringify(error), error.message); + } + }); + }) + // [End pointer_style] + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.BREAK_ALL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + .wordBreak(WordBreak.NORMAL) + } + .height('100%') + .width('80%') + .alignItems(HorizontalAlign.Center) + .position({ left: '10%', right: '10%' }) + .margin({ bottom: 200 }) + } + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/module.json5 b/input/ArkTsPointer/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..476f4f508edb44dc9edfe115808545c33b284e0b --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/module.json5 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/resources/base/element/color.json b/input/ArkTsPointer/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/resources/base/element/float.json b/input/ArkTsPointer/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/input/ArkTsPointer/entry/src/main/resources/base/element/string.json b/input/ArkTsPointer/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/resources/base/media/background.png b/input/ArkTsPointer/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/ArkTsPointer/entry/src/main/resources/base/media/background.png differ diff --git a/input/ArkTsPointer/entry/src/main/resources/base/media/foreground.png b/input/ArkTsPointer/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/input/ArkTsPointer/entry/src/main/resources/base/media/foreground.png differ diff --git a/input/ArkTsPointer/entry/src/main/resources/base/media/layered_image.json b/input/ArkTsPointer/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/resources/base/media/startIcon.png b/input/ArkTsPointer/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/input/ArkTsPointer/entry/src/main/resources/base/media/startIcon.png differ diff --git a/input/ArkTsPointer/entry/src/main/resources/base/profile/backup_config.json b/input/ArkTsPointer/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/main/resources/base/profile/main_pages.json b/input/ArkTsPointer/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/input/ArkTsPointer/entry/src/main/resources/dark/element/color.json b/input/ArkTsPointer/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/input/ArkTsPointer/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/mock/mock-config.json5 b/input/ArkTsPointer/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/input/ArkTsPointer/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/ohosTest/ets/test/Ability.test.ets b/input/ArkTsPointer/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..ce6847fd92fd0ef6576b8c4b4f38c10cf1bc6c52 --- /dev/null +++ b/input/ArkTsPointer/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import hilog from '@ohos.hilog'; + +const TAG = '[Sample_ArkTSPointerAPI]'; +const DOMAIN = 0xF811; +const BUNDLE = 'ArkTSPointerAPI_'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + /** + * 打开应用 + */ + it('ArkTSPointerAPI_StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktspointer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Click to hide pointer')); + await driver.assertComponentExist(ON.text('Click to display pointer')); + await driver.assertComponentExist(ON.text('Click to set the mouse pointer style to the color picker style')); + await driver.assertComponentExist(ON.text('Click to set the mouse pointer style to default style')); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 隐藏光标 + */ + it('ArkTSPointerAPI_setPointerVisible_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerVisible_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktspointer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `setPointerVisible_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Click to hide pointer')); + let button = await driver.findComponent(ON.text('Click to hide pointer')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerVisible_001 end') + }) + + /** + * 显示光标 + */ + it('ArkTSPointerAPI_setPointerVisible_002', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerVisible_002, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktspointer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `setPointerVisible_002 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Click to display pointer')); + let button = await driver.findComponent(ON.text('Click to display pointer')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerVisible_002 end') + }) + + /** + * 设置鼠标光标样式为取色器样式 + */ + it('ArkTSPointerAPI_setPointerStyle_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerStyle_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktspointer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `setPointerStyle_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Click to set the mouse pointer style to the color picker style')); + let button = await driver.findComponent(ON.text('Click to set the mouse pointer style to the color picker style')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerStyle_001 end') + }) + + /** + * 设置设置鼠标光标样式为默认样式 + */ + it('ArkTSPointerAPI_setPointerStyle_002', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerStyle_002, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.arktspointer', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `setPointerStyle_002 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Click to set the mouse pointer style to default style')); + let button = await driver.findComponent(ON.text('Click to set the mouse pointer style to default style')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'setPointerStyle_002 end') + }) + }) +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/ohosTest/ets/test/List.test.ets b/input/ArkTsPointer/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/input/ArkTsPointer/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/ohosTest/module.json5 b/input/ArkTsPointer/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/input/ArkTsPointer/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/input/ArkTsPointer/entry/src/test/List.test.ets b/input/ArkTsPointer/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/input/ArkTsPointer/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/input/ArkTsPointer/entry/src/test/LocalUnit.test.ets b/input/ArkTsPointer/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/input/ArkTsPointer/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/input/ArkTsPointer/hvigor/hvigor-config.json5 b/input/ArkTsPointer/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/input/ArkTsPointer/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/input/ArkTsPointer/hvigorfile.ts b/input/ArkTsPointer/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/input/ArkTsPointer/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/ArkTsPointer/oh-package.json5 b/input/ArkTsPointer/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd654848c4bea70abddc158d02b3057a0164413c --- /dev/null +++ b/input/ArkTsPointer/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.23", + "@ohos/hamock": "1.0.0" + } +} diff --git a/input/ArkTsPointer/ohosTest.md b/input/ArkTsPointer/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..99032dab2072efadba1e07df1603a7ce1f4a27de --- /dev/null +++ b/input/ArkTsPointer/ohosTest.md @@ -0,0 +1,13 @@ +# 鼠标光标设置(ArkTS) + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|--------------|--------|------------------------|------------|------|------| +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 设置光标隐藏 | 位于首页 | 点击**Click to hide pointer** | 光标隐藏 | 是 | Pass | +| 设置光标显示 | 位于首页 | 点击**Click to display pointer** | 光标显示 | 是 | Pass | +| 设置光标样式为取色器样式 | 位于首页 | 点击**Click to set the mouse pointer style to the color picker style** | 光标样式为取色器样式 | 是 | Pass | +| 设置光标样式为默认样式 | 位于首页 | 点击**Click to set the mouse pointer style to default style** | 光表样式为默认样式 | 是 | Pass | + + diff --git a/input/ArkTsPointer/screenshot/pointer.png b/input/ArkTsPointer/screenshot/pointer.png new file mode 100644 index 0000000000000000000000000000000000000000..9defc5630143878fad2b7e0a59d9f48c9285b047 Binary files /dev/null and b/input/ArkTsPointer/screenshot/pointer.png differ diff --git a/input/NDKInputEventInterceptor/.gitignore b/input/NDKInputEventInterceptor/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/input/NDKInputEventInterceptor/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/AppScope/app.json5 b/input/NDKInputEventInterceptor/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c312441bf44ed90601a26e4cd9128d616c52528c --- /dev/null +++ b/input/NDKInputEventInterceptor/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.ndkinputeventinterceptor", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/input/NDKInputEventInterceptor/AppScope/resources/base/element/string.json b/input/NDKInputEventInterceptor/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a39e84f029fd515c58a4558aad216d928f48bbfa --- /dev/null +++ b/input/NDKInputEventInterceptor/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NDKInputEventInterceptor" + } + ] +} diff --git a/input/NDKInputEventInterceptor/AppScope/resources/base/media/background.png b/input/NDKInputEventInterceptor/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/NDKInputEventInterceptor/AppScope/resources/base/media/background.png differ diff --git a/input/NDKInputEventInterceptor/AppScope/resources/base/media/foreground.png b/input/NDKInputEventInterceptor/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/input/NDKInputEventInterceptor/AppScope/resources/base/media/foreground.png differ diff --git a/input/NDKInputEventInterceptor/AppScope/resources/base/media/layered_image.json b/input/NDKInputEventInterceptor/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/NDKInputEventInterceptor/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/README_zh.md b/input/NDKInputEventInterceptor/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..a1e6c2778ab2a8b063667e2d0b9f3d80986ce83b --- /dev/null +++ b/input/NDKInputEventInterceptor/README_zh.md @@ -0,0 +1,67 @@ +# 输入事件拦截(C/C++) + +## 介绍 + +本工程主要实现了对以下指南文档[事件拦截开发指导](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/device/input/interceptor-guidelines.md) +中示例代码片段的工程化,通过该工程可以添加和移除对按键、输入事件(鼠标、触屏和轴事件)的拦截。 + +## 效果预览 + +| ![](screenshot/InputEventInterceptor.png) | +|-------------------------------------------| + +使用说明: + +1. 安装编译生成的hap包,打开应用。 +2. 点击对应按键添加和移除按键事件拦截,添加后使用键盘在输入框输入文本,输入被拦截并在页面实时显示拦截到的按键事件。 +3. 点击对应按键添加和移除输入事件拦截,添加后使用鼠标、使用触屏功能、在触摸板进行捏合操作和使用鼠标滚轮时,输入被拦截并在页面实时显示监听到的输入事件。 +4. 30秒后自动取消输入事件拦截。 +5. 进入"DocsSample/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/Ability.test.ets"文件,可以对本项目进行UI的自动化测试。 + +## 工程目录 + +``` +NDKInputEventInterceptor +├──entry/src/main +│ ├──cpp // C++代码区 +│ │ ├──CMakeLists.txt // CMake配置文件 +│ │ ├──napi_init.cpp // 示例代码 +| | ├──types +| | | ├──libentry +| | | | ├──Index.d.ts +| | | | ├──oh-package.json5 +│ ├──ets // ets代码区 +│ │ ├──entryability +│ │ │ ├──EntryAbility.ts +| | ├──entrybackupability +| | | ├──EntryBackupAbility.ets +│ │ ├──pages +│ │ ├──Index.ets // 主界面 +``` + +## 相关权限 + +ohos.permission.INTERCEPT_INPUT_EVENT + +## 依赖 + +不涉及。 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:Phone、Tablet。 +2. 本示例支持API20版本SDK,版本号:6.0.0.36。 +3. 本示例已支持使DevEco Studio 5.1.1 Release (构建版本:5.1.1.840,构建 2025年9月20日)编译运行。 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/input/NDKInputEventInterceptor > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/input/NDKInputEventInterceptor/build-profile.json5 b/input/NDKInputEventInterceptor/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b4c76119a50cee21e3a9edbb58ebed7905e7c08e --- /dev/null +++ b/input/NDKInputEventInterceptor/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "targetSdkVersion": 20, + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/code-linter.json5 b/input/NDKInputEventInterceptor/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/input/NDKInputEventInterceptor/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/.gitignore b/input/NDKInputEventInterceptor/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/build-profile.json5 b/input/NDKInputEventInterceptor/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d18577b4d93c6e5152fbd8cdfd1bd50e143fc976 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/build-profile.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ], + "buildOption":{ + "externalNativeOptions": { + "abiFilters": [ + "x86_64", + "arm64-v8a", + ] + } + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/hvigorfile.ts b/input/NDKInputEventInterceptor/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/obfuscation-rules.txt b/input/NDKInputEventInterceptor/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/oh-package-lock.json5 b/input/NDKInputEventInterceptor/entry/oh-package-lock.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/input/NDKInputEventInterceptor/entry/oh-package.json5 b/input/NDKInputEventInterceptor/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5b21e253af246edab8b6ef4f10938f4417e8bc25 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/cpp/CMakeLists.txt b/input/NDKInputEventInterceptor/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3bdc597fbc61c2dcda5314d14d35524afbd5d6a5 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(NDKInputEventInterceptor) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED napi_init.cpp) +target_link_libraries(entry PUBLIC libace_napi.z.so libohinput.so) \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/cpp/napi_init.cpp b/input/NDKInputEventInterceptor/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7703cfe52572e4cceffd5ff038e98628605f75ad --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "napi/native_api.h" +#include "multimodalinput/oh_input_manager.h" + +std::string g_value = ""; +napi_ref g_callback_ref = nullptr; +napi_env g_env = nullptr; + +napi_value OnChange(napi_env env, napi_callback_info info) +{ + g_env = env; + size_t argc = 1; + napi_value args[1]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // 保存 callback 引用 + napi_create_reference(env, args[0], 1, &g_callback_ref); + return nullptr; +} + +void NotifyValueChange() +{ + if (g_callback_ref == nullptr || g_env == nullptr) { + return; + } + + napi_value callback; + napi_get_reference_value(g_env, g_callback_ref, &callback); + + // callback的输入参数 + napi_value event; + napi_create_object(g_env, &event); + + napi_value value_js; + napi_create_string_utf8(g_env, g_value.c_str(), g_value.length(), &value_js); + napi_set_named_property(g_env, event, "value", value_js); + napi_value global; + napi_get_global(g_env, &global); + napi_call_function(g_env, global, callback, 1, &event, nullptr); +} + +// [Start key_event_interceptor] +struct KeyEvent { + int32_t action; + int32_t keyCode; + int64_t actionTime { -1 }; +}; + +//定义按键事件回调函数 +void OnKeyEventCallback(const Input_KeyEvent* keyEvent) +{ + KeyEvent event; + //Input_KeyEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + event.action = OH_Input_GetKeyEventAction(keyEvent); + event.keyCode = OH_Input_GetKeyEventKeyCode(keyEvent); + event.actionTime = OH_Input_GetKeyEventActionTime(keyEvent); + // [StartExclude key_event_interceptor] + std::ostringstream oss; + oss << "Key event detected action:" << event.action + << " keyCode: " << event.keyCode + << " actionTime: " << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude key_event_interceptor] +} + +static napi_value AddKeyEventInterceptor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddKeyEventInterceptor(OnKeyEventCallback, nullptr); + // [StartExclude key_event_interceptor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Key event interceptor added successfully, return " + std::to_string(ret); + } else { + message = "Key event interceptor added failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude key_event_interceptor] +} + +static napi_value RemoveKeyEventInterceptor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveKeyEventInterceptor(); + // [StartExclude key_event_interceptor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Key event interceptor removed successfully, return " + std::to_string(ret); + } else { + message = "Key event interceptor removed failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude key_event_interceptor] +} +// [End key_event_interceptor] + +// [Start input_event_interceptor] +struct MouseEvent { + int32_t action; + int32_t displayX; + int32_t displayY; + int32_t button { -1 }; + int32_t axisType { -1 }; + float axisValue { 0.0f }; + int64_t actionTime { -1 }; +}; + +struct TouchEvent { + int32_t action; + int32_t id; + int32_t displayX; + int32_t displayY; + int64_t actionTime { -1 }; +}; + +struct AxisEvent { + int32_t axisAction; + float displayX; + float displayY; + std::map axisValues; + int64_t actionTime { -1 }; + int32_t sourceType; + int32_t axisEventType { -1 }; +}; + +//定义鼠标事件回调函数 +void OnMouseEventCallback(const Input_MouseEvent* mouseEvent) +{ + MouseEvent event; + //Input_MouseEvent的生命周期仅在回调函数内,出了回调函数会被销毁 + event.action = OH_Input_GetMouseEventAction(mouseEvent); + event.displayX = OH_Input_GetMouseEventDisplayX(mouseEvent); + event.displayY = OH_Input_GetMouseEventDisplayY(mouseEvent); + event.button = OH_Input_GetMouseEventButton(mouseEvent); + event.axisType = OH_Input_GetMouseEventAxisType(mouseEvent); + event.axisValue = OH_Input_GetMouseEventAxisValue(mouseEvent); + event.actionTime = OH_Input_GetMouseEventActionTime(mouseEvent); + // [StartExclude input_event_interceptor] + std::ostringstream oss; + oss << "Mouse event detected action:" << event.action + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " button:" << event.button + << " axisType:" << event.axisType + << " axisValue:" << event.axisValue + << " actionTime:" << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude input_event_interceptor] +} + +//定义触摸事件回调函数 +void OnTouchEventCallback(const Input_TouchEvent* touchEvent) +{ + TouchEvent event; + //Input_TouchEvent的生命周期仅在回调函数内,出了回调函数会被销毁 + event.action = OH_Input_GetTouchEventAction(touchEvent); + event.id = OH_Input_GetTouchEventFingerId(touchEvent); + event.displayX = OH_Input_GetTouchEventDisplayX(touchEvent); + event.displayY = OH_Input_GetTouchEventDisplayY(touchEvent); + event.actionTime = OH_Input_GetTouchEventActionTime(touchEvent); + // [StartExclude input_event_interceptor] + std::ostringstream oss; + oss << "Touch event detected action:" << event.action + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " id:" << event.id + << " actionTime:" << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude input_event_interceptor] +} + +//定义轴事件回调函数 +void OnAxisEventCallback(const Input_AxisEvent* axisEvent) +{ + AxisEvent event; + + //Input_AxisEvent的生命周期仅在回调函数内,出了回调函数会被销毁 + InputEvent_AxisAction action; + Input_Result ret = OH_Input_GetAxisEventAction(axisEvent, &action); + event.axisAction = action; + ret = OH_Input_GetAxisEventDisplayX(axisEvent, &event.displayX); + ret = OH_Input_GetAxisEventDisplayY(axisEvent, &event.displayY); + ret = OH_Input_GetAxisEventActionTime(axisEvent, &event.actionTime); + InputEvent_SourceType sourceType; + ret = OH_Input_GetAxisEventSourceType(axisEvent, &sourceType); + event.sourceType = sourceType; + InputEvent_AxisEventType axisEventType; + ret = OH_Input_GetAxisEventType(axisEvent, &axisEventType); + event.axisEventType = axisEventType; + if (event.axisEventType == AXIS_EVENT_TYPE_PINCH) { + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_PINCH, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_PINCH, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_ROTATE, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_ROTATE, value)); + } else if (event.axisEventType == AXIS_EVENT_TYPE_SCROLL) { + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_VERTICAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_VERTICAL, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_HORIZONTAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_HORIZONTAL, value)); + } + // [StartExclude input_event_interceptor] + std::ostringstream oss; + oss << "Axis event detected axisAction:" << event.axisAction + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " sourceType:" << event.sourceType + << " actionTime:" << event.actionTime + << " axisEventType:" << event.axisEventType + << "\n axisValues:"; + for (const auto& pair : event.axisValues) { + oss << " axis" << pair.first << "=" << pair.second; + } + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude input_event_interceptor] +} + +//输入事件回调函数结构体 +Input_InterceptorEventCallback g_eventCallback; + +static napi_value AddEventInterceptor(napi_env env, napi_callback_info info) +{ + //设置鼠标事件回调函数 + g_eventCallback.mouseCallback = OnMouseEventCallback; + //设置触摸事件回调函数 + g_eventCallback.touchCallback = OnTouchEventCallback; + //设置轴事件回调函数 + g_eventCallback.axisCallback = OnAxisEventCallback; + Input_Result ret = OH_Input_AddInputEventInterceptor(&g_eventCallback, nullptr); + // [StartExclude input_event_interceptor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Input event interception added successfully, return code: " + std::to_string(ret); + } else { + message = "Failed to add input event interception, return code: " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude input_event_interceptor] +} + +static napi_value RemoveEventInterceptor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveInputEventInterceptor(); + // [StartExclude input_event_interceptor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Input event interception removed successfully, return code: " + std::to_string(ret); + } else { + message = "Failed to remove input event interception, return code: " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude input_event_interceptor] +} +// [End input_event_interceptor] + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "onChange", nullptr, OnChange, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "addKeyEventInterceptor", nullptr, AddKeyEventInterceptor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "removeKeyEventInterceptor", nullptr, RemoveKeyEventInterceptor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "addEventInterceptor", nullptr, AddEventInterceptor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "removeEventInterceptor", nullptr, RemoveEventInterceptor, nullptr, nullptr, nullptr, napi_default, nullptr }, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/Index.d.ts b/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..58bb617a98c65355986eec1eff9c72c614d4bbe4 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface ValueChangeEvent { + value: string; +} + +export declare const onChange: (callback: (event: ValueChangeEvent) => void) => void; +export const addKeyEventInterceptor: () => string; +export const removeKeyEventInterceptor: () => string; +export const addEventInterceptor: () => string; +export const removeEventInterceptor: () => string; \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/oh-package.json5 b/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..77052c679533e45a066030a9fc21cdbf9cbcf995 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/ets/entryability/EntryAbility.ets b/input/NDKInputEventInterceptor/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/input/NDKInputEventInterceptor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/ets/pages/Index.ets b/input/NDKInputEventInterceptor/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..a5c96cd4825403e798526e6786a5a5c3e6d264c3 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import testNapi from 'libentry.so'; + +const DOMAIN = 0x0000; + +@Component +export struct ResultDisplay { + @Prop result: string + + build() { + Column() { + Text(this.result) + .fontSize(14) + .width('100%') + .wordBreak(WordBreak.NORMAL) + .fontWeight(FontWeight.Medium) + .textAlign(TextAlign.Start) + .padding(12) + } + .width('100%') + .backgroundColor('#F5F5F5') + .borderRadius(8) + .margin({ top: 20, bottom: 20 }) + .padding(0) + } +} + +@Entry +@Component +struct Index { + @State result: string = ''; + + @Builder + ApiMethodItem(title: string, onClick: () => void) { + Text(title) + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.NORMAL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + .onClick(onClick) + } + + aboutToAppear(): void { + if (testNapi) { + testNapi.onChange((event: testNapi.ValueChangeEvent) => { + this.result = event.value; + }); + } else { + hilog.error(DOMAIN, 'NDKInputEventInterceptor', 'testNapi is undefined'); + this.result = 'Native plugin failed to load'; + } + } + + build() { + Scroll() { + Column() { + ResultDisplay({ result: this.result }) + + Column() { + TextInput({ placeholder: 'input' }) + .type(InputType.Normal) + .width('80%') + .height(50) + .margin(10) + } + + this.ApiMethodItem( + "Add key event interceptor", + () => { + try { + this.result = testNapi.addKeyEventInterceptor() + } catch (e) { + this.result = `Add key event interceptor, error:${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove key event interceptor", + () => { + try { + this.result = testNapi.removeKeyEventInterceptor() + } catch (e) { + this.result = `Remove key event interceptor, error:${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add input event interceptor. Input event include: mouse event, touch event, and axis event", + () => { + try { + this.result = `${testNapi.addEventInterceptor()}, input event interception will be automatically canceled after 30 seconds.` + setTimeout(() => { + try { + this.result = testNapi.removeEventInterceptor() + } catch (e) { + this.result = `Automatic removal of input event interception failed: ${JSON.stringify(e)}`; + } + }, 30000); + } catch (e) { + this.result = `Automatic removal of input event interception failed: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + `Remove input event interceptor. include: mouse event, touch event, and axis event`, + () => { + try { + this.result = testNapi.removeEventInterceptor() + } catch (e) { + this.result = `Failed to remove input event interception: ${JSON.stringify(e)}` + } + } + ) + + } + .height('100%') + .width('80%') + .alignItems(HorizontalAlign.Center) + .margin({ left: '10%', right: '10%' }) + .margin({ bottom: 200 }) + } + .width('100%') + .height('100%') + .scrollable(ScrollDirection.Vertical) + .scrollBar(BarState.On) + .scrollBarColor('#888888') + .scrollBarWidth(8) + .edgeEffect(EdgeEffect.Spring) + } +} diff --git a/input/NDKInputEventInterceptor/entry/src/main/module.json5 b/input/NDKInputEventInterceptor/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..82a47a3d85715a1fc91fafe03328e5993d8d2346 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/module.json5 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "requestPermissions": [ + { + "name": "ohos.permission.INTERCEPT_INPUT_EVENT" + } + ], + "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.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/color.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/float.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/string.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/background.png b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/background.png differ diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/foreground.png b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/foreground.png differ diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/layered_image.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/startIcon.png b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/input/NDKInputEventInterceptor/entry/src/main/resources/base/media/startIcon.png differ diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/backup_config.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/main_pages.json b/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/input/NDKInputEventInterceptor/entry/src/main/resources/dark/element/color.json b/input/NDKInputEventInterceptor/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/mock/Libentry.mock.ets b/input/NDKInputEventInterceptor/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..eebf1ed910f6a8f2a9e7e565aa71b179b7b8b537 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/mock/mock-config.json5 b/input/NDKInputEventInterceptor/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..98b0ae79f0090e1fc381d54c959fb32c9f7563f4 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/mock/mock-config.json5 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/Ability.test.ets b/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7e190179b1154c6882f424afea558575e97843b3 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import hilog from '@ohos.hilog'; + +const TAG = '[Sample_NDKInputEventInterceptorAPI]'; +const DOMAIN = 0xF811; +const BUNDLE = 'NDKInputEventInterceptorAPI_'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + /** + * 打开应用 + */ + it('NDKInputEventInterceptorAPI_StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventinterceptor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Add key event interceptor')); + await driver.assertComponentExist(ON.text('Remove key event interceptor')); + await driver.assertComponentExist(ON.text('Add input event interceptor. Input event include: mouse event, touch event, and axis event')); + await driver.assertComponentExist(ON.text('Remove input event interceptor. include: mouse event, touch event, and axis event')); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 添加按键事件拦截 + */ + it('NDKInputEventInterceptorAPI_addKeyEventInterceptor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addKeyEventInterceptor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventinterceptor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addKeyEventInterceptor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Add key event interceptor')); + let button = await driver.findComponent(ON.text('Add key event interceptor')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addKeyEventInterceptor_001 end') + }) + + /** + * 移除按键事件拦截 + */ + it('NDKInputEventInterceptorAPI_removeKeyEventInterceptor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeKeyEventInterceptor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventinterceptor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeKeyEventInterceptor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Remove key event interceptor')); + let button = await driver.findComponent(ON.text('Remove key event interceptor')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeKeyEventInterceptor_001 end') + }) + + /** + * 添加输入事件拦截 + */ + it('NDKInputEventInterceptorAPI_addEventInterceptor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addEventInterceptor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventinterceptor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addEventInterceptor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Add input event interceptor. Input event include: mouse event, touch event, and axis event')); + let button = await driver.findComponent(ON.text('Add input event interceptor. Input event include: mouse event, touch event, and axis event')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addEventInterceptor_001 end') + }) + + /** + * 添加输入事件拦截 + */ + it('NDKInputEventInterceptorAPI_removeEventInterceptor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeEventInterceptor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventinterceptor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeEventInterceptor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + await driver.assertComponentExist(ON.text('Remove input event interceptor. include: mouse event, touch event, and axis event')); + let button = await driver.findComponent(ON.text('Remove input event interceptor. include: mouse event, touch event, and axis event')); + await button.click(); + await driver.delayMs(3000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeEventInterceptor_001 end') + }) + }) +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/List.test.ets b/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/ohosTest/module.json5 b/input/NDKInputEventInterceptor/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/input/NDKInputEventInterceptor/entry/src/test/List.test.ets b/input/NDKInputEventInterceptor/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/entry/src/test/LocalUnit.test.ets b/input/NDKInputEventInterceptor/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/input/NDKInputEventInterceptor/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/hvigor/hvigor-config.json5 b/input/NDKInputEventInterceptor/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/input/NDKInputEventInterceptor/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/input/NDKInputEventInterceptor/hvigorfile.ts b/input/NDKInputEventInterceptor/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/input/NDKInputEventInterceptor/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/NDKInputEventInterceptor/oh-package.json5 b/input/NDKInputEventInterceptor/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd654848c4bea70abddc158d02b3057a0164413c --- /dev/null +++ b/input/NDKInputEventInterceptor/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.23", + "@ohos/hamock": "1.0.0" + } +} diff --git a/input/NDKInputEventInterceptor/ohosTest.md b/input/NDKInputEventInterceptor/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..90f1329436521189b34f1251a1aa2babb00b6797 --- /dev/null +++ b/input/NDKInputEventInterceptor/ohosTest.md @@ -0,0 +1,26 @@ +# 输入事件拦截(ArkTS) + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|------------|-----------|-------------------------------------|--------------------------------------------------|------|------| +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 添加按键事件拦截 | 未添加按键事件拦截 | 点击**Add key event interceptor** | 页面显示**Key event interceptor added successfully, return 0** | 是 | Pass | +| 按键事件拦截 | 已添加按键事件拦截 | 在输入框输入文本 | 输入被拦截,页面实时显示拦截到的按键事件 | 否 | Pass | +| 移除按键事件拦截 | 已添加按键事件拦截 | 点击**Remove key event interceptor** | 页面显示**Key event interceptor removed successfully, return 0** | 是 | Pass | +| 按键事件不拦截 | 已移除按键事件拦截 | 在输入框输入文本 | 输入不被拦截,页面不显示拦截到的按键事件 | 否 | Pass | +| 添加输入事件拦截 | 未添加输入事件拦截 | 点击**Add input event interceptor. Input event include: mouse event, touch event, and axis event** | 页面显示**Input event interceptor added successfully, return code: 0. Input event interceptor will be automatically canceled after 30 seconds**,30秒后取消拦截 | 是 | Pass | +| 鼠标输入事件拦截 | 已添加输入事件拦截 | 使用鼠标 | 输入被拦截,页面实时显示拦截到的鼠标事件 | 否 | Pass | +| 触摸输入事件拦截 | 已添加输入事件拦截 | 使用触屏功能 | 输入被拦截,页面实时显示拦截到的触摸事件 | 否 | Pass | +| 捏合轴输入事件拦截 | 已添加输入事件拦截 | 在触摸板进行捏合操作 | 输入被拦截,页面实时显示拦截到的捏合轴事件 | 否 | Pass | +| 滚轮轴输入事件拦截 | 已添加输入事件拦截 | 使用鼠标滚轮 | 输入被拦截,页面实时显示拦截到的滚轮轴事件 | 否 | Pass | +| 移除输入事件拦截 | 已添加输入事件拦截 | 点击**Remove input event interceptor. Input event include: mouse event, touch event, and axis event** | 页面显示接口调用结果 | 是 | Pass | +| 鼠标输入事件不拦截 | 已移除输入事件拦截 | 使用鼠标 | 输入不被拦截,页面不显示拦截到的鼠标事件 | 否 | Pass | +| 触摸输入事件不拦截 | 已移除输入事件拦截 | 使用触屏功能 | 输入不被拦截,页面不显示拦截到的鼠标事件 | 否 | Pass | +| 捏合轴输入事件不拦截 | 已移除输入事件拦截 | 在触摸板进行捏合操作 | 输入不被拦截,页面不显示拦截到的鼠标事件 | 否 | Pass | +| 滚轮轴输入事件不拦截 | 已移除输入事件拦截 | 使用鼠标滚轮 | 输入不被拦截,页面不显示拦截到的鼠标事件 | 否 | Pass | + + + + + diff --git a/input/NDKInputEventInterceptor/screenshot/InputEventInterceptor.png b/input/NDKInputEventInterceptor/screenshot/InputEventInterceptor.png new file mode 100644 index 0000000000000000000000000000000000000000..3eacba6f208fb1d425a8cf4986e922359d890cf1 Binary files /dev/null and b/input/NDKInputEventInterceptor/screenshot/InputEventInterceptor.png differ diff --git a/input/NDKInputEventMonitor/.gitignore b/input/NDKInputEventMonitor/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/input/NDKInputEventMonitor/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/input/NDKInputEventMonitor/AppScope/app.json5 b/input/NDKInputEventMonitor/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..26aa6364788ac39221bef439b28febc8afb84a97 --- /dev/null +++ b/input/NDKInputEventMonitor/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "bundleName": "com.example.ndkinputeventmonitor", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/input/NDKInputEventMonitor/AppScope/resources/base/element/string.json b/input/NDKInputEventMonitor/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..616e1b60e1c000e6e0ea4f565a6cb8b9ee00bced --- /dev/null +++ b/input/NDKInputEventMonitor/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NDKInputEventMonitor" + } + ] +} diff --git a/input/NDKInputEventMonitor/AppScope/resources/base/media/background.png b/input/NDKInputEventMonitor/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/NDKInputEventMonitor/AppScope/resources/base/media/background.png differ diff --git a/input/NDKInputEventMonitor/AppScope/resources/base/media/foreground.png b/input/NDKInputEventMonitor/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/input/NDKInputEventMonitor/AppScope/resources/base/media/foreground.png differ diff --git a/input/NDKInputEventMonitor/AppScope/resources/base/media/layered_image.json b/input/NDKInputEventMonitor/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/NDKInputEventMonitor/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/README_zh.md b/input/NDKInputEventMonitor/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..6efd90fddff4fa97eb4936752c7276f47ea682fb --- /dev/null +++ b/input/NDKInputEventMonitor/README_zh.md @@ -0,0 +1,70 @@ +# 输入事件监听(C/C++) + +## 介绍 + +本工程主要实现了对以下指南文档[输入监听开发指导](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/device/input/inputmonitor-guidelines-sys.md) +中示例代码片段的工程化,通过该工程可以添加和移除对于按键、输入事件(鼠标、触屏和轴事件)的监听。 + +## 效果预览 + +| ![](screenshot/inputMonitor.png) | +|----------------------------------| + +使用说明: + +1. 安装编译生成的hap包,打开应用。 +2. 点击对应按键添加和移除按键事件监听,添加后使用键盘,页面会实时显示监听到的按键事件。 +3. 点击对应按键添加和移除鼠标事件监听,添加后使用鼠标,页面会实时显示监听到的鼠标事件。 +4. 点击对应按键添加和移除触摸事件监听,添加后进行触屏动作,页面会实时显示监听到的触摸事件。 +5. 点击对应按键添加和移除轴事件监听,添加后在触摸板进行捏合动作或滚动鼠标滚轮,页面会实时显示监听到的捏合轴事件、滚轮轴事件。 +6. 点击对应按键添加和移除捏合轴事件监听,添加后在触摸板进行捏合动作,页面会实时显示监听到的捏合轴事件事件。 +7. 点击对应按键添加和移除滚轮轴事件监听,添加后滚动鼠标滚轮,页面会实时显示监听到的滚轮轴事件事件。 +8. 进入"DocsSample/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/Ability.test.ets"文件,可以对本项目进行UI的自动化测试。 + +## 工程目录 + +``` +NDKInputEventMonitor +├──entry/src/main +│ ├──cpp // C++代码区 +│ │ ├──CMakeLists.txt // CMake配置文件 +│ │ ├──napi_init.cpp // 示例代码 +| | ├──types +| | | ├──libentry +| | | | ├──Index.d.ts +| | | | ├──oh-package.json5 +│ ├──ets // ets代码区 +│ │ ├──entryability +│ │ │ ├──EntryAbility.ts +| | ├──entrybackupability +| | | ├──EntryBackupAbility.ets +│ │ ├──pages +│ │ ├──Index.ets // 主界面 +``` + +## 相关权限 + +ohos.permission.INPUT_MONITORING + +## 依赖 + +不涉及。 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:Phone、Tablet。 +2. 本示例支持API20版本SDK,版本号:6.0.0.36。 +3. 本示例已支持使DevEco Studio 5.1.1 Release (构建版本:5.1.1.840,构建 2025年9月20日)编译运行。 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/input/NDKInputEventMonitor > .git/info/sparse-checkout +git remote add origin https://gitcode.com/openharmony/applications_app_samples.git +git pull origin master +``` + diff --git a/input/NDKInputEventMonitor/build-profile.json5 b/input/NDKInputEventMonitor/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b4c76119a50cee21e3a9edbb58ebed7905e7c08e --- /dev/null +++ b/input/NDKInputEventMonitor/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "app": { + "signingConfigs": [ + ], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 20, + "compatibleSdkVersion": 20, + "targetSdkVersion": 20, + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/code-linter.json5 b/input/NDKInputEventMonitor/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/input/NDKInputEventMonitor/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/.gitignore b/input/NDKInputEventMonitor/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/build-profile.json5 b/input/NDKInputEventMonitor/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..219a6f173302fe1c22cc10134094a77e4c423a24 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/build-profile.json5 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "apiType": "stageMode", + "buildOption": { + "resOptions": { + "copyCodeResource": { + "enable": false + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/hvigorfile.ts b/input/NDKInputEventMonitor/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/obfuscation-rules.txt b/input/NDKInputEventMonitor/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/input/NDKInputEventMonitor/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/oh-package.json5 b/input/NDKInputEventMonitor/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5b21e253af246edab8b6ef4f10938f4417e8bc25 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/cpp/CMakeLists.txt b/input/NDKInputEventMonitor/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..4406878cdeb9724b8793029399c52a9e4a683779 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(NDKInputEventMonitor) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +add_library(entry SHARED napi_init.cpp) +target_link_libraries(entry PUBLIC libace_napi.z.so libohinput.so) \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/cpp/napi_init.cpp b/input/NDKInputEventMonitor/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abf9ff5b1de2341b6428f67122327351f1a04625 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "napi/native_api.h" +#include "multimodalinput/oh_input_manager.h" + +std::string g_value = ""; +napi_ref g_callback_ref = nullptr; +napi_env g_env = nullptr; + +napi_value OnChange(napi_env env, napi_callback_info info) +{ + g_env = env; + size_t argc = 1; + napi_value args[1]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + // 保存 callback 引用 + napi_create_reference(env, args[0], 1, &g_callback_ref); + return nullptr; +} + +void NotifyValueChange() +{ + if (g_callback_ref == nullptr || g_env == nullptr) { + return; + } + + napi_value callback; + napi_get_reference_value(g_env, g_callback_ref, &callback); + + // callback的输入参数 + napi_value event; + napi_create_object(g_env, &event); + + napi_value value_js; + napi_create_string_utf8(g_env, g_value.c_str(), g_value.length(), &value_js); + napi_set_named_property(g_env, event, "value", value_js); + napi_value global; + napi_get_global(g_env, &global); + napi_call_function(g_env, global, callback, 1, &event, nullptr); +} + +// [Start key_event_monitor] +struct KeyEvent { + int32_t action; + int32_t keyCode; + int64_t actionTime { -1 }; +}; + +//定义按键事件回调函数 +void OnKeyEventCallback(const Input_KeyEvent* keyEvent) +{ + KeyEvent event; + //Input_KeyEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + event.action = OH_Input_GetKeyEventAction(keyEvent); + event.keyCode = OH_Input_GetKeyEventKeyCode(keyEvent); + event.actionTime = OH_Input_GetKeyEventActionTime(keyEvent); + // [StartExclude key_event_monitor] + std::ostringstream oss; + oss << "Key event detected action:" << event.action + << " keyCode: " << event.keyCode + << " actionTime:" << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude key_event_monitor] +} + +static napi_value AddKeyEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddKeyEventMonitor(OnKeyEventCallback); + // [StartExclude key_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Add key event monitor successfully, return " + std::to_string(ret); + } else { + message = "Add key event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude key_event_monitor] +} + +static napi_value RemoveKeyEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveKeyEventMonitor(OnKeyEventCallback); + // [StartExclude key_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Remove key event monitor successfully, return " + std::to_string(ret); + } else { + message = "Remove key event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude key_event_monitor] +} +// [End key_event_monitor] + +// [Start mouse_event_monitor] +struct MouseEvent { + int32_t action; + int32_t displayX; + int32_t displayY; + int32_t button { -1 }; + int32_t axisType { -1 }; + float axisValue { 0.0f }; + int64_t actionTime { -1 }; +}; + +//定义鼠标事件回调函数 +void OnMouseEventCallback(const Input_MouseEvent* mouseEvent) +{ + MouseEvent event; + //Input_MouseEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + event.action = OH_Input_GetMouseEventAction(mouseEvent); + event.displayX = OH_Input_GetMouseEventDisplayX(mouseEvent); + event.displayY = OH_Input_GetMouseEventDisplayY(mouseEvent); + event.button = OH_Input_GetMouseEventButton(mouseEvent); + event.axisType = OH_Input_GetMouseEventAxisType(mouseEvent); + event.axisValue = OH_Input_GetMouseEventAxisValue(mouseEvent); + event.actionTime = OH_Input_GetMouseEventActionTime(mouseEvent); + // [StartExclude mouse_event_monitor] + std::ostringstream oss; + oss << "Mouse event detected action:" << event.action + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " button:" << event.button + << " axisType:" << event.axisType + << " axisValue:" << event.axisValue + << " actionTime:" << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude mouse_event_monitor] +} + +static napi_value AddMouseEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddMouseEventMonitor(OnMouseEventCallback); + // [StartExclude mouse_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Mouse event monitor added successfully, return code: " + std::to_string(ret); + } else { + message = "Failed to add mouse event monitor, return code: " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude mouse_event_monitor] +} + +static napi_value RemoveMouseEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveMouseEventMonitor(OnMouseEventCallback); + // [StartExclude mouse_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Remove mouse event monitor successfully, return code: " + std::to_string(ret); + } else { + message = "Remove mouse event monitor failed, return code: " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude mouse_event_monitor] +} +// [End mouse_event_monitor] + +// [Start touch_event_monitor] +struct TouchEvent { + int32_t action; + int32_t id; + int32_t displayX; + int32_t displayY; + int64_t actionTime { -1 }; +}; + +void OnTouchEventCallback(const Input_TouchEvent* touchEvent) +{ + TouchEvent event; + //Input_TouchEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + event.action = OH_Input_GetTouchEventAction(touchEvent); + event.id = OH_Input_GetTouchEventFingerId(touchEvent); + event.displayX = OH_Input_GetTouchEventDisplayX(touchEvent); + event.displayY = OH_Input_GetTouchEventDisplayY(touchEvent); + event.actionTime = OH_Input_GetTouchEventActionTime(touchEvent); + // [StartExclude touch_event_monitor] + std::ostringstream oss; + oss << "Touch event detected action:" << event.action + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " id:" << event.id + << " actionTime:" << event.actionTime; + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude touch_event_monitor] +} + +static napi_value AddTouchEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddTouchEventMonitor(OnTouchEventCallback); + // [StartExclude touch_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Touch event monitor added successfully, return code:" + std::to_string(ret); + } else { + message = "Failed to add touch event monitor, return code: " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude touch_event_monitor] +} + +static napi_value RemoveTouchEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveTouchEventMonitor(OnTouchEventCallback); + // [StartExclude touch_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Remove touch event monitor successfully, return " + std::to_string(ret); + } else { + message = "Remove touch event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude touch_event_monitor] +} +// [End touch_event_monitor] + +// [Start axis_event_monitor] +struct AxisEvent { + int32_t axisAction; + float displayX; + float displayY; + std::map axisValues; + int64_t actionTime { -1 }; + int32_t sourceType; + int32_t axisEventType { -1 }; +}; + +void OnAllAxisEventCallback(const Input_AxisEvent* axisEvent) +{ + AxisEvent event; + //Input_AxisEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + InputEvent_AxisAction action = static_cast(0); + Input_Result ret = OH_Input_GetAxisEventAction(axisEvent, &action); + event.axisAction = action; + ret = OH_Input_GetAxisEventDisplayX(axisEvent, &event.displayX); + ret = OH_Input_GetAxisEventDisplayY(axisEvent, &event.displayY); + ret = OH_Input_GetAxisEventActionTime(axisEvent, &event.actionTime); + InputEvent_SourceType sourceType = static_cast(0); + ret = OH_Input_GetAxisEventSourceType(axisEvent, &sourceType); + event.sourceType = sourceType; + InputEvent_AxisEventType axisEventType = static_cast(-1); + ret = OH_Input_GetAxisEventType(axisEvent, &axisEventType); + event.axisEventType = axisEventType; + if (event.axisEventType == AXIS_EVENT_TYPE_PINCH) { + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_PINCH, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_PINCH, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_ROTATE, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_ROTATE, value)); + } else if (event.axisEventType == AXIS_EVENT_TYPE_SCROLL) { + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_VERTICAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_VERTICAL, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_HORIZONTAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_HORIZONTAL, value)); + } + // [StartExclude axis_event_monitor] + std::ostringstream oss; + oss << "Axis event detected axisAction:" << event.axisAction + << " displayX:" << event.displayX + << " displayY:" << event.displayY + << " sourceType:" << event.sourceType + << " actionTime:" << event.actionTime + << " axisEventType:" << event.axisEventType + << "\n axisValues:"; + for (const auto& pair : event.axisValues) { + oss << " axis" << pair.first << "=" << pair.second; + } + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude axis_event_monitor] +} + +//定义捏合类型轴事件回调函数 +void OnPinchAxisEventCallback(const Input_AxisEvent* axisEvent) +{ + AxisEvent event; + //Input_AxisEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + InputEvent_AxisAction action = static_cast(0); + Input_Result ret = OH_Input_GetAxisEventAction(axisEvent, &action); + event.axisAction = action; + ret = OH_Input_GetAxisEventDisplayX(axisEvent, &event.displayX); + ret = OH_Input_GetAxisEventDisplayY(axisEvent, &event.displayY); + ret = OH_Input_GetAxisEventActionTime(axisEvent, &event.actionTime); + InputEvent_SourceType sourceType = static_cast(0); + ret = OH_Input_GetAxisEventSourceType(axisEvent, &sourceType); + event.sourceType = sourceType; + InputEvent_AxisEventType axisEventType = static_cast(-1); + ret = OH_Input_GetAxisEventType(axisEvent, &axisEventType); + event.axisEventType = axisEventType; + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_PINCH, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_PINCH, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_ROTATE, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_ROTATE, value)); + // [StartExclude axis_event_monitor] + std::ostringstream oss; + oss << "Pinch axis event detected axisAction:" << event.axisAction + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " sourceType:" << event.sourceType + << " actionTime:" << event.actionTime + << " axisEventType:" << event.axisEventType + << "\n axisValues:"; + for (const auto& pair : event.axisValues) { + oss << " axis" << pair.first << "=" << pair.second; + } + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude axis_event_monitor] +} + +void OnScrollAxisEventCallback(const Input_AxisEvent* axisEvent) +{ + AxisEvent event; + //Input_AxisEvent的生命周期仅限于回调函数内,回调函数执行完毕后会被自动销毁 + InputEvent_AxisAction action = static_cast(0); + Input_Result ret = OH_Input_GetAxisEventAction(axisEvent, &action); + event.axisAction = action; + ret = OH_Input_GetAxisEventDisplayX(axisEvent, &event.displayX); + ret = OH_Input_GetAxisEventDisplayY(axisEvent, &event.displayY); + ret = OH_Input_GetAxisEventActionTime(axisEvent, &event.actionTime); + InputEvent_SourceType sourceType = static_cast(0); + ret = OH_Input_GetAxisEventSourceType(axisEvent, &sourceType); + event.sourceType = sourceType; + InputEvent_AxisEventType axisEventType = static_cast(-1); + ret = OH_Input_GetAxisEventType(axisEvent, &axisEventType); + event.axisEventType = axisEventType; + double value = 0; + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_VERTICAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_VERTICAL, value)); + ret = OH_Input_GetAxisEventAxisValue(axisEvent, AXIS_TYPE_SCROLL_HORIZONTAL, &value); + event.axisValues.insert(std::make_pair(AXIS_TYPE_SCROLL_HORIZONTAL, value)); + // [StartExclude axis_event_monitor] + std::ostringstream oss; + oss << "Scroll axis event detected axisAction:" << event.axisAction + << " displayX: " << event.displayX + << " displayY:" << event.displayY + << " sourceType:" << event.sourceType + << " actionTime:" << event.actionTime + << " axisEventType:" << event.axisEventType + << "\n axisValues:"; + for (const auto& pair : event.axisValues) { + oss << " axis" << pair.first << "=" << pair.second; + } + g_value = oss.str(); + NotifyValueChange(); + // [EndExclude axis_event_monitor] +} + +static napi_value AddAxisEventMonitorForAll(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddAxisEventMonitorForAll(OnAllAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Add axis event monitor successfully, return " + std::to_string(ret); + } else { + message = "Add axis event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} + +static napi_value RemoveAxisEventMonitorForAll(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveAxisEventMonitorForAll(OnAllAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Remove axis event monitor successfully, return " + std::to_string(ret); + } else { + message = "Remove axis event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} + +static napi_value AddPinchAxisEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddAxisEventMonitor(AXIS_EVENT_TYPE_PINCH, OnPinchAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Add pinch axis event monitor successfully, return " + std::to_string(ret); + } else { + message = "Add pinch axis event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} + +static napi_value RemovePinchAxisEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveAxisEventMonitor(AXIS_EVENT_TYPE_PINCH, OnPinchAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Remove pinch axis event monitor successfully, return " + std::to_string(ret); + } else { + message = "Remove pinch axis event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} + +static napi_value AddScrollAxisEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_AddAxisEventMonitor(AXIS_EVENT_TYPE_SCROLL, OnScrollAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Add scroll axis event monitor successfully, return " + std::to_string(ret); + } else { + message = "Add scroll axis event monitor failed, return " + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} + +static napi_value RemoveScrollAxisEventMonitor(napi_env env, napi_callback_info info) +{ + Input_Result ret = OH_Input_RemoveAxisEventMonitor(AXIS_EVENT_TYPE_SCROLL, OnScrollAxisEventCallback); + // [StartExclude axis_event_monitor] + std::string message = ""; + if (ret == INPUT_SUCCESS) { + message = "Mouse event listener removed successfully, return code:" + std::to_string(ret); + } else { + message = "Failed to remove mouse event listener, return code:" + std::to_string(ret); + } + napi_value result; + napi_create_string_utf8(env, message.c_str(), message.size(), &result); + return result; + // [EndExclude axis_event_monitor] +} +// [End axis_event_monitor] + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "onChange", nullptr, OnChange, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "addKeyEventMonitor", nullptr, AddKeyEventMonitor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "removeKeyEventMonitor", nullptr, RemoveKeyEventMonitor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "addMouseEventMonitor", nullptr, AddMouseEventMonitor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "removeMouseEventMonitor", nullptr, RemoveMouseEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "addTouchEventMonitor", nullptr, AddTouchEventMonitor, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "removeTouchEventMonitor", nullptr, RemoveTouchEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "addAxisEventMonitorForAll", nullptr, AddAxisEventMonitorForAll, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "removeAxisEventMonitorForAll", nullptr, RemoveAxisEventMonitorForAll, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "addPinchAxisEventMonitor", nullptr, AddPinchAxisEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "removePinchAxisEventMonitor", nullptr, RemovePinchAxisEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "addScrollAxisEventMonitor", nullptr, AddScrollAxisEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + { "removeScrollAxisEventMonitor", nullptr, RemoveScrollAxisEventMonitor, nullptr, nullptr, nullptr, + napi_default, nullptr }, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/Index.d.ts b/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..9330376126714adbc419b682bd0e5705fdd0631f --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/Index.d.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface ValueChangeEvent { + value: string; +} + +export declare const onChange: (callback: (event: ValueChangeEvent) => void) => void; +export const addKeyEventMonitor: () => string; +export const removeKeyEventMonitor: () => string; +export const addMouseEventMonitor: () => string; +export const removeMouseEventMonitor: () => string; +export const addTouchEventMonitor: () => string; +export const removeTouchEventMonitor: () => string; + +export const addAxisEventMonitorForAll: () => string; +export const removeAxisEventMonitorForAll: () => string; +export const addPinchAxisEventMonitor: () => string; +export const removePinchAxisEventMonitor: () => string; +export const addScrollAxisEventMonitor: () => string; +export const removeScrollAxisEventMonitor: () => string; \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/oh-package.json5 b/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..77052c679533e45a066030a9fc21cdbf9cbcf995 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/ets/entryability/EntryAbility.ets b/input/NDKInputEventMonitor/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..62f53acbc95e5be7985f8fb1fe2db591cea260bd --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + try { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } catch (err) { + hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err)); + } + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/input/NDKInputEventMonitor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..0a97e21bd7a15599af76a806695860ff1eb0ebfe --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/ets/pages/Index.ets b/input/NDKInputEventMonitor/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..40ee02a66caf5118b7c1cca6a302cfa4428b804f --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import testNapi from 'libentry.so'; + +const DOMAIN = 0x0000; + +@Component +export struct ResultDisplay { + @Prop result: string + + build() { + Column() { + Text(this.result) + .fontSize(14) + .width('100%') + .wordBreak(WordBreak.NORMAL) + .fontWeight(FontWeight.Medium) + .textAlign(TextAlign.Start) + .padding(12) + } + .width('100%') + .backgroundColor('#F5F5F5') + .borderRadius(8) + .margin({ top: 20, bottom: 20 }) + .padding(0) + } +} + +@Entry +@Component +struct Index { + @State result: string = ''; + + @Builder + ApiMethodItem(title: string, onClick: () => void) { + Text(title) + .height('auto') + .width('100%') + .fontSize(13) + .fontWeight(FontWeight.Bold) + .fontColor('#0A59F7') + .textAlign(TextAlign.Start) + .margin({ top: 8, bottom: 8 }) + .lineHeight(20) + .wordBreak(WordBreak.NORMAL) + .maxLines(2) + .backgroundColor('#F7F9FC') + .borderRadius(4) + .padding(8) + .onClick(onClick) + } + + aboutToAppear(): void { + if (testNapi) { + testNapi.onChange((event: testNapi.ValueChangeEvent) => { + this.result = event.value; + }); + } else { + hilog.error(DOMAIN, 'NDKInputEventMonitor', 'testNapi is undefined'); + this.result = 'Native plugin failed to load'; + } + } + + build() { + Scroll() { + Column() { + ResultDisplay({ result: this.result }) + + this.ApiMethodItem( + "Add key event monitor", + () => { + try { + this.result = testNapi.addKeyEventMonitor() + } catch (e) { + this.result = `Add key event monitor, error:${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove key event monitor", + () => { + try { + this.result = testNapi.removeKeyEventMonitor() + } catch (e) { + this.result = `Remove key event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add mouse event monitor", + () => { + try { + this.result = testNapi.addMouseEventMonitor() + } catch (e) { + this.result = `Add mouse event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove mouse event monitor", + () => { + try { + this.result = testNapi.removeMouseEventMonitor() + } catch (e) { + this.result = `Remove mouse event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add touch event monitor", + () => { + try { + this.result = testNapi.addTouchEventMonitor() + } catch (e) { + this.result = `Add touch event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove touch event monitor", + () => { + try { + this.result = testNapi.removeTouchEventMonitor() + } catch (e) { + this.result = `Remove touch event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add axis event monitor", + () => { + try { + this.result = testNapi.addAxisEventMonitorForAll() + } catch (e) { + this.result = `Add axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove axis event monitor", + () => { + try { + this.result = testNapi.removeAxisEventMonitorForAll() + } catch (e) { + this.result = `Remove axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add pinch axis event monitor", + () => { + try { + this.result = testNapi.addPinchAxisEventMonitor() + } catch (e) { + this.result = `Add axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove pinch axis event monitor", + () => { + try { + this.result = testNapi.removePinchAxisEventMonitor() + } catch (e) { + this.result = `Remove axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Add scroll axis event monitor", + () => { + try { + this.result = testNapi.addScrollAxisEventMonitor() + } catch (e) { + this.result = `Add scroll axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + this.ApiMethodItem( + "Remove scroll axis event monitor", + () => { + try { + this.result = testNapi.removeScrollAxisEventMonitor() + } catch (e) { + this.result = `Remove scroll axis event monitor, error: ${JSON.stringify(e)}` + } + } + ) + + } + .height('100%') + .width('80%') + .alignItems(HorizontalAlign.Center) + .margin({ left: '10%', right: '10%' }) + .margin({ bottom: 200 }) + } + .width('100%') + .height('100%') + .scrollable(ScrollDirection.Vertical) + .scrollBar(BarState.On) + .scrollBarColor('#888888') + .scrollBarWidth(8) + .edgeEffect(EdgeEffect.Spring) + } +} diff --git a/input/NDKInputEventMonitor/entry/src/main/module.json5 b/input/NDKInputEventMonitor/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f37d3523c0684bc9d3414c46008487f7010ff438 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/module.json5 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.INPUT_MONITORING" + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/element/color.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/element/float.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/element/string.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/media/background.png b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/background.png differ diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/media/foreground.png b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/foreground.png differ diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/media/layered_image.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/media/startIcon.png b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/input/NDKInputEventMonitor/entry/src/main/resources/base/media/startIcon.png differ diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/backup_config.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/main_pages.json b/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/input/NDKInputEventMonitor/entry/src/main/resources/dark/element/color.json b/input/NDKInputEventMonitor/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/mock/Libentry.mock.ets b/input/NDKInputEventMonitor/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..eebf1ed910f6a8f2a9e7e565aa71b179b7b8b537 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/mock/Libentry.mock.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const NativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default NativeMock; \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/mock/mock-config.json5 b/input/NDKInputEventMonitor/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..98b0ae79f0090e1fc381d54c959fb32c9f7563f4 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/mock/mock-config.json5 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/Ability.test.ets b/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..053ad26e4ebde538df7ed9c621b9d6d1c1dd6daf --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { describe, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import hilog from '@ohos.hilog'; + +const TAG = '[Sample_NDKInputEventMonitor]'; +const DOMAIN = 0xF811; +const BUNDLE = 'NDKInputEventMonitor'; + + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + + /** + * 打开应用 + */ + it('NDKInputEventMonitorAPI_StartAbility_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add key event monitor')); + await driver.assertComponentExist(ON.text('Remove key event monitor')); + await driver.assertComponentExist(ON.text('Add mouse event monitor')); + await driver.assertComponentExist(ON.text('Remove mouse event monitor')); + await driver.assertComponentExist(ON.text('Add touch event monitor')); + await driver.assertComponentExist(ON.text('Remove touch event monitor')); + await driver.assertComponentExist(ON.text('Add axis event monitor')); + await driver.assertComponentExist(ON.text('Remove axis event monitor')); + await driver.assertComponentExist(ON.text('Add pinch axis event monitor')); + await driver.assertComponentExist(ON.text('Remove pinch axis event monitor')); + await driver.assertComponentExist(ON.text('Add scroll axis event monitor')); + await driver.assertComponentExist(ON.text('Remove scroll axis event monitor')); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') + }) + + /** + * 添加按键事件监听 + */ + it('NDKInputEventMonitorAPI_addKeyEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addKeyEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addKeyEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add key event monitor')); + let button = await driver.findComponent(ON.text('Add key event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addKeyEventMonitor_001 end') + }) + + /** + * 移除按键事件监听 + */ + it('NDKInputEventMonitorAPI_removeKeyEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeKeyEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeKeyEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add key event monitor')); + let button = await driver.findComponent(ON.text('Add key event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeKeyEventMonitor_001 end') + }) + + /** + * 添加鼠标事件监听 + */ + it('NDKInputEventMonitorAPI_addMouseEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addMouseEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addMouseEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add mouse event monitor')); + let button = await driver.findComponent(ON.text('Add mouse event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addMouseEventMonitor_001 end') + }) + + /** + * 移除鼠标事件监听 + */ + it('NDKInputEventMonitorAPI_removeMouseEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeMouseEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeMouseEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove mouse event monitor')); + let button = await driver.findComponent(ON.text('Remove mouse event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeMouseEventMonitor_001 end') + }) + + /** + * 添加触摸事件监听 + */ + it('NDKInputEventMonitorAPI_addTouchEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addTouchEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addTouchEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add touch event monitor')); + let button = await driver.findComponent(ON.text('Add touch event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addTouchEventMonitor_001 end') + }) + + /** + * 移除触摸事件监听 + */ + it('NDKInputEventMonitorAPI_removeTouchEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeTouchEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeTouchEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove touch event monitor')); + let button = await driver.findComponent(ON.text('Remove touch event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeTouchEventMonitor_001 end') + }) + + /** + * 添加轴事件监听 + */ + it('NDKInputEventMonitorAPI_addAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add axis event monitor')); + let button = await driver.findComponent(ON.text('Add axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addAxisEventMonitor_001 end') + }) + + /** + * 移除轴事件监听 + */ + it('NDKInputEventMonitorAPI_removeAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove axis event monitor')); + let button = await driver.findComponent(ON.text('Remove axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeAxisEventMonitor_001 end') + }) + + /** + * 添加捏合轴事件监听 + */ + it('NDKInputEventMonitorAPI_addPinchAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addPinchAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addPinchAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add pinch axis event monitor')); + let button = await driver.findComponent(ON.text('Add pinch axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addPinchAxisEventMonitor_001 end') + }) + + /** + * 移除捏合轴事件监听 + */ + it('NDKInputEventMonitorAPI_removePinchAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removePinchAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removePinchAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove pinch axis event monitor')); + let button = await driver.findComponent(ON.text('Remove pinch axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removePinchAxisEventMonitor_001 end') + }) + + /** + * 添加滚轮轴事件监听 + */ + it('NDKInputEventMonitorAPI_addScrollAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'addScrollAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `addScrollAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Add scroll axis event monitor')); + let button = await driver.findComponent(ON.text('Add scroll axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'addScrollhAxisEventMonitor_001 end') + }) + + /** + * 移除滚轮轴事件监听 + */ + it('NDKInputEventMonitorAPI_removeScrollAxisEventMonitor_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + 'removeScrollAxisEventMonitor_001, begin'); + let driver = Driver.create(); + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + try { + await abilityDelegator.startAbility({ + bundleName: 'com.example.ndkinputeventmonitor', + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.info(DOMAIN, TAG, BUNDLE + `removeScrollAxisEventMonitor_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(1000); + await driver.assertComponentExist(ON.text('Remove scroll axis event monitor')); + let button = await driver.findComponent(ON.text('Remove scroll axis event monitor')); + await button.click(); + await driver.delayMs(1000); + done(); + hilog.info(DOMAIN, TAG, BUNDLE + 'removeScrollhAxisEventMonitor_001 end') + }) + + }) +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/List.test.ets b/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/ohosTest/module.json5 b/input/NDKInputEventMonitor/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/ohosTest/module.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/input/NDKInputEventMonitor/entry/src/test/List.test.ets b/input/NDKInputEventMonitor/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/entry/src/test/LocalUnit.test.ets b/input/NDKInputEventMonitor/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/input/NDKInputEventMonitor/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/hvigor/hvigor-config.json5 b/input/NDKInputEventMonitor/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/input/NDKInputEventMonitor/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/input/NDKInputEventMonitor/hvigorfile.ts b/input/NDKInputEventMonitor/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/input/NDKInputEventMonitor/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { 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. */ +} \ No newline at end of file diff --git a/input/NDKInputEventMonitor/oh-package.json5 b/input/NDKInputEventMonitor/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..cd654848c4bea70abddc158d02b3057a0164413c --- /dev/null +++ b/input/NDKInputEventMonitor/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +{ + "modelVersion": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.23", + "@ohos/hamock": "1.0.0" + } +} diff --git a/input/NDKInputEventMonitor/ohosTest.md b/input/NDKInputEventMonitor/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..392f101018ee37b76889b3d5cec66f900957bcdb --- /dev/null +++ b/input/NDKInputEventMonitor/ohosTest.md @@ -0,0 +1,35 @@ +# 输入事件监听(ArkTS) + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|-----------|------------|-------------------|---------------------------|------|------| +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 添加按键事件监听 | 未添加按键事件监听 | 点击**Add key event monitor** | 页面显示**Add key event monitor successfully, return 0** | 是 | Pass | +| 按键事件监听 | 已添加按键事件监听 | 使用按键 | 页面实时显示监听到的按键事件 | 否 | Pass | +| 移除按键事件监听 | 已添加按键事件监听 | 点击**Remove key event monitor** | 页面显示**Remove key event monitor successfully, return 0** | 是 | Pass | +| 按键事件不监听 | 已移除按键事件监听 | 使用按键 | 页面不显示按键事件 | 否 | Pass | +| 添加鼠标事件监听 | 未添加鼠标事件监听 | 点击**Add mouse event monitor** | 页面显示**Add mouse event monitor successfully, return 0** | 是 | Pass | +| 鼠标事件监听 | 已添加鼠标事件监听 | 使用鼠标 | 页面实时显示监听到的鼠标事件 | 否 | Pass | +| 移除鼠标事件监听 | 已添加鼠标事件监听 | 点击**Remove mouse event monitor** | 页面显示**Remove mouse event monitor successfully, return 0** | 是 | Pass | +| 鼠标事件不监听 | 已移除鼠标事件监听 | 使用鼠标 | 页面不显示鼠标事件 | 否 | Pass | +| 添加触摸事件监听 | 未添加触摸事件监听 | 点击**Add touch event monitor** | 页面显示**Add touch event monitor successfully, return 0** | 是 | Pass | +| 触摸事件监听 | 已添加触摸事件监听 | 使用触屏功能 | 页面实时显示监听到的触摸事件 | 否 | Pass | +| 移除触摸事件监听 | 已添加触摸事件监听 | 点击**Remove touch event monitor** | 页面显示**Remove touch event monitor successfully, return 0** | 是 | Pass | +| 触摸事件不监听 | 已移除触摸事件监听 | 使用触屏功能 | 页面不显示触摸事件 | 否 | Pass | +| 添加轴事件监听 | 未添加轴事件监听 | 点击**Add axis event monitor** | 页面显示**Add axis event monitor successfully, return 0** | 是 | Pass | +| 轴事件监听 | 已添加轴事件监听 | 在触摸板进行捏合动作或滚动鼠标滚轮 | 页面实时显示监听到的轴事件 | 否 | Pass | +| 移除轴事件监听 | 已添加轴事件监听 | 点击**Remove axis event monitor** | 页面显示**Remove axis event monitor successfully, return 0** | 是 | Pass | +| 轴事件不监听 | 已移除轴事件监听 | 在触摸板进行捏合动作或滚动鼠标滚轮 | 页面不显示轴事件 | 否 | Pass | +| 添加捏合轴事件监听 | 未添加捏合轴事件监听 | 点击**Add pinch axis event monitor** | 页面显示**Add pinch axis event monitor successfully, return 0** | 是 | Pass | +| 捏合轴事件监听 | 已添加捏合轴事件监听 | 在触摸板进行捏合动作 | 页面实时显示监听到的捏合轴事件 | 否 | Pass | +| 移除捏合轴事件监听 | 已添加捏合轴事件监听 | 点击**Remove pinch axis event monitor** | 页面显示**Remove pinch axis event monitor successfully, return 0** | 是 | Pass | +| 捏合轴事件不监听 | 已移除捏合轴事件监听 | 在触摸板进行捏合动作 | 页面不显示捏合轴事件 | 否 | Pass | +| 添加滚动轴事件监听 | 未添加滚动轴事件监听 | 点击**Add scroll axis event monitor** | 页面显示**Add scroll axis event monitor successfully, return 0** | 是 | Pass | +| 滚动轴事件监听 | 已添加滚动轴事件监听 | 滚动鼠标滚轮 | 页面实时显示监听到的滚动轴事件 | 否 | Pass | +| 移除滚动轴事件监听 | 已添加滚动轴事件监听 | 点击**Remove scroll axis event monitor** | 页面显示**Remove scroll axis event monitor successfully, return 0** | 是 | Pass | +| 滚动轴事件不监听 | 已移除滚动轴事件监听 | 滚动鼠标滚轮 | 页面不显示捏合轴事件 | 否 | Pass | + + + + diff --git a/input/NDKInputEventMonitor/screenshot/inputMonitor.png b/input/NDKInputEventMonitor/screenshot/inputMonitor.png new file mode 100644 index 0000000000000000000000000000000000000000..582075859ac641fc34567f976afe4adf62bd0db1 Binary files /dev/null and b/input/NDKInputEventMonitor/screenshot/inputMonitor.png differ