diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/.gitignore b/ConnectivityKit/Bluetooth/SerialCommunication/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/.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/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/app.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..2f23a8125eba63644dd59f3fe5c38e34af3e7192 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.serialcommunication", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/element/string.json b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f7c89bfc2123d0cb53c842637d6dbd97c7ec3d55 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "SerialCommunication" + } + ] +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/media/app_icon.png b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ConnectivityKit/Bluetooth/SerialCommunication/AppScope/resources/base/media/app_icon.png differ diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/README.md b/ConnectivityKit/Bluetooth/SerialCommunication/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8776066e678b3da7def02aeef556ba762a4cf4d8 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/README.md @@ -0,0 +1,90 @@ +# 串行通信开发指导 + +### 介绍 + +本示例为开发指南中[蓝牙服务开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/Readme-CN.md)章节中**传输数据开发指导***示例代码的完整工程,该工程中展示的代码详细描述可查如下链接: + +[传输数据开发指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/spp-development-guide.md) + +### 效果预览 +|Serial Communication| +|-------| +| | + +### 使用说明 + +1. 启动应用,弹出申请蓝牙权限的弹窗,点击允许,打卡设备的蓝牙功能。 +2. 按照格式输入deviceId和uuid。 +3. 点击listenSocket创建服务器监听Socket。 +4. 点击ServerConnect,socket等待客户端连接,连接成功返回clientId,弹出弹窗提示。 +5. 点击connectDevice,连接对端设备。 +6. 点击writeData,向客户端写入数据。 +7. 点击subscribeEvent,订阅读请求事件。 +8. 点击subscribeEvent,取消订阅读请求事件。 +9. 点击closeServer,关闭服务。 +10. 单击closeClient,关闭客户端。 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +| |---EntryAbility.ets +|---entrybackupability +| |---EntryBackupAbility.ets +|---pages +| |---Index.ets // 应用主页面 +``` + +### 具体实现 + +#### 服务端向客户端写入数据 + +1. import需要的socket模块。 +2. 需要SystemCapability.Communication.Bluetooth.Core系统能力。 +3. 创开启设备蓝牙。 +4. 创建服务端socket,返回serverId。 +5. 服务端等待客户端连接,返回clientId。 +6. 服务端向客户端写入数据。 +7. (可选)服务端订阅客户端写入的数据。 +8. 注销服务端socket。 +9. 注销客户端socket。 +10. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md). + +#### 通过socket连接对端设备 + +1. import需要的socket模块。 +2. 需要SystemCapability.Communication.Bluetooth.Core系统能力。 +3. 开启设备蓝牙。 +4. 开启ble扫描,获取对端设备mac地址。 +5. 连接对端设备。 +6. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md). + +### 相关权限 + +[ohos.permission.ACCESS_BLUETOOTH](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all-user.md#ohospermissionaccess_bluetooth) + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ConnectivityKit/Bluetooth/SerialCommunication/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/build-profile.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fb5a1ab654ae6715a0ab69a31900ad26dcf2487f --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "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/ConnectivityKit/Bluetooth/SerialCommunication/code-linter.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/.gitignore b/ConnectivityKit/Bluetooth/SerialCommunication/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/build-profile.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/hvigorfile.ts b/ConnectivityKit/Bluetooth/SerialCommunication/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/obfuscation-rules.txt b/ConnectivityKit/Bluetooth/SerialCommunication/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/oh-package.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/common/ToastReport.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/common/ToastReport.ets new file mode 100644 index 0000000000000000000000000000000000000000..80c12c4a9c04c5a82e2ed4e2278f2eceee52c93f --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/common/ToastReport.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { promptAction } from '@kit.ArkUI' + +export class ToastReport { + public showResult(message: string) { + promptAction.showToast({ + message: message, + duration: 2000, + showMode: promptAction.ToastShowMode.DEFAULT, + bottom: 80 + }) + } +} + +let toastReport = new ToastReport(); + +export default toastReport as ToastReport; \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c3ac9ef7691afaed75b57159c9f757ab0f65208 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,83 @@ +/* + * 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 from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl'; +import { BusinessError } from '@ohos.base'; + +const permissions: Permissions[] = ['ohos.permission.ACCESS_BLUETOOTH']; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + let context: Context = this.context; + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); + // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 + + atManager.requestPermissionsFromUser(context, permissions).then((data: PermissionRequestResult) => { + let grantStatus: number[] = data.authResults; + let length: number = grantStatus.length; + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // 用户授权,可以继续访问目标操作 + } else { + // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 + return; + } + } + // 授权成功 + }).catch((err: BusinessError) => { + console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); + }) + + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/pages/Index.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..540edc86a450de848ea7f068671ea19d93600a30 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,262 @@ +/* + * 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 { socket } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ToastReport } from '../common/ToastReport'; +import util from '@ohos.util'; + +const TAG: string = 'SerialCommunication'; +let encoder = new util.TextEncoder(); + +@Entry +@Component +struct serialCommunication { + @State serverNumber: number = 0; + @State clientNumber: number = 1; + @State deviceId: string = ''; + @State uuid: string = '00001101-0000-1000-8000-00805f9b34fb'; + @State dataValue: string = ''; + private toastReport: ToastReport = new ToastReport(); + + build() { + Column({ space: 12 }) { + Text('serial communication') + .fontSize(45) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Top }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + + Text($r('app.string.deviceId_style')) + Row() { + Text('deviceId: ') + + TextInput().onChange((value: string) => { + this.deviceId = value; + }).height('40vp').width('70%') + }.width('80%') + + Text($r('app.string.uuid_style')) + Row() { + Text('uuid: ') + + TextInput().onChange((value: string) => { + this.uuid = value; + }).height('40vp').width('70%') + }.width('80%') + + Row() { + Text('dataValue: ') + + TextInput().onChange((value: string) => { + this.dataValue = value; + }).height('40vp').width('70%') + }.width('80%') + + // [Start server_write_client] + Button('listenSocket') + .width('50%') + .id('listenSocket') + .backgroundColor('#8CE072') + .onClick(() => { + let serverNumber = -1; + let sppOption: socket.SppOptions = { + uuid: this.uuid, + secure: true, + type: 0 + }; + try { + socket.sppListen('server1', sppOption, (code: BusinessError | null, serverSocketID: number) => { + if (code != null) { + console.error(TAG, 'sppListen error, code is ' + (code as BusinessError).code); + this.toastReport.showResult('sppListen error, code is ' + (code as BusinessError).code); + return; + } else { + serverNumber = serverSocketID; + this.serverNumber = serverNumber; + console.info(TAG, 'sppListen success, serverNumber = ' + serverNumber); + this.toastReport.showResult('sppListen success, serverNumber = ' + serverNumber) + } + }); + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + + Button('ServerConnect') + .width('50%') + .id('ServerConnect') + .backgroundColor('#8CE072') + .onClick(() => { + let clientNumber = -1; + try { + + socket.sppAccept(this.serverNumber, (code: BusinessError | null, clientSocketID: number) => { + if (code != null) { + console.error(TAG, 'sppAccept error, code is ' + (code as BusinessError).code); + this.toastReport.showResult('sppAccept error, code is ' + (code as BusinessError).code); + return; + } else { + clientNumber = clientSocketID; + this.clientNumber = clientNumber + console.info(TAG, 'accept the client success'); + this.toastReport.showResult('accept the client success'); + } + }) + console.info(TAG, 'waiting for client connection'); + this.toastReport.showResult('waiting for client connection'); + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + + } + }) + + // [Start socket_spp_connect] + Button('connectDevice') + .width('50%') + .backgroundColor('#8CE072') + .onClick(() => { + try { + socket.sppConnect(this.deviceId, { + uuid: this.uuid, + secure: true, + type: 0 + }, (code: BusinessError | null, socketID: number) => { + if (code != null) { + console.error(TAG, 'sppConnect error, code = ' + (code as BusinessError).code); + this.toastReport.showResult('sppConnect error, code = ' + (code as BusinessError).code); + return; + } + console.info(TAG, 'sppConnect success, socketId = ' + socketID); + this.toastReport.showResult('sppConnect success, socketId = ' + socketID); + }) + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + // [End socket_spp_connect] + + Button('writeData') + .width('50%') + .id('writeData') + .backgroundColor('#8CE072') + .onClick(() => { + let array = new Uint8Array(this.dataValue.length); + encoder.encodeIntoUint8Array(this.dataValue, array); + + try { + socket.sppWrite(this.clientNumber, array.buffer); + console.info(TAG, 'sppWrite success'); + this.toastReport.showResult('sppWrite success'); + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + + Button('subscribeEvent') + .width('50%') + .id('subscribeEvent') + .backgroundColor('#8CE072') + .onClick(() => { + try { + socket.on('sppRead', this.clientNumber, (dataBuffer: ArrayBuffer) => { + const data = new Uint8Array(dataBuffer); + if (data != null) { + console.info(TAG, 'sppRead success, data = ' + JSON.stringify(data)); + this.toastReport.showResult('sppRead success, data = ' + JSON.stringify(data)); + } else { + console.error(TAG, 'sppRead error, data is null'); + this.toastReport.showResult('sppRead error, data is null'); + } + }) + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + + Button('unsubscribeEvent') + .width('50%') + .id('unsubscribeEvent') + .backgroundColor('#8CE072') + .onClick(() => { + try { + socket.off('sppRead', this.clientNumber, (dataBuffer: ArrayBuffer) => { + const data = new Uint8Array(dataBuffer); + if (data != null) { + console.info(TAG, 'offSppRead success, data = ' + JSON.stringify(data)); + this.toastReport.showResult('offSppRead success, data = ' + JSON.stringify(data)); + } else { + console.error(TAG, 'offSppRead error, data is null'); + this.toastReport.showResult('offSppRead error, data is null'); + } + }) + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + + Button('closeServer') + .width('50%') + .id('closeServer') + .backgroundColor('#8CE072') + .onClick(() => { + try { + socket.sppCloseServerSocket(this.serverNumber); + console.info(TAG, 'sppCloseServerSocket success'); + this.toastReport.showResult('sppCloseServerSocket success'); + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + this.toastReport.showResult('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + }) + + Button('closeClient') + .width('50%') + .id('closeClient') + .backgroundColor('#8CE072') + .onClick(() => { + socket.sppCloseClientSocket(this.clientNumber); + console.info(TAG, 'sppCloseClientSocket success'); + this.toastReport.showResult('sppCloseClientSocket success'); + }) + // [End server_write_client] + } + .width('100%') + .height('100%') + .backgroundColor('#E6F7FF') + } +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/module.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a4d001e6eeef8773e6ce3eaea955215a716a5e75 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/module.json5 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.ACCESS_BLUETOOTH", + "reason": "$string:ACCESS_BLUETOOTH", + "usedScene": { + "when": "always" + } + }], + "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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/element/color.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/element/string.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..b18a02c7dc4b7f418dae0fc0745f8bb13297849b --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/element/string.json @@ -0,0 +1,28 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "serial communication" + }, + { + "name": "ACCESS_BLUETOOTH", + "value": "user" + }, + { + "name": "deviceId_style", + "value": "deviceId格式为:11:22:33:44:55::66 ':'不可省略" + }, + { + "name": "uuid_style", + "value": "uuid格式为:1111-2222-33333... '-'不可省略" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/background.png b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/foreground.png b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/layered_image.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/startIcon.png b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/dark/element/color.json b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/mock/mock-config.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/module.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/test/List.test.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/test/LocalUnit.test.ets b/ConnectivityKit/Bluetooth/SerialCommunication/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/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/ConnectivityKit/Bluetooth/SerialCommunication/hvigor/hvigor-config.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1e473e424320d4e68b16737b289f5c851bb19d36 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/hvigorfile.ts b/ConnectivityKit/Bluetooth/SerialCommunication/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/oh-package.json5 b/ConnectivityKit/Bluetooth/SerialCommunication/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/ohosTest.md b/ConnectivityKit/Bluetooth/SerialCommunication/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..732d974b0d1fc6710d07af1ec70e73314d90be6f --- /dev/null +++ b/ConnectivityKit/Bluetooth/SerialCommunication/ohosTest.md @@ -0,0 +1,15 @@ +# 串行通信开发指导 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ----------------- | ------------ | ----------------- | ------------------------|--------- | -------- | +| 应用正常启动 | 设备支持蓝牙 | 启动应用 | 进入应用界面,弹出申请蓝牙权限的弹窗 |否 | Pass | +| 创建服务器监听 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 点击listenSocket | 弹出对应弹窗 |否 | Pass | +| socket等待客户端连接 | 设备支持蓝牙,蓝牙权限申请成功 | 点击ServerConnect | 弹出对应弹窗 |否 | Pass | +| 连接对端设备 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 点击connectDevice | 弹出对应弹窗 |否 |Pass | +| 向客户端写入数据 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 点击writeData | 弹出对应弹窗 |否 | Pass | +| 订阅读请求事件 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 点击subscribeEvent | 弹出对应弹窗 |否 | Pass | +| 取消订阅读请求事件 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 点击unsubscribeEvent | 弹出对应弹窗 |否 | Pass | +| 关闭服务 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已扫描到设备 | 点击closeServer | 弹出对应弹窗 |否 | Pass | +| 关闭客户端 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 单击closeClient | 弹出对应弹窗 |否 | Pass | diff --git a/ConnectivityKit/Bluetooth/SerialCommunication/screenshots/serialCommuniaction.jpeg b/ConnectivityKit/Bluetooth/SerialCommunication/screenshots/serialCommuniaction.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2ae3408d74e0770e7786e632aad605719c3f29a9 Binary files /dev/null and b/ConnectivityKit/Bluetooth/SerialCommunication/screenshots/serialCommuniaction.jpeg differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/.gitignore b/ConnectivityKit/NFC/HCECardSimulationDevelopment/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/.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/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/app.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7c57137332b9d1e039984bb73cbd6713e5492589 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "app": { + "bundleName": "com.samples.hcecardsimulationdevelopment", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/element/string.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..a5faca124a32379a45c663c85ff675480d1ee658 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "HCECardSimulationDevelopment" + } + ] +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/media/app_icon.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/AppScope/resources/base/media/app_icon.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/README.md b/ConnectivityKit/NFC/HCECardSimulationDevelopment/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7b8397ae343a895c336566a1f151210b1f59f5a6 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/README.md @@ -0,0 +1,84 @@ +# HCE卡模拟开发指南 + +### 介绍 + +本示例通过使用[HCE卡模拟开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-hce-guide.md)中各场景的开发示例,展示在工程中,帮助开发者更好地理解HEC功能并合理使用。该工程中展示的代码详细描述可查如下链接: +[HCE卡模拟开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-hce-guide.md) + +### 效果预览 +|启动界面| +|-------| +| | + +### 使用说明 + +1.启动应用 +2.应用停留在启动界面 +3.输出预期日志,功能启动 + +### 工程目录 +``` +entry/src/main/ets/ # HCE应用前台刷卡 +|---entryability +| |---EntryAbility.ets +|---entrybackupability +| |---EntryBackupAbility.ets +|---pages +| |---Index.ets +entry1/src/main/ets/ # HCE应用后台刷卡 +|---entry1ability +| |---Entry1Ability.ets +|---entry1backupability +| |---Entry1BackupAbility.ets +|---pages +| |---Index.ets +``` + +### 具体实现 + +#### HCE应用前台刷卡 +1. 在module.json5文件中声明NFC卡模拟权限,以及声明HCE特定的action。 +2. import需要的NFC卡模拟模块和其他相关的模块。 +3. 判断设备是否支持NFC能力和HCE能力。 +4. 使能前台HCE应用程序优先处理NFC刷卡功能。 +5. 订阅HCE APDU数据的接收。 +6. 完成HCE刷卡APDU数据的接收和发送。 +7. 退出应用程序NFC刷卡页面时,退出前台优先功能。 + +#### HCE应用后台刷卡 +1. 在module.json5文件中声明NFC卡模拟权限,声明HCE特定的action,声明应用能够处理的AID。 +2. import需要的NFC卡模拟模块和其他相关的模块。 +3. 判断设备是否支持NFC能力和HCE能力。 +4. 订阅HCE APDU数据的接收。 +5. 完成HCE刷卡APDU数据的接收和发送。 +6. 退出应用程序时,退出订阅功能。 + +### 相关权限 + +[ohos.permission.NFC_CARD_EMULATION](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionnfc_card_emulation) + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo ConnectivityKit/NFC/HCECardSimulationDevelopment/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +``` \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/build-profile.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..180f0c008e61f2b5aeab049a34dfd55e803113b3 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/build-profile.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. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "entry1", + "srcPath": "./entry1", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/code-linter.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/.gitignore b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/build-profile.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/hvigorfile.ts b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/obfuscation-rules.txt b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/oh-package.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..eeb5607a72dd59148f34fbd691dd5dc120e5350b --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,97 @@ +/* + * 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 front_hce_swipe_ets] +import { cardEmulation } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { AsyncCallback } from '@kit.BasicServicesKit'; +import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; + +let hceElementName: bundleManager.ElementName; +let hceService: cardEmulation.HceService; + +const hceCommandCb : AsyncCallback = (error : BusinessError, hceCommand : number[]) => { + if (!error) { + if (hceCommand == null || hceCommand == undefined) { + hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); + return; + } + // 检查命令,并相应作出响应 + hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); + let responseData = [0x90, 0x00]; // 根据接收到的不同命令更改响应 + hceService.transmit(responseData).then(() => { + hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); + }); + } else { + hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); + } +} + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + + // 判断设备是否支持NFC能力和HCE能力 + if (!canIUse("SystemCapability.Communication.NFC.Core")) { + hilog.error(0x0000, 'testTag', 'nfc unavailable.'); + return; + } + if (!cardEmulation.hasHceCapability()) { + hilog.error(0x0000, 'testTag', 'hce unavailable.'); + return; + } + + hceElementName = { + bundleName: want.bundleName ?? '', + abilityName: want.abilityName ?? '', + moduleName: want.moduleName, + } + hceService = new cardEmulation.HceService(); + } + + onForeground() { + // 当前Ability已进入前台状态 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + if (hceElementName != undefined) { + try { + // 调用接口使能前台HCE应用程序优先处理NFC刷卡功能 + let aidList = ["A0000000031010", "A0000000031011"]; + hceService.start(hceElementName, aidList); + + // 订阅HCE APDU数据的接收 + hceService.on('hceCmd', hceCommandCb); + } catch (error) { + hilog.error(0x0000, 'testTag', 'hceService.start error = %{public}s', JSON.stringify(error)); + } + } + } + + onBackground() { + // 当前Ability已回到后台状态 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + // 退出应用程序NFC标签页面时,调用tag模块退出前台优先功能 + if (hceElementName != undefined) { + try { + hceService.stop(hceElementName); + } catch (error) { + hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); + } + } + } +} +// [End front_hce_swipe_ets] \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..29feaca7669174be5c2b0e2366529ee94ab7e726 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/pages/Index.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..cbe08e2badb66f54e7dbd5758f77de1b730d4f55 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +@Entry +@Component +struct Index { + @State message: string = 'HCE application front-end card swiping'; + + build() { + RelativeContainer() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/module.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3a34e46f780871f5dcf39169e0347f369e016556 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/module.json5 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + // [Start front_hce_swipe] + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + + // 添加nfc卡模拟操作以过滤此应用程序。 + "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" + ] + } + ] + } + ], + "requestPermissions": [ + { + // 添加nfc卡模拟的权限。 + "name": "ohos.permission.NFC_CARD_EMULATION", + "reason": "$string:app_name" + } + ], + // [End front_hce_swipe] + "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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/element/color.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/element/string.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..2b5be9c46305dd75afc2ae0643b882fb4f7c4513 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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": "HCECardSimulationDevelopment" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/background.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/foreground.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/layered_image.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/startIcon.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/dark/element/color.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/mock/mock-config.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/module.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/test/List.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/test/LocalUnit.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/.gitignore b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/build-profile.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/hvigorfile.ts b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/obfuscation-rules.txt b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/oh-package.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c4e8768835e5e869bbd19dfb80d2e323afaa6f2d --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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": "entry1", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1ability/Entry1Ability.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1ability/Entry1Ability.ets new file mode 100644 index 0000000000000000000000000000000000000000..362517f8a635defbe444fdbb35c44aa678c4ae3f --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1ability/Entry1Ability.ets @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Start back_hce_swipe_ets] +import { cardEmulation } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { AsyncCallback } from '@kit.BasicServicesKit'; +import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; + +let hceElementName : bundleManager.ElementName; +let hceService: cardEmulation.HceService; + +const hceCommandCb : AsyncCallback = (error : BusinessError, hceCommand : number[]) => { + if (!error) { + if (hceCommand == null || hceCommand == undefined) { + hilog.error(0x0000, 'testTag', 'hceCommandCb has invalid hceCommand.'); + return; + } + + // 检查命令,然后发送响应。 + hilog.info(0x0000, 'testTag', 'hceCommand = %{public}s', JSON.stringify(hceCommand)); + let responseData = [0x90, 0x00]; // 根据接收到的不同命令更改响应。 + hceService.transmit(responseData).then(() => { + hilog.info(0x0000, 'testTag', 'hceService transmit Promise success.'); + }).catch((err: BusinessError) => { + hilog.error(0x0000, 'testTag', 'hceService transmit Promise error = %{public}s', JSON.stringify(err)); + }); + } else { + hilog.error(0x0000, 'testTag', 'hceCommandCb error %{public}s', JSON.stringify(error)); + } +} + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + + // 判断设备是否支持NFC能力和HCE能力 + if (!canIUse('SystemCapability.Communication.NFC.Core')) { + hilog.error(0x0000, 'testTag', 'nfc unavailable.'); + return; + } + if (!cardEmulation.hasHceCapability()) { + hilog.error(0x0000, 'testTag', 'hce unavailable.'); + return; + } + + hceElementName = { + bundleName: want.bundleName ?? '', + abilityName: want.abilityName ?? '', + moduleName: want.moduleName, + } + hceService = new cardEmulation.HceService(); + hceService.on('hceCmd', hceCommandCb); + } + + onForeground() { + // 当前Ability已进入前台状态 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onDestroy() { + // Ability已被销毁 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + // 退出应用程序NFC标签页面时,调用tag模块退出前台优先功能 + if (hceElementName != undefined) { + try { + hceService.stop(hceElementName); + } catch (error) { + hilog.error(0x0000, 'testTag', 'hceService.stop error = %{public}s', JSON.stringify(error)); + } + } + } +} +// [End back_hce_swipe_ets] \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..91e3598dd883515d5229ca7392d96868b0da5875 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class Entry1BackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/pages/Index.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..a524a899a549432640d35fe5f53c3316a08dbfc7 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/ets/pages/Index.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + RelativeContainer() { + Text(this.message) + .id('HelloWorld') + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/module.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ce1fb387b0cc6a390a3f17bb82c9bf11925243d0 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/module.json5 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry1", + "type": "feature", + "description": "$string:module_desc", + "mainElement": "Entry1Ability", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + // [Start back_hce_swipe] + "abilities": [ + { + "name": "Entry1Ability", + "srcEntry": "./ets/entry1ability/Entry1Ability.ets", + "description": "$string:Entry1Ability_desc", + "icon": "$media:layered_image", + "label": "$string:Entry1Ability_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + + // 添加nfc卡模拟操作以过滤此应用程序。 + "ohos.nfc.cardemulation.action.HOST_APDU_SERVICE" + ] + } + ], + "metadata": [ + { + "name": "payment-aid", + "value": "A0000000031010" // 将其更改为正确 + }, + { + "name": "other-aid", + "value": "A0000000031011" // 将其更改为正确 + } + ] + } + ], + "requestPermissions": [ + { + // 添加nfc卡模拟的权限。 + "name": "ohos.permission.NFC_CARD_EMULATION", + "reason": "$string:app_name" + } + ], + // [End back_hce_swipe] + "extensionAbilities": [ + { + "name": "Entry1BackupAbility", + "srcEntry": "./ets/entry1backupability/Entry1BackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/element/color.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/element/string.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..bfacd4a9c18907308e10e501a9f6f42684c0587d --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "Entry1Ability_desc", + "value": "description" + }, + { + "name": "Entry1Ability_label", + "value": "HCECardSimulationDevelopment1" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/background.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/foreground.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/layered_image.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/startIcon.png b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/mock/mock-config.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/module.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dd5b7a003869fce5b11da19f1de9d791afb131b5 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/ohosTest/module.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry1_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/test/List.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/test/LocalUnit.test.ets b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/entry1/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/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigor/hvigor-config.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigorfile.ts b/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..4d72939a0516be957346941b6438580a93b15230 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/oh-package.json5 b/ConnectivityKit/NFC/HCECardSimulationDevelopment/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/ohosTest.md b/ConnectivityKit/NFC/HCECardSimulationDevelopment/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..8287c8a8cb2939182fdda647f92bae69cef3a282 --- /dev/null +++ b/ConnectivityKit/NFC/HCECardSimulationDevelopment/ohosTest.md @@ -0,0 +1,7 @@ +# HCE卡模拟开发示例代码工程化 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ----------------- | ------------ | ----------------- | ------------------------|--------- | -------- | +| NFC功能正常启动 | 设备支持NFC | 启动应用 | 应用停留在启动界面,输出预期日志 |否 | Pass | \ No newline at end of file diff --git a/ConnectivityKit/NFC/HCECardSimulationDevelopment/screenshots/image.jpeg b/ConnectivityKit/NFC/HCECardSimulationDevelopment/screenshots/image.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..9129c2132ae22b21a5134cd75d5433dace7e2234 Binary files /dev/null and b/ConnectivityKit/NFC/HCECardSimulationDevelopment/screenshots/image.jpeg differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/.gitignore b/ConnectivityKit/NFC/NFCReadAndWrite/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/.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/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/app.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f2ded1340c481d466911f3f14be5e604eaf80b9d --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "app": { + "bundleName": "com.samples.nfcreadandwrite", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/element/string.json b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..30b97e99fd5d77997e6b6ce93376d2083c053a91 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NFCReadAndWrite" + } + ] +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/media/app_icon.png b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/AppScope/resources/base/media/app_icon.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/README.md b/ConnectivityKit/NFC/NFCReadAndWrite/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b51be9b4f3271143f050b46e95e5787b217964d4 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/README.md @@ -0,0 +1,84 @@ +# NFC标签读写开发指南 + +### 介绍 + +本示例通过使用[NFC标签读写开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-tag-access-guide.md)中各场景的开发示例,展示在工程中,帮助开发者更好地理解NFC标签读写功能并合理使用。该工程中展示的代码详细描述可查如下链接: +[NFC标签读写开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-tag-access-guide.md) + +### 效果预览 +|启动界面| +|-------| +| | + +### 使用说明 + +1.启动应用 +2.应用停留在启动界面 +3.输出预期日志,功能启动 + +### 工程目录 +``` +entry/src/main/ets/ # 前台读取标签 +|---entryability +| |---EntryAbility.ets +|---entrybackupability +| |---EntryBackupAbility.ets +|---pages +| |---Index.ets +entry1/src/main/ets/ # 后台读取标签 +|---entryability +| |---EntryAbility.ets +|---entrybackupability +| |---EntryBackupAbility.ets +|---pages +| |---Index.ets +``` + +### 具体实现 + +#### 前台读取标签 + +1. 在module.json5文件中声明NFC标签读取的权限,以及声明NFC标签特定的action。 +2. import需要的tag模块和其他相关的模块。 +3. 判断设备是否支持NFC能力。 +4. 调用tag模块中前台优先的接口,使能前台应用程序优先处理所发现的NFC标签功能。 +5. 获取特定技术类型的NFC标签对象。 +6. 执行读写接口完成标签数据的读取或写入数据到标签。 +7. 退出应用程序NFC标签页面时,调用tag模块退出前台优先功能。 + +#### 后台读取标签 + +1. 在module.json5文件中声明NFC标签读取的权限,声明NFC标签特定的action,以及声明本应用程序的能够处理的NFC标签技术类型。 +2. import需要的tag模块和其他相关的模块。 +3. 获取特定技术类型的NFC标签对象。 +4. 执行读写接口完成标签数据的读取或写入数据到标签。 + +### 相关权限 + +[ohos.permission.NFC_TAG](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionnfc_tag) + +### 依赖 + +不涉及 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ConnectivityKit/NFC/NFCReadAndWrite/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/build-profile.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a06288f8a68a45ab04dd8f8d6b872b4dbf6cf41b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/build-profile.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. + */ + + { + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "entry1", + "srcPath": "./entry1", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/code-linter.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4bacc9e298b707e25577dbcef9e1c7c698880ecf --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/.gitignore b/ConnectivityKit/NFC/NFCReadAndWrite/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/build-profile.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4e956928b47b71f85916d920e894e1272a61d125 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/hvigorfile.ts b/ConnectivityKit/NFC/NFCReadAndWrite/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/obfuscation-rules.txt b/ConnectivityKit/NFC/NFCReadAndWrite/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/oh-package.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dbacc308e4f7758a11b72c6a2af812b2471a0e8a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..d244d203a7ac9748313094b307a1437a9d9963d5 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,136 @@ +/* + * 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 front_get_nfc_tag_ets] +import { tag } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { AbilityConstant, UIAbility, Want, bundleManager } from '@kit.AbilityKit'; + +let nfcTagElementName: bundleManager.ElementName; +let foregroundRegister: boolean; + +async function readerModeCb(error : BusinessError, tagInfo : tag.TagInfo) { + if (!error) { + // 获取特定技术类型的NFC标签对象 + if (tagInfo == null || tagInfo == undefined) { + hilog.error(0x0000, 'testTag', 'readerModeCb tagInfo is invalid'); + return; + } + if (tagInfo.uid == null || tagInfo.uid == undefined) { + hilog.error(0x0000, 'testTag', 'readerModeCb uid is invalid'); + return; + } + if (tagInfo.technology == null || tagInfo.technology == undefined || tagInfo.technology.length == 0) { + hilog.error(0x0000, 'testTag', 'readerModeCb technology is invalid'); + return; + } + + // 执行读写接口完成标签数据的读取或写入数据到标签 + // 使用IsoDep技术访问这个NFC标签。 + let isoDep : tag.IsoDepTag | null = null; + for (let i = 0; i < tagInfo.technology.length; i++) { + if (tagInfo.technology[i] == tag.ISO_DEP) { + try { + isoDep = tag.getIsoDep(tagInfo); + } catch (error) { + hilog.error(0x0000, 'testTag', 'readerModeCb getIsoDep error = %{public}s', JSON.stringify(error)); + return; + } + } + // 如果需要,使用其他技术访问这个NFC标签。 + } + if (isoDep == undefined) { + hilog.error(0x0000, 'testTag', 'readerModeCb getIsoDep is invalid'); + return; + } + + // 使用IsoDep技术连接到这个NFC标签。 + try { + isoDep.connect(); + } catch (error) { + hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.connect() error = %{public}s', JSON.stringify(error)); + return; + } + if (!isoDep.isConnected()) { + hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.isConnected() false.'); + return; + } + + // 向连接的标签发送数据。 + let cmdData = [0x01, 0x02, 0x03, 0x04]; // 请根据需要修改原始数据。 + try { + isoDep.transmit(cmdData).then((response : number[]) => { + hilog.info(0x0000, 'testTag', 'readerModeCb isoDep.transmit() response = %{public}s.', JSON.stringify(response)); + }).catch((err : BusinessError)=> { + hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.transmit() err = %{public}s.', JSON.stringify(err)); + return; + }); + } catch (businessError) { + hilog.error(0x0000, 'testTag', 'readerModeCb isoDep.transmit() businessError = %{public}s.', JSON.stringify(businessError)); + return; + } + } else { + hilog.info(0x0000, 'testTag', 'readerModeCb readerModeCb error %{public}s', JSON.stringify(error)); + } +} + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + + // 判断设备是否支持NFC能力 + if (!canIUse("SystemCapability.Communication.NFC.Core")) { + hilog.error(0x0000, 'testTag', 'nfc unavailable.'); + return; + } + + nfcTagElementName = { + bundleName: want.bundleName ?? '', + abilityName: want.abilityName ?? '', + moduleName: want.moduleName, + } + } + + onForeground() { + // 当前Ability已进入前台状态 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + if (nfcTagElementName != undefined) { + // 调用tag模块中前台优先的接口,使能前台应用程序优先处理所发现的NFC标签功能 + let techList : number[] = [tag.NFC_A, tag.NFC_B, tag.NFC_F, tag.NFC_V]; + try { + tag.on('readerMode', nfcTagElementName, techList, readerModeCb); + foregroundRegister = true; + } catch (error) { + hilog.error(0x0000, 'testTag', 'on readerMode error = %{public}s', JSON.stringify(error)); + } + } + } + + onBackground() { + // 当前Ability已回到后台状态 + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + // 退出应用程序NFC标签页面时,调用tag模块退出前台优先功能 + if (foregroundRegister) { + foregroundRegister = false; + try { + tag.off('readerMode', nfcTagElementName); + } catch (error) { + hilog.error(0x0000, 'testTag', 'off readerMode error = %{public}s', JSON.stringify(error)); + } + } + } +} +// [End front_get_nfc_tag_ets] \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/pages/Index.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..ba890239c7dea4abc424e1c36050ea9ae7295db0 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +@Entry +@Component +struct Index { + @State message: string = 'Front end reads tags'; + + build() { + RelativeContainer() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/module.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b8826c54637287aa21c350e8e3ad3b2fd6cdf56e --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/module.json5 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + // {Start front_get_nfc_tag] + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.nfc.tag.action.TAG_FOUND" + ] + } + ] + } + ], + "requestPermissions": [ + { + // 添加nfc标记操作的权限。 + "name": "ohos.permission.NFC_TAG", + "reason": "$string:app_name" + } + ], + // [End front_get_nfc_tag] + "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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/element/color.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/element/string.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..c175394ff25f5c39302e7dcd31e5ccfbf06eb01b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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": "readAndWrite" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/background.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/foreground.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/layered_image.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/startIcon.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/dark/element/color.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/mock/mock-config.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a99e1d70a555e9935e93519642bb8d05bcb5a149 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f40533d1374f4046f8af1e7df6aa90157cb361d8 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/module.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..be4685a172af804c5b26c0e3618bf770cf138e98 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/test/List.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/test/LocalUnit.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..b7b035e9b66997b8cac57382753074ff60c3f5ee --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/.gitignore b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/build-profile.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/hvigorfile.ts b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/obfuscation-rules.txt b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/oh-package.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c4e8768835e5e869bbd19dfb80d2e323afaa6f2d --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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": "entry1", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..3a17c53f2e978fb7253194a198619c3f183107b5 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entry1backupability/Entry1BackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class Entry1BackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..6817624c7c39356c31ccca986b5e08a00aca232f --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,94 @@ +/* + * 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 back_get_nfc_tag_ets] + import { tag } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + + // 获取特定技术类型的NFC标签对象 + let tagInfo : tag.TagInfo; + try { + tagInfo = tag.getTagInfo(want); + } catch (error) { + hilog.error(0x0000, 'testTag', 'getTagInfo error = %{public}s', JSON.stringify(error)); + return; + } + + if (tagInfo == null || tagInfo == undefined) { + hilog.error(0x0000, 'testTag', 'tagInfo is invalid'); + return; + } + if (tagInfo.uid == null || tagInfo.uid == undefined) { + hilog.error(0x0000, 'testTag', 'uid is invalid'); + return; + } + if (tagInfo.technology == null || tagInfo.technology == undefined || tagInfo.technology.length == 0) { + hilog.error(0x0000, 'testTag', 'technology is invalid'); + return; + } + + // 执行读写接口完成标签数据的读取或写入数据到标签 + // 使用IsoDep技术访问这个NFC标签。 + let isoDep : tag.IsoDepTag | null = null; + for (let i = 0; i < tagInfo.technology.length; i++) { + if (tagInfo.technology[i] == tag.ISO_DEP) { + try { + isoDep = tag.getIsoDep(tagInfo); + } catch (error) { + hilog.error(0x0000, 'testTag', 'getIsoDep error = %{public}s', JSON.stringify(error)); + return; + } + } + // 如果需要,使用其他技术访问这个NFC标签。 + } + if (isoDep == undefined) { + hilog.error(0x0000, 'testTag', 'getIsoDep is invalid'); + return; + } + + // 使用IsoDep技术连接到这个NFC标签。 + try { + isoDep.connect(); + } catch (error) { + hilog.error(0x0000, 'testTag', 'isoDep.connect() error = %{public}s', JSON.stringify(error)); + return; + } + if (!isoDep.isConnected()) { + hilog.error(0x0000, 'testTag', 'isoDep.isConnected() false.'); + return; + } + + // 向连接的标签发送数据。 + let cmdData = [0x01, 0x02, 0x03, 0x04]; // 请根据需要修改原始数据。 + try { + isoDep.transmit(cmdData).then((response : number[]) => { + hilog.info(0x0000, 'testTag', 'isoDep.transmit() response = %{public}s.', JSON.stringify(response)); + }).catch((err : BusinessError)=> { + hilog.error(0x0000, 'testTag', 'isoDep.transmit() err = %{public}s.', JSON.stringify(err)); + return; + }); + } catch (businessError) { + hilog.error(0x0000, 'testTag', 'isoDep.transmit() businessError = %{public}s.', JSON.stringify(businessError)); + return; + } + } +} +// [End back_get_nfc_tag_ets] \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/pages/Index.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..a3795272228e2f6f649e50e5ebad7d4a2c8469d0 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/ets/pages/Index.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +@Entry +@Component +struct Index { + @State message: string = 'Read tags in the background'; + + build() { + RelativeContainer() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/module.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..adbda334abb632003e9ecddb0c345bcf05fe798a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/module.json5 @@ -0,0 +1,85 @@ +/* + * 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": "entry1", + "type": "feature", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + // [Start back_get_nfc_tag] + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home", + "ohos.nfc.tag.action.TAG_FOUND" + ], + "uris": [ + { + "type":"tag-tech/NfcA" + }, + { + "type":"tag-tech/IsoDep" + } + // 必要时添加其他技术, + // 例如: NfcB/NfcF/NfcV/Ndef/MifareClassic/MifareUL/NdefFormatable + ] + } + ] + } + ], + "requestPermissions": [ + { + // 添加nfc标记操作的权限。 + "name": "ohos.permission.NFC_TAG", + "reason": "$string:app_name" + } + ], + // [End back_get_nfc_tag] + "extensionAbilities": [ + { + "name": "Entry1BackupAbility", + "srcEntry": "./ets/entry1backupability/Entry1BackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/element/color.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/element/string.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..cf7f724d70ab2e12153e0432967d96330fcfb6ad --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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": "readAndWrite1" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/background.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/foreground.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/layered_image.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/startIcon.png b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/mock/mock-config.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/module.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..dd5b7a003869fce5b11da19f1de9d791afb131b5 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/ohosTest/module.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry1_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/test/List.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/test/LocalUnit.test.ets b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/entry1/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/ConnectivityKit/NFC/NFCReadAndWrite/hvigor/hvigor-config.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3511c6358c656ebda11ff67ebc9dc6454caeaa69 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/hvigorfile.ts b/ConnectivityKit/NFC/NFCReadAndWrite/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/oh-package.json5 b/ConnectivityKit/NFC/NFCReadAndWrite/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..87fd23ee937818091c08f0d203d079a91d3cf11b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/ohosTest.md b/ConnectivityKit/NFC/NFCReadAndWrite/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..4e057f15d29063614611820304830eb2fd93501b --- /dev/null +++ b/ConnectivityKit/NFC/NFCReadAndWrite/ohosTest.md @@ -0,0 +1,7 @@ +# NFC标签读写示例代码工程化 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ----------------- | ------------ | ----------------- | ------------------------|--------- | -------- | +| NFC功能正常启动 | 设备支持NFC | 启动应用 | 应用停留在启动界面,输出预期日志 |否 | Pass | \ No newline at end of file diff --git a/ConnectivityKit/NFC/NFCReadAndWrite/screenshots/image.jpeg b/ConnectivityKit/NFC/NFCReadAndWrite/screenshots/image.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..9129c2132ae22b21a5134cd75d5433dace7e2234 Binary files /dev/null and b/ConnectivityKit/NFC/NFCReadAndWrite/screenshots/image.jpeg differ diff --git a/ConnectivityKit/NFC/SecureElement/.gitignore b/ConnectivityKit/NFC/SecureElement/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/.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/ConnectivityKit/NFC/SecureElement/AppScope/app.json5 b/ConnectivityKit/NFC/SecureElement/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5ff44d5fe96ed8c43ea03ac46515a572cbfb6a25 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.nfc_se", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/element/string.json b/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..475ddaf762835a539225a2c288c4e6d03b1b3446 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "NFC_SE" + } + ] +} diff --git a/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/media/app_icon.png b/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ConnectivityKit/NFC/SecureElement/AppScope/resources/base/media/app_icon.png differ diff --git a/ConnectivityKit/NFC/SecureElement/README.md b/ConnectivityKit/NFC/SecureElement/README.md new file mode 100644 index 0000000000000000000000000000000000000000..60b4877b1aba32e5d7919c5e6833caeb5ffe293e --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/README.md @@ -0,0 +1,65 @@ +# 安全单元访问开发指南 + +### 介绍 + +本示例通过使用[安全单元访问开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-se-access-guide.md)中各场景的开发示例,展示在工程中,帮助开发者更好地理解HEC功能并合理使用。该工程中展示的代码详细描述可查如下链接: +[安全单元访问开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/nfc/nfc-se-access-guide.md) + +### 效果预览 +|启动界面| +|-------| +| | + +### 使用说明 + +1.启动应用 +2.应用停留在启动界面 +3.输出预期日志,功能启动 + +### 工程目录 +``` +entry/src/main/ets/ +|---entryability +| |---EntryAbility.ets +|---entrybackupability +| |---EntryBackupAbility.ets +|---pages +| |---Index.ets +``` + +### 具体实现 + +#### 应用程序访问安全单元 +1. import需要的安全单元模块。 +2. 判断设备是否支持安全单元能力。 +3. 访问安全单元,实现数据的读取或写入。 + +### 相关权限 + +不涉及 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ConnectivityKit/NFC/SecureElement/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/build-profile.json5 b/ConnectivityKit/NFC/SecureElement/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f28b03dd861d2e84e4ceca13985f36694429f8fc --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/build-profile.json5 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/code-linter.json5 b/ConnectivityKit/NFC/SecureElement/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/.gitignore b/ConnectivityKit/NFC/SecureElement/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/build-profile.json5 b/ConnectivityKit/NFC/SecureElement/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/hvigorfile.ts b/ConnectivityKit/NFC/SecureElement/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/SecureElement/entry/obfuscation-rules.txt b/ConnectivityKit/NFC/SecureElement/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/oh-package.json5 b/ConnectivityKit/NFC/SecureElement/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..a680111a4717a0a59153a21b5a944793178513f0 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,124 @@ +/* + * 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 access_security_unit] +import { omapi } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; + +let seService : omapi.SEService; +let seReaders : omapi.Reader[]; +let seSession : omapi.Session; +let seChannel : omapi.Channel; +let aidArray : number[] = [0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10]; +let p2 : number = 0x00; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + + // 判断设备是否支持安全单元能力 + if (!canIUse('SystemCapability.Communication.SecureElement')) { + hilog.error(0x0000, 'testTag', 'secure element unavailable.'); + return; + } + hilog.info(0x0000, 'testTag', 'secure element available.'); + this.omaTest(); + } + + private async omaTest () { + // 获取服务 + await omapi.createService().then((data) => { + if (data == undefined || !data.isConnected()) { + hilog.error(0x0000, 'testTag', 'secure element service disconnected.'); + return; + } + seService = data; + hilog.info(0x0000, 'testTag', 'secure element service connected.'); + }).catch((error: BusinessError) => { + hilog.error(0x0000, 'testTag', 'createService error %{public}s', JSON.stringify(error)); + return; + }); + + // 获取读卡器 + try { + seReaders = seService.getReaders(); + } catch (error) { + hilog.error(0x0000, 'testTag', 'getReaders error %{public}s', JSON.stringify(error)); + } + if (seReaders == undefined || seReaders.length == 0) { + hilog.error(0x0000, 'testTag', 'no valid reader found.'); + seService.shutdown(); + return; + } + let reader: (omapi.Reader | undefined); + for (let i = 0; i < seReaders.length; ++i) { + let r = seReaders[i]; + if (r.getName().includes('SIM')) { + reader = r; + break; + } + } + if (reader == undefined) { + hilog.error(0x0000, 'testTag', 'no valid sim reader.'); + return; + } + hilog.info(0x0000, 'testTag', 'reader is %{public}s', reader?.getName()); + + // 获取会话 + try { + seSession = reader?.openSession() as omapi.Session; + } catch (error) { + hilog.error(0x0000, 'testTag', 'openSession error %{public}s', JSON.stringify(error)); + } + if (seSession == undefined) { + hilog.error(0x0000, 'testTag', 'seSession invalid.'); + seService.shutdown(); + return; + } + + // 获取通道 + try { + // 修改此处的aid值以打开逻辑通道。 + seChannel = await seSession.openLogicalChannel(aidArray, p2); + } catch (exception) { + hilog.error(0x0000, 'testTag', 'openLogicalChannel exception %{public}s', JSON.stringify(exception)); + } + + if (seChannel == undefined) { + hilog.error(0x0000, 'testTag', 'seChannel invalid.'); + return; + } + + // 发送数据 + let cmdData = [0x01, 0x02, 0x03, 0x04]; // 请根据需要修改原始数据。 + try { + let response: number[] = await seChannel.transmit(cmdData) + hilog.info(0x0000, 'testTag', 'seChannel.transmit() response = %{public}s.', JSON.stringify(response)); + } catch (exception) { + hilog.error(0x0000, 'testTag', 'seChannel.transmit() exception = %{public}s.', JSON.stringify(exception)); + } + + // 关闭通道。必须确保最后关闭通道。 + try { + seChannel.close(); + } catch (exception) { + hilog.error(0x0000, 'testTag', 'seChannel.close() exception = %{public}s.', JSON.stringify(exception)); + } + + } +} +// [End access_security_unit] diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/pages/Index.ets b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..7534811edebd35404f010e92b0a312b9dbdd3e2a --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@Entry +@Component +struct Index { + @State message: string = 'SecureElement'; + + build() { + RelativeContainer() { + Text(this.message) + .id('SecureElement') + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/module.json5 b/ConnectivityKit/NFC/SecureElement/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4144486d1af4c03b0d767cce1cda86fc0d697f91 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/module.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. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "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/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/element/color.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/element/string.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7f9c2173321d80ccb6d42ebf0e748a88209d63b2 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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": "SecureElement" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/background.png b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/background.png differ diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/foreground.png b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/foreground.png differ diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/layered_image.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/startIcon.png b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/backup_config.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/dark/element/color.json b/ConnectivityKit/NFC/SecureElement/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/src/mock/mock-config.json5 b/ConnectivityKit/NFC/SecureElement/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..8630f0493ae875a1eb88b53bbaf9de8a2c7c359f --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f40533d1374f4046f8af1e7df6aa90157cb361d8 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/module.json5 b/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/NFC/SecureElement/entry/src/test/List.test.ets b/ConnectivityKit/NFC/SecureElement/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/entry/src/test/LocalUnit.test.ets b/ConnectivityKit/NFC/SecureElement/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/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/ConnectivityKit/NFC/SecureElement/hvigor/hvigor-config.json5 b/ConnectivityKit/NFC/SecureElement/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1e473e424320d4e68b16737b289f5c851bb19d36 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/ConnectivityKit/NFC/SecureElement/hvigorfile.ts b/ConnectivityKit/NFC/SecureElement/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ConnectivityKit/NFC/SecureElement/oh-package.json5 b/ConnectivityKit/NFC/SecureElement/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..14655ea1c07e1b7b8b8eb3d9f6813577b90f6a0f --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ConnectivityKit/NFC/SecureElement/ohosTest.md b/ConnectivityKit/NFC/SecureElement/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..f3c71387def5a32481b0aba1d60b71e7c4d08f64 --- /dev/null +++ b/ConnectivityKit/NFC/SecureElement/ohosTest.md @@ -0,0 +1,7 @@ +# 安全单元访问示例代码工程化 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ----------------- | ------------ | ----------------- | ------------------------|--------- | -------- | +| NFC功能正常启动 | 设备支持NFC | 启动应用 | 应用停留在启动界面,输出预期日志 |否 | Pass | \ No newline at end of file diff --git a/ConnectivityKit/NFC/SecureElement/screenshots/image.jpeg b/ConnectivityKit/NFC/SecureElement/screenshots/image.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..9129c2132ae22b21a5134cd75d5433dace7e2234 Binary files /dev/null and b/ConnectivityKit/NFC/SecureElement/screenshots/image.jpeg differ diff --git a/ConnectivityKit/Wlan/.gitignore b/ConnectivityKit/Wlan/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6ff06d2ba5623824e833c16a55976cec28edb64e --- /dev/null +++ b/ConnectivityKit/Wlan/.gitignore @@ -0,0 +1,13 @@ +/node_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +/package-lock.json +/entry/package-lock.json +**/oh_modules +**/oh-package-lock.json5 diff --git a/ConnectivityKit/Wlan/AppScope/app.json5 b/ConnectivityKit/Wlan/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e0496f6b4e7a904203f9287389efebd1bef41e1d --- /dev/null +++ b/ConnectivityKit/Wlan/AppScope/app.json5 @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +{ + "app": { + "bundleName": "com.samples.wlan", + "vendor": "samples", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true + } +} diff --git a/ConnectivityKit/Wlan/AppScope/resources/base/element/string.json b/ConnectivityKit/Wlan/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..561c62fe0815ac0ebb4f356e0b8b261b504c64be --- /dev/null +++ b/ConnectivityKit/Wlan/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Wlan" + } + ] +} diff --git a/ConnectivityKit/Wlan/AppScope/resources/base/media/app_icon.png b/ConnectivityKit/Wlan/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/ConnectivityKit/Wlan/AppScope/resources/base/media/app_icon.png differ diff --git a/ConnectivityKit/Wlan/README_zh.md b/ConnectivityKit/Wlan/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..25811dced647943900b63e1ef682d6141a4121f2 --- /dev/null +++ b/ConnectivityKit/Wlan/README_zh.md @@ -0,0 +1,89 @@ +# P2P模式开发指南 + +### 介绍 + +本示例通过将[Connectivity Kit指南文档](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/connectivity)中各场景的开发示例,展示在工程中,帮助开发者更好地理解ArkUI提供的组件及组件属性并合理使用。该工程中展示的代码详细描述可查如下链接: +[P2P模式开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/wlan/p2p-development-guide.md)。 +[Wi-Fi扫描](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/wlan/scan-development-guide.md)。 +[STA模式开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/wlan/sta-development-guide.md)。 + +### 效果预览 +|应用界面| +|主页 |建议网络连接 | WiFi列表 | +|---------------------------------------------|---------------------------------------|-----------------------------------------| +|![password](screenshots/main.png)|![password](screenshots/connect_wifi.png)|![password](screenshots/wifi_list.png)| +|P2p测试 |P2p连接 | 创建群组 | +|---------------------------------------------|---------------------------------------|-----------------------------------------| +|![password](screenshots/p2ptest.png)|![password](screenshots/p2pconnect.png)|![password](screenshots/creatgroup.png)| + + +|获取真实BSSID授权 | +|-----------------------------------------| +|![password](screenshots/GET_WIFI_PEERS_MAC.png) | + +### 使用说明 + +1. 启动应用后会判断WLAN是否激活,如果是激活状态,点击wifi列表会扫描并展示可用WiFi列表; +2. 点击首页建议击网络连接,填写可选参数,连接建议网络; +3. 点击首页P2p测试,进行P2p连接和创建群组场景测试。 + +### 工程目录 +``` +entry/src/main/ets/ +|---component +| |---P2pView.ets // P2p列表详情页 +| |---TitleBar.ets // 页面头部组件 +| |---WifiView.ets // wifi列表详情页 +|---entryability +| |---EntryAbility.ets // 应用入口,在这里请求相关权限和进入首页 +|---pages +| |---Index.ets // 首页 +| |---AvailableWifi.ets // 热点扫描信息列表 +| |---WifiConnect.ets // 建议网络连接 +| |---P2pTest.ets // P2p测试场景 +| |---AvailableP2p.ets // P2p扫描信息列表 +| |---P2pSetting.ets // 创建群组 +``` + +### 具体实现 + +* 开始测试前需打开设备WiFi, +首页:[Index.ets](entry/src/main/ets/pages/Index.ets)。 + +* 建议网络连接:[WifiConnect.ets](entry/src/main/ets/pages/WifiConnect.ets),根据提示填写参数信息通过connectwifi()发起连接。 +* wifi的扫描功能:首页点击wifi列表,在[AvailableWifi.ets](entry/src/main/ets/pages/AvailableWifi.ets) 通过(entry/src/main/ets/component/WifiView.ets)显示每一个WiFi信息,调用getScanInfos()获取扫描结果,调用定时器每3s获取一次。 +* P2p场景测试: + *p2p连接:[AvailableP2p.ets.ets](entry/src/main/ets/pages/AvailableP2p.ets) 通过(entry/src/main/ets/component/P2pView.ets)显示每一个P2p信息,点击列表信息通过connectP2p()函数发起连接。 + *创建P2P群组:在[P2pSetting.ets](entry/src/main/ets/pages/P2pSetting.ets) 填写参数信息通过createGroup()来创建群组。 +### 相关权限 + +[ohos.permission.GET_WIFI_INFO](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionget_wifi_info) + +[ohos.permission.SET_WIFI_INFO](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionset_wifi_info) + +[ohos.permission.GET_WIFI_PEERS_MAC](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/restricted-permissions.md#ohospermissionget_wifi_peers_mac) +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. 本示例需要使用DevEco Studio 6.0.0 及以上版本才可编译运行。 + +3. 本示例已适配API version 20版本SDK,本示例需要使用@ohos.wifiManager系统权限的系统接口。使用Full SDK时需要手动从镜像站点获取,并在DevEco Studio中替换,具体操作可参考[替换指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/faqs/full-sdk-switch-guide.md/) 。 + +4. 本示例需要使用ohos.permission.GET_WIFI_INFO、ohos.permission.SET_WIFI_INFO的权限为system_grant级别、ohos.permission.GET_WIFI_PEERS_MAC的权限为system_basic级别(相关权限级别可通过[权限定义列表](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md) 查看),需要手动配置对应级别的权限签名。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo ConnectivityKit/Wlan > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +``` \ No newline at end of file diff --git a/ConnectivityKit/Wlan/build-profile.json5 b/ConnectivityKit/Wlan/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..05d4900f0cdd772b39ebd218eaa7eea491e7b352 --- /dev/null +++ b/ConnectivityKit/Wlan/build-profile.json5 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "products": [ + { + "name": "default", + "bundleName": "com.samples.wlan", + "signingConfig": "default", + "compatibleSdkVersion": "6.0.0(20)", + "targetSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + } + ], + "signingConfigs": [] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/code-linter.json5 b/ConnectivityKit/Wlan/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4bacc9e298b707e25577dbcef9e1c7c698880ecf --- /dev/null +++ b/ConnectivityKit/Wlan/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/.gitignore b/ConnectivityKit/Wlan/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e5d65b11d36650f2d90d25facccfec45a382e931 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/.gitignore @@ -0,0 +1,4 @@ +/node_modules +/.preview +/build +/.cxx diff --git a/ConnectivityKit/Wlan/entry/build-profile.json5 b/ConnectivityKit/Wlan/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a2d361ac657af1056e243fd093bc2d16bf8089b6 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/build-profile.json5 @@ -0,0 +1,28 @@ +/* + * 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": { + }, + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/hvigorfile.ts b/ConnectivityKit/Wlan/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..94b039ca97168c2ece09f5559b156db2a19d82e1 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/hvigorfile.ts @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { hapTasks } from '@ohos/hvigor-ohos-plugin' diff --git a/ConnectivityKit/Wlan/entry/obfuscation-rules.txt b/ConnectivityKit/Wlan/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..f722a31cae22b03ec6440126cb942bc1faa09884 --- /dev/null +++ b/ConnectivityKit/Wlan/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 hilog.info* 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/ConnectivityKit/Wlan/entry/oh-package.json5 b/ConnectivityKit/Wlan/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..73bef04acf22052af438cef69617a83c0d269719 --- /dev/null +++ b/ConnectivityKit/Wlan/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. + */ + +{ + "license": "ISC", + "devDependencies": {}, + "name": "entry", + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {} +} diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/component/P2pView.ets b/ConnectivityKit/Wlan/entry/src/main/ets/component/P2pView.ets new file mode 100644 index 0000000000000000000000000000000000000000..0762f36fa11abf2b5c11d5c2e1de1a9c082193fe --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/component/P2pView.ets @@ -0,0 +1,86 @@ +/** + * 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 wifi from '@ohos.wifiManager'; +import hilog from '../model/Logger' + +/** + * P2pView Component of p2p test + */ +const TAG = 'wifiTestApp [P2pView]' + +@Component +export struct P2pView { + private p2p!: wifi.WifiP2pDevice + private securityString: Resource = $r('app.string.useful') + private p2pConnectState: number = 0 + @StorageLink('p2pLinkedDeviceName') p2pLinkedDeviceName: string = '' + @State isLock: boolean = true + + aboutToAppear() { + hilog.info(TAG , `aboutToAppear ${ JSON.stringify(this.p2p) }`) + + this.p2pConnectState = AppStorage.get('p2pConnectState') ! + this.p2pLinkedDeviceName = AppStorage.get('p2pLinkedDeviceName') ! + if ( this.p2p ) { + hilog.info(TAG , 'this.p2p is true'); + } else { + hilog.info(TAG , 'this.p2p is false'); + } + } + + build() { + Row() { + Column() { + if ( this.p2p ) { + if ( this.p2p.deviceName ) { + Text(this.p2p.deviceName) + .fontSize(20) + .width('100%') + } + } + if ( this.p2pConnectState == 1 && this.p2pLinkedDeviceName == this.p2p.deviceName ) { + Text($r('app.string.p2pConnected')) + .fontSize(18) + .fontColor(Color.Gray) + .width('100%') + } else { + Text($r('app.string.useful')) + .fontSize(18) + .fontColor(Color.Gray) + .width('100%') + } + } + .layoutWeight(1) + + Stack({ alignContent : Alignment.BottomEnd }) { + Image($r('app.media.wifi')) + .height(30).width(30) + .objectFit(ImageFit.Contain) + if ( this.isLock ) { + Image($r('app.media.lock')) + .objectFit(ImageFit.Contain) + .width(15).height(15) + } + } + .width(40).height(40) + .margin({ right : 10 }) + } + .backgroundColor(Color.White) + .width('100%') + .padding(10) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/component/TitleBar.ets b/ConnectivityKit/Wlan/entry/src/main/ets/component/TitleBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..7db1022c4ad667775de2c56df899b286a364944d --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/component/TitleBar.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import router from '@ohos.router' + +@Component +export struct TitleBar { + build() { + Row() { + Text($r('app.string.EntryAbility_label')) + .fontColor(Color.White) + .fontSize(25) + .layoutWeight(1) + + Button() { + Image($r('app.media.about')) + .size({ width: 60, height: '95%' }) + .objectFit(ImageFit.Contain) + } + .id('about') + .type(ButtonType.Normal) + .height('90%') + .backgroundColor($r('app.color.button_color')) + } + .width('100%') + .height('8%') + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .backgroundColor($r('app.color.button_color')) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/component/WifiView.ets b/ConnectivityKit/Wlan/entry/src/main/ets/component/WifiView.ets new file mode 100644 index 0000000000000000000000000000000000000000..d131f13061f2f76d74098c2ef6f0c20c219f9385 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/component/WifiView.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import hilog from '../model/Logger' +import wifi from '@ohos.wifiManager' + +const TAG: string = 'WifiView' + +@Component +export struct WifiView { + private wifi: wifi.WifiScanInfo | null = null; + private securityString: Resource = $r('app.string.encryption') + @State isLock: boolean = true + + aboutToAppear() { + hilog.debug(TAG, `aboutToAppear ${JSON.stringify(this.wifi)}`) + if (this.wifi) { + if (this.wifi.securityType) { + if ((this.wifi.securityType as number) === 0 || this.wifi.securityType === 1) { + this.securityString = $r('app.string.open') + this.isLock = false + } + } + } + } + + build() { + Row() { + Column() { + if (this.wifi) { + if (this.wifi.ssid) { + Text(this.wifi.ssid) + .fontSize(20) + .width('100%') + } + } + Text(this.securityString) + .fontSize(18) + .fontColor(Color.Gray) + .width('100%') + } + .layoutWeight(1) + + Stack({ alignContent: Alignment.BottomEnd }) { + Image($r('app.media.wifi')) + .height(30) + .width(30) + .objectFit(ImageFit.Contain) + if (this.isLock) { + Image($r('app.media.lock')) + .objectFit(ImageFit.Contain) + .width(15) + .height(15) + } + } + .width(40) + .height(40) + .margin({ right: 10 }) + } + .backgroundColor(Color.White) + .width('100%') + .padding(10) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/entryability/EntryAbility.ets b/ConnectivityKit/Wlan/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..f09ffa4749ac2516f3fe0b40c2e75cc950a8470e --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/entryability/EntryAbility.ets @@ -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. + */ + +import hilog from '../model/Logger' +import UIAbility from '@ohos.app.ability.UIAbility'; +import Window from '@ohos.window' +import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; +import type { Permissions } from '@ohos.abilityAccessCtrl'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info('Ability onCreate') + const PERMISSIONS: Array = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION']; + try { + abilityAccessCtrl.createAtManager().requestPermissionsFromUser(this.context, PERMISSIONS); + } catch (err) { + hilog.info(`catch err->${JSON.stringify(err)}`); + } + } + + onDestroy() { + hilog.info('Ability onDestroy') + } + + onWindowStageCreate(windowStage: Window.WindowStage) { + hilog.info('Ability onWindowStageCreate') + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(`Failed to load the content. Cause: ${JSON.stringify(err)}`) + return + } + hilog.info(`Succeeded in loading the content. Data: ${JSON.stringify(data)}`) + }) + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + hilog.info('Ability onWindowStageDestroy') + } + + onForeground() { + // Ability has brought to foreground + hilog.info('Ability onForeground') + } + + onBackground() { + // Ability has back to background + hilog.info('Ability onBackground') + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/model/Logger.ets b/ConnectivityKit/Wlan/entry/src/main/ets/model/Logger.ets new file mode 100644 index 0000000000000000000000000000000000000000..9c1934088d95910eece5e056d78eedcec2946977 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/model/Logger.ets @@ -0,0 +1,53 @@ +/* + * 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'; + +class Logger { + private domain: number; + private prefix: string; + private format: string = '%{public}s'; + + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0x0001; // 设置域名 + } + + debug(...args: string[]) { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]) { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]) { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]) { + hilog.error(this.domain, this.prefix, this.format, args); + } + + fatal(...args: string[]) { + hilog.fatal(this.domain, this.prefix, this.format, args); + } + + isLoggable(level: number) { + hilog.isLoggable(this.domain, this.prefix, level); + } +} + +export default new Logger('[Sample_NetConnection_Exploitation]'); \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableP2p.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableP2p.ets new file mode 100644 index 0000000000000000000000000000000000000000..9a4606a8902bf9d424fe6dd3f92e68334464be9a --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableP2p.ets @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import promptAction from '@ohos.promptAction'; +import hilog from '../model/Logger'; +import wifi from '@ohos.wifiManager'; +import { P2pView } from '../component/P2pView'; + +const TAG = 'availableP2p'; + +/** + * available p2p page of WiFi test + */ +@Entry +@Component +struct WifiConnect { + @State p2pList: Array = [] + @State p2pLinkedInfo: wifi.WifiP2pLinkedInfo | null = null; + private selectIndex: number = - 1 + @State isSwitchOn: boolean = false; + + addListener() { + // 连接状态改变时,修改连接信息 + hilog.info(TAG, 'addListener'); + wifi.on('p2pConnectionChange', async wifiP2pLinkedInfo => { + hilog.info('p2p connection change receive event: ' + JSON.stringify(wifiP2pLinkedInfo)); + this.p2pLinkedInfo = wifiP2pLinkedInfo + let connectState = wifiP2pLinkedInfo.connectState + let p2pConnectionMessage = '' + switch ( connectState ) { + case 0: + p2pConnectionMessage = 'DISCONNECTED!'; + this.p2pLinkedInfo = null + promptAction.showToast({ message : 'connect disabled' }) + break; + case 1: + p2pConnectionMessage = 'CONNECTED!'; + promptAction.showToast({ message : 'connect success' }) + let curGp = await wifi.getCurrentGroup() + AppStorage.setOrCreate('p2pLinkedDeviceName', curGp.groupName) + break; + default: + p2pConnectionMessage = '未知状态'; + break; + } + AppStorage.setOrCreate('p2pConnectState', connectState) + }) + + wifi.on('p2pPeerDeviceChange', async (_: wifi.WifiP2pDevice[]) => { + hilog.info(TAG, 'p2pPeerDeviceChange:', JSON.stringify(_)) + try { + let devices = await wifi.getP2pPeerDevices() + this.p2pList = devices + } catch (e) { + hilog.info(JSON.stringify(e)) + } + }) + } + + aboutToAppear() { + // 如果wifi是开的,就记录下状态,然后扫描p2p设备,并获取连接信息 + if (!wifi.isWifiActive()) { + promptAction.showToast({ message : 'place active wifi' }) + return + } + this.isSwitchOn = true; + wifi.startDiscoverDevices() + this.addListener(); + } + + aboutToDisappear() { + wifi.off('p2pPeerDeviceChange') + wifi.off('p2pConnectionChange') + } + + + connectP2p(p2pScanInfo: wifi.WifiP2pDevice) { + promptAction.showToast({ message : 'connect to device' }) + hilog.info(TAG , `connect deviceAddress=${ p2pScanInfo.deviceAddress }`) + hilog.info(TAG , `p2pScanInfo:` + JSON.stringify(p2pScanInfo)) + let config: wifi.WifiP2PConfig = { + deviceAddress : p2pScanInfo.deviceAddress, + netId : - 2 , + deviceAddressType: 1, + passphrase : '' , + groupName : '' , + goBand : 0 + } + wifi.p2pConnect(config) + } + + + build() { + Column() { + Row() { + Text($r('app.string.p2p_available')) + .fontSize(22) + .fontWeight(FontWeight.Bold) + .height(40) + } + .width('100%') + .padding({ left: 16, right: 16 }) + + List({ space: 5 }) { + ForEach(this.p2pList , (item: wifi.WifiP2pDevice , index: number) => { + ListItem() { + P2pView({ p2p : item }) + } + .onClick(() => { + hilog.info(TAG , 'p2p click') + this.selectIndex = index + if ( this.p2pLinkedInfo !== null && this.p2pLinkedInfo.connectState == 1 ) { + promptAction.showToast({ message : 'this p2p is connected' }) + return + } + this.connectP2p(item) + }) + } , (item: wifi.WifiP2pDevice) => JSON.stringify(item)); + } + .layoutWeight(1) + .divider({ strokeWidth : 1 , color : Color.Gray , startMargin : 10 , endMargin : 10 }) + .margin(10) + } + .margin({ top : 15 , bottom : 100 }) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableWifi.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableWifi.ets new file mode 100644 index 0000000000000000000000000000000000000000..288377b09672653f5206b8be523fe5c35ab4185b --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/AvailableWifi.ets @@ -0,0 +1,126 @@ +/* + * 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 '../model/Logger' +import { WifiView } from '../component/WifiView' +import wifi from '@ohos.wifiManager' + +const TAG = 'AvailableWiFi' +let self: AvailableWifi | null = null; +@Entry +@Component +export struct AvailableWifi { + @State wifilist: Array = [] + @State wifilisttest: Array = [] + @State isSwitchOn: boolean = false; + private linkedInfo: wifi.WifiLinkedInfo | null = null; + @State isLinked: boolean = false; + + // 扫描wifi + async getScanInfos() { + // 不停地扫描wifi + let result: wifi.WifiScanInfo[] = await wifi.getScanInfoList(); + + if (this.isSwitchOn) { + setTimeout(async () => { + this.wifilist = result + await this.getScanInfos(); + }, 3000) + } + } + + addListener() { + // 连接状态改变时,修改连接信息 + wifi.on('wifiConnectionChange', async state => { + hilog.info(TAG, `wifiConnectionChange: ${state}`); + await this.getLinkedInfo(); + }) + // wifi状态改变时,先清空wifi列表,然后判断是否是开启状态,如果是就扫描 + wifi.on('wifiStateChange', state => { + hilog.info(TAG, `wifiStateLisener state: ${state}`); + if (state === 1) { // 1: wifi is enable, 0:wifi is disable + this.isSwitchOn = true; + this.getScanInfos(); + } + if (state === 0) { // 1: wifi is enable, 0:wifi is disable + this.isSwitchOn = false; + } + }) + } + + async getLinkedInfo() { + try { + let wifiLinkedInfo = await wifi.getLinkedInfo(); + if (wifiLinkedInfo === null || wifiLinkedInfo.bssid === '') { + this.isLinked = false; + this.linkedInfo = null; + return; + } + this.isLinked = true; + this.linkedInfo = wifiLinkedInfo; + } catch (err) { + hilog.info(`getLinkedInfo failed err is ${JSON.stringify(err)}`); + } + } + + aboutToAppear() { + if (wifi.isWifiActive()) { + hilog.info(TAG, 'wifi is active'); + this.isSwitchOn = true; + this.getScanInfos(); + this.getLinkedInfo(); + } + hilog.info(TAG, 'wifi is disabled'); + // 启动监听 + this.addListener(); + } + + aboutToDisappear() { + wifi.off('wifiConnectionChange'); + wifi.off('wifiStateChange'); + } + + build() { + Column() { + Row() { + Text($r('app.string.wlan')) + .fontSize(22) + .fontWeight(FontWeight.Bold) + .height(40) + Column() { + Toggle({ type: ToggleType.Switch, isOn: this.isSwitchOn }) + .id('switch') + .onChange((isOn: boolean) => { + hilog.info(`wifi swtich is: ${isOn}`); + this.wifilist = this.wifilisttest + }) + } + } + .width('100%') + .padding({ left: 16, right: 16 }) + + List({ space: 5 }) { + ForEach(this.isSwitchOn ? this.wifilist : this.wifilisttest, (wifiItem: wifi.WifiScanInfo) => { + ListItem() { + WifiView({ wifi: wifiItem }) + } + }, (wifiItem: wifi.WifiScanInfo) => JSON.stringify(wifiItem)); + } + } + .width('100%') + .height('100%') + .backgroundColor($r('app.color.index_bg')) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/Index.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..35bc487e9a01002278ae2b4338d6ab6512f329a6 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/Index.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 hilog from '../model/Logger'; +import { TitleBar } from '../component/TitleBar'; +import router from '@ohos.router' + +const TAG = 'Index'; + +@Entry +@Component +struct Index { + build() { + Column({ space: 5 }) { + TitleBar() + Text($r('app.string.wifi_List')) + .fontColor(Color.Black) + .fontSize(20) + .layoutWeight(1) + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .borderRadius(5) + .width('100%') + // .fontColor($r('app.color.text_color')) + .backgroundColor($r('app.color.button_color2')) + .onClick(() => { + router.pushUrl({ url: 'pages/AvailableWifi' }) + }) + + Text($r('app.string.wifi_Connect')) + .fontColor(Color.Black) + .fontSize(20) + .layoutWeight(1) + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .borderRadius(5) + .width('100%') + // .fontColor($r('app.color.text_color')) + .backgroundColor($r('app.color.text_color')) + .onClick(() => { + router.pushUrl({ url: 'pages/WifiConnect' }) + }) + + Text($r('app.string.p2p_test')) + .fontColor(Color.Black) + .fontSize(20) + .layoutWeight(1) + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .borderRadius(5) + .width('100%') + // .fontColor($r('app.color.text_color')) + .backgroundColor($r('app.color.index_background')) + .onClick(() => { + router.pushUrl({ url: 'pages/P2pTest' }) + }) + } + .width('100%') + .height('8%') + .backgroundColor($r('app.color.index_bg')) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pSetting.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pSetting.ets new file mode 100644 index 0000000000000000000000000000000000000000..2a9393ac3f16c600547c9aadaa65023686dc0815 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pSetting.ets @@ -0,0 +1,180 @@ +/* + * 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 '../model/Logger'; +import router from '@ohos.router' +import wifi from '@ohos.wifiManager'; +import promptAction from '@ohos.promptAction' + +const TAG = 'p2pSetting' + +@Entry +@Component +struct p2pSetting { + @State deviceAddress: string = ''; + @State netId: number = - 2; + @State passphrase: string = ''; + @State groupName: string = '' + @State goBand: number = 0; + + aboutToAppear() { + AppStorage.setOrCreate('deviceAddress' , this.deviceAddress) + AppStorage.setOrCreate('netId' , this.netId) + AppStorage.setOrCreate('passphrase' , this.passphrase) + AppStorage.setOrCreate('groupName' , this.groupName) + AppStorage.setOrCreate('goBand' , this.goBand) + } + + + async createGroup() { + try { + let deviceInfo = await wifi.getP2pLocalDevice() + let config:wifi.WifiP2PConfig = { + deviceAddress: deviceInfo.deviceAddress, + netId: this.netId, + passphrase: this.passphrase, + groupName: this.groupName, + goBand: this.goBand, + } + hilog.info(`deviceAddress: ${config.deviceAddress}, netId: ${config.netId}, pwd: ${config.passphrase}, gpname: ${config.groupName}, goBand: ${config.goBand}`) + wifi.createGroup(config) + promptAction.showToast({ message : 'createGroup success' }) + } catch (e) { + hilog.info(TAG, `createGroup Error: ${JSON.stringify(e)}`) + } + } + + build() { + Column() { + Row() { + Text('deviceAddress:').fontSize(16).width(120) + TextInput({ text : this.deviceAddress , placeholder : 'input peripheral deviceId.' }) + .fontSize('15vp') + .onChange((strInput: string) => { + this.deviceAddress = strInput; + //判断合法性 + if ( strInput.length >= 1 ) { + AppStorage.setOrCreate('deviceAddress' , this.deviceAddress); + } + }) + .width('80%') + .borderRadius(1) + } + .backgroundColor($r('app.color.moon')) + .padding(5) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + + Column() { + Stack().height('0.25vp').backgroundColor('#000000'); + Column() { + Row() { + Text('netId:').fontSize(15).width(60); + TextInput({ text : this.netId.toString() , placeholder : '-2' }) + .fontSize('15vp') + .onChange((strInput: string) => { + this.netId = parseInt(strInput); + //判断合法性 + if ( strInput.length >= 1 ) { + AppStorage.setOrCreate('netId' , this.netId); + } + }) + .width('80%') + .borderRadius(1) + } + .padding(5) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .backgroundColor($r('app.color.spring')) + + Row() { + Text('passphrase:').fontSize(15).width(100); + TextInput({ text : this.passphrase , placeholder : 'input passphrase' }) + .fontSize('15vp') + .onChange((strInput: string) => { + this.passphrase = strInput; + if ( strInput.length >= 1 ) { + AppStorage.setOrCreate('passphrase' , this.passphrase); + } + }) + .width('80%') + .borderRadius(1) + } + .backgroundColor($r('app.color.spring')) + .padding(5) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + + Row() { + Text('groupName:').fontSize(15).width(100); + TextInput({ text : this.groupName , placeholder : 'testGroup' }) + .fontSize('15vp') + .onChange((strInput: string) => { + this.groupName = strInput; + if ( strInput.length >= 1 ) { + AppStorage.setOrCreate('groupName' , this.groupName); + } + }) + .width('80%') + .borderRadius(1) + } + .backgroundColor($r('app.color.spring')) + .padding(5) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + + Row() { + Text('goBand:').fontSize(15).width(80); + TextInput({ text : this.goBand.toString() , placeholder : '0' }) + .fontSize('15vp') + .onChange((strInput: string) => { + this.goBand = Number(strInput); + if ( strInput.length >= 1 ) { + AppStorage.setOrCreate('goBand' , this.goBand); + } + }) + .width('80%') + .borderRadius(1) + } + .backgroundColor($r('app.color.spring')) + .padding(5) + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + + } + + Stack().height('0.25vp').backgroundColor('#000000'); + } + + Row() { + Button($r('app.string.create_group'))// .dialogButtonStyle() + .fontSize('16fp') + .onClick(() => { + if(this.passphrase === '' || this.groupName === '') { + hilog.info(TAG, 'ssid || preSharedKey is null'); + promptAction.showToast({ message : 'passphrase or groupName is null' }) + return; + } + this.createGroup(); + }) + .height('100%') + } + .width('50%') + .height('6%') + .justifyContent(FlexAlign.SpaceBetween) + } + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pTest.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pTest.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1aea01713a51e7e7add41fb3346afb8f9ae884b --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/P2pTest.ets @@ -0,0 +1,59 @@ +/* + * 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 '../model/Logger'; +import { TitleBar } from '../component/TitleBar'; +import router from '@ohos.router' + +const TAG = 'Index'; + +@Entry +@Component +struct P2pTest { + build() { + Column({ space: 5 }) { + Text($r('app.string.p2p_Connect')) + .fontColor(Color.Black) + .fontSize(20) + .layoutWeight(1) + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .borderRadius(5) + .width('100%') + // .fontColor($r('app.color.text_color')) + .backgroundColor($r('app.color.moon')) + .onClick(() => { + router.pushUrl({ url: 'pages/AvailableP2p' }) + }) + + Text($r('app.string.create_group_test')) + .fontColor(Color.Black) + .fontSize(20) + .layoutWeight(1) + .constraintSize({ minHeight: 50 }) + .padding({ left: 15 }) + .borderRadius(5) + .width('100%') + // .fontColor($r('app.color.text_color')) + .backgroundColor($r('app.color.cyan')) + .onClick(() => { + router.pushUrl({ url: 'pages/P2pSetting' }) + }) + } + .width('100%') + .height('8%') + .backgroundColor($r('app.color.index_bg')) + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/ets/pages/WifiConnect.ets b/ConnectivityKit/Wlan/entry/src/main/ets/pages/WifiConnect.ets new file mode 100644 index 0000000000000000000000000000000000000000..c1406a79d55a00996a070274f6e6a2736d12a24c --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/ets/pages/WifiConnect.ets @@ -0,0 +1,207 @@ +/* + * 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 '../model/Logger' +import promptAction from '@ohos.promptAction' +import wifi from '@ohos.wifiManager' +import router from '@ohos.router' + +const TAG = 'WifiConnect' +@Entry +@Component +struct WifiConnect { + ssid: string = '' + password: string = '' + selectedSecurityType: wifi.WifiSecurityType = wifi.WifiSecurityType.WIFI_SEC_TYPE_INVALID + private linkedInfo: wifi.WifiLinkedInfo | null = null; + @State isLinked: boolean = false; + @State isSwitchOn: boolean = false; + @State wifiCandidateConfig: wifi.WifiDeviceConfig = { + ssid: '', + bssid: '', + preSharedKey: '', + isHiddenSsid: false, + securityType: 0 + } + private controller: CustomDialogController | null = null; + + async connectwifi(deviceConfig: wifi.WifiDeviceConfig) { + try { + promptAction.showToast({ message : 'connect to wifi' }) + hilog.info(`connectwifi failed err is ${JSON.stringify(deviceConfig)}`); + wifi.addCandidateConfig(deviceConfig).then(result => { + // 连接指定网络 + wifi.connectToCandidateConfig(result); + this.getLinkedInfo() + }); + }catch(error){ + hilog.error('sun failed:' + JSON.stringify(error)); + } + } + + async getLinkedInfo() { + try { + let wifiLinkedInfo = await wifi.getLinkedInfo(); + if (wifiLinkedInfo === null || wifiLinkedInfo.bssid === '') { + this.isLinked = false; + this.linkedInfo = null; + return; + } + this.isLinked = true; + this.linkedInfo = wifiLinkedInfo; + } catch (err) { + hilog.info(`getLinkedInfo failed err is ${JSON.stringify(err)}`); + } + } + + addListener() { + // 连接状态改变时,修改连接信息 + wifi.on('wifiConnectionChange', async state => { + hilog.info(TAG, `wifiConnectionChange: ${state}`); + await this.getLinkedInfo(); + }) + } + + aboutToAppear() { + // 如果wifi是开的,就记录下状态,然后扫描wifi,并获取连接信息 + if (wifi.isWifiActive()) { + hilog.info(TAG, 'wifi is active'); + this.isSwitchOn = true; + } + hilog.info(TAG, 'wifi is disabled'); + // 启动监听 + this.addListener(); + } + + build() { + Column() { + Column() { + Row() { + Text('ssid').fontSize('16fp').width('18%') + TextInput({ placeholder: $r('app.string.input_candidate_wifi_ssid') }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: '16fp' }) + .caretColor(Color.Blue) + .width('80%') + .fontSize('16fp') + .fontColor($r('app.color.title_black_color')) + .onChange((value: string) => { + this.wifiCandidateConfig.ssid = value; + }) + } + .width('100%') + .margin({ top: '3%' }) + + // .height( CommonConstants.TEXT_INPUT_HEIGHT ) + // .backgroundColor( $r( 'app.color.input_background' ) ) + Row() { + Text('bssid').fontSize('16fp').width('18%') + TextInput({ placeholder: $r('app.string.input_candidate_wifi_bssid') }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: '16fp' }) + .caretColor(Color.Blue) + .width('80%') + .fontSize('16fp') + .fontColor($r('app.color.title_black_color')) + .onChange((value: string) => { + this.wifiCandidateConfig.bssid = value; + }) + } + .width('100%') + .margin({ top: '3%' }) + + Row() { + Text('preSharedKey').fontSize('16fp').width('28%') + TextInput({ placeholder: $r('app.string.input_candidate_wifi_preSharedKey') }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: '16fp' }) + .caretColor(Color.Blue) + .width('70%') + .fontSize('16fp') + .fontColor($r('app.color.title_black_color')) + .onChange((value: string) => { + this.wifiCandidateConfig.preSharedKey = value; + }) + } + .width('100%') + .margin({ top: '3%' }) + + + Row() { + Text('isHiddenSsid').fontSize('16fp').width('28%') + TextInput({ placeholder: $r('app.string.input_candidate_wifi_isHiddenSsid') }) + .placeholderColor(Color.Grey) + .placeholderFont({ size: '16fp' }) + .caretColor(Color.Blue) + .width('70%') + .fontSize('16fp') + .fontColor($r('app.color.title_black_color')) + .onChange((value: string) => { + this.wifiCandidateConfig.isHiddenSsid = parseInt(value, 10) === 1; + }) + } + .width('100%') + .margin({ top: '3%' }) + + Row() { + Text('securityType').fontSize('16fp').width('28%') + Column() { + Select([ + { value: 'WIFI_SEC_TYPE_INVALID' }, + { value: 'WIFI_SEC_TYPE_OPEN' }, + { value: 'WIFI_SEC_TYPE_PSK' }, + { value: 'WIFI_SEC_TYPE_SAE' } + ]) + .fontColor($r('app.color.title_black_color')) + .optionBgColor($r('app.color.input_background')) + .selectedOptionBgColor($r('app.color.input_background')) + .selectedOptionFontColor($r('app.color.input_background')) + .selected(0) + .value('WIFI_SEC_TYPE_INVALID') + .font({ size: 16 }) + .selectedOptionFont({ size: 17 }) + .optionFont({ size: 15 }) + .width('100%') + .onSelect((index: number) => { + this.wifiCandidateConfig.securityType = index; + }) + } + .width('70%') + .borderRadius(1) + } + .justifyContent(FlexAlign.Start) + .alignItems(VerticalAlign.Center) + .width('100%') + .margin({ top: '3%' }) + + Row() { + Button($r('app.string.confirm_button'))// .dialogButtonStyle() + .onClick(() => { + if(this.wifiCandidateConfig.ssid === '' || this.wifiCandidateConfig.preSharedKey === '') { + hilog.info(TAG, 'ssid || preSharedKey is null'); + promptAction.showToast({ message : 'ssid or preSharedKey is null' }) + return; + } + this.connectwifi(this.wifiCandidateConfig); + }) + .height('100%') + } + .width('70') + .height('6%') + .justifyContent(FlexAlign.SpaceBetween) + } + } + } + } \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/module.json5 b/ConnectivityKit/Wlan/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f2740de4e12488dbc998b6d84ca8709c002bff4f --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/module.json5 @@ -0,0 +1,84 @@ +/* + * 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": "MainAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "requestPermissions": [ + { + "name": "ohos.permission.GET_WIFI_INFO", + "reason": "$string:GET_WIFI_INFO", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + }, + }, + { + "name": "ohos.permission.SET_WIFI_INFO", + "reason": "$string:SET_WIFI_INFO", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.GET_WIFI_PEERS_MAC", + "reason": "$string:GET_WIFI_PEERS_MAC", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + }, + ], + "abilities": [ + { + "srcEntry": "./ets/entryability/EntryAbility.ets", + "name": "EntryAbility", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/element/color.json b/ConnectivityKit/Wlan/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..8919d0f5d480b0f118a27e07cf79019aeb1ae73a --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/resources/base/element/color.json @@ -0,0 +1,60 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + }, + { + "name": "index_bg", + "value": "#F5F5F5" + }, + { + "name": "button_color", + "value": "#0D9FFB" + }, + { + "name": "button_color1", + "value": "#007AFF" + }, + { + "name": "button_color2", + "value": "#D7ECF1" + }, + { + "name": "title_black_color", + "value": "#182431" + }, + { + "name": "cyan", + "value": "#70919F" + }, + { + "name": "spring", + "value": "#F5FFFA" + }, + { + "name": "moon", + "value": "#D7ECF1" + }, + { + "name": "main_blue", + "value": "#007DFF" + }, + { + "name": "index_background", + "value": "#E8E7EB" + }, + { + "name": "intput_background", + "value": "#D9B612" + }, + { + "name": "input_background", + "value": "#D9B612" + }, + { + "name": "text_color", + "value": "#8F8F8F" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/element/string.json b/ConnectivityKit/Wlan/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..3511e0933d77c6a5b80711513af7ec2cf54f262b --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/resources/base/element/string.json @@ -0,0 +1,156 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Wlan" + }, + { + "name": "entry_MainAbility", + "value": "eTSWLAN" + }, + { + "name": "description_mainability", + "value": "eTSWLAN Ability" + }, + { + "name": "cancel", + "value": "Cancel" + }, + { + "name": "sure", + "value": "Sure" + }, + { + "name": "wlan", + "value": "WLAN" + }, + { + "name": "available_wlan", + "value": "Available WLAN" + }, + { + "name": "wifi_List", + "value": "wifi_List" + }, + { + "name": "connected", + "value": "connected" + }, + { + "name": "ip_address", + "value": "IP address:" + }, + { + "name": "gate_way", + "value": "Gateway:" + }, + { + "name": "net_mask", + "value": "Netmask:" + }, + { + "name": "primary_dns", + "value": "Primary Dns IP address:" + }, + { + "name": "second_dns", + "value": "Second DNS IP address:" + }, + { + "name": "server_ip", + "value": "DHCP server IP:" + }, + { + "name": "lease_duration", + "value": "IP address lease duration:" + }, + { + "name": "country_code", + "value": "Country code:" + }, + { + "name": "infrastructure_feature", + "value": "Infrastructure Feature:" + }, + { + "name": "ghz_feature", + "value": "5 GHz Feature:" + }, + { + "name": "gas_anqp_feature", + "value": "GAS/ANQP Feature:" + }, + { + "name": "wifi_direct", + "value": "WiFi-Direct Feature:" + }, + { + "name": "soft_ap", + "value": "Soft AP Feature:" + }, + { + "name": "wifi_aware", + "value": "WiFi Aware Feature:" + }, + { + "name": "encryption", + "value": "encrypted" + }, + { + "name": "open", + "value": "open" + }, + { + "name": "location_permission", + "value": "Allow app to obtain device location information" + }, + { + "name": "approximately_location_permission", + "value": "Allow app to obtain device ambiguous location information" + }, + { + "name": "GET_WIFI_INFO", + "value": "Allow applications to obtain Wi Fi information" + }, + { + "name": "SET_WIFI_INFO", + "value": "Allow applications to configure Wi Fi devices" + }, + { + "name": "GET_WIFI_INFO_INTERNAL", + "value": "Allow system processes to obtain Wi Fi related parameters" + }, + { + "name": "GET_WIFI_PEERS_MAC", + "value": "Allow applications to obtain the MAC address of peer Wi Fi devices" + }, + { + "name": "GET_WIFI_LOCAL_MAC", + "value": "Allow applications to obtain the MAC address of local Wi Fi devices" + }, + { + "name": "GET_WIFI_CONFIG", + "value": "Allow applications to obtain Wi Fi configuration information" + }, + { + "name": "SET_WIFI_CONFIG", + "value": "Allow applications to configure Wi Fi information" + }, + { + "name": "MANAGE_WIFI_CONNECTION", + "value": "Allow applications to manage Wi Fi connections" + }, + { + "name": "MANAGE_WIFI_HOTSPOT", + "value": "Allow applications to turn on or off Wi Fi hotspots" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/media/about.png b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/about.png new file mode 100644 index 0000000000000000000000000000000000000000..2613fc352850e45f0582fa825183e3928cef3378 Binary files /dev/null and b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/about.png differ diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/media/ic_back.png b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/ic_back.png new file mode 100644 index 0000000000000000000000000000000000000000..9f793557fd1ba7a4941e2ba4dea6fc2316eb5f24 Binary files /dev/null and b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/ic_back.png differ diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/media/icon.png b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c Binary files /dev/null and b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/icon.png differ diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/media/lock.png b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/lock.png new file mode 100644 index 0000000000000000000000000000000000000000..b78d86d2fc3afcc542f069b75ada2338fcf1a71a Binary files /dev/null and b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/lock.png differ diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/media/wifi.png b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..7017ea920f2683095b49d9f8221e40d7697f9943 Binary files /dev/null and b/ConnectivityKit/Wlan/entry/src/main/resources/base/media/wifi.png differ diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/base/profile/main_pages.json b/ConnectivityKit/Wlan/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..ae818d5d433790df8603e9ed8d082b79f411f166 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,10 @@ +{ + "src": [ + "pages/Index", + "pages/AvailableWifi", + "pages/WifiConnect", + "pages/P2pTest", + "pages/P2pSetting", + "pages/AvailableP2p" + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/en_US/element/string.json b/ConnectivityKit/Wlan/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..53657655fc0157d5558c4210dc1a5f41095285c6 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,232 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Wlan" + }, + { + "name": "entry_MainAbility", + "value": "eTSWLAN" + }, + { + "name": "description_mainability", + "value": "eTSWLAN Ability" + }, + { + "name": "cancel", + "value": "Cancel" + }, + { + "name": "wlan", + "value": "WLAN" + }, + { + "name": "sure", + "value": "Sure" + }, + { + "name": "available_wlan", + "value": "Available WLAN" + }, + { + "name": "connected", + "value": "Connected" + }, + { + "name": "about", + "value": "About" + }, + { + "name": "ip_address", + "value": "IP address:" + }, + { + "name": "gate_way", + "value": "Gateway:" + }, + { + "name": "net_mask", + "value": "Netmask:" + }, + { + "name": "primary_dns", + "value": "Primary Dns IP address:" + }, + { + "name": "second_dns", + "value": "Second DNS IP address:" + }, + { + "name": "server_ip", + "value": "DHCP server IP:" + }, + { + "name": "lease_duration", + "value": "IP address lease duration:" + }, + { + "name": "country_code", + "value": "Country code:" + }, + { + "name": "infrastructure_feature", + "value": "Infrastructure Feature:" + }, + { + "name": "ghz_feature", + "value": "5 GHz Feature:" + }, + { + "name": "gas_anqp_feature", + "value": "GAS/ANQP Feature:" + }, + { + "name": "wifi_List", + "value": "wifi_List" + }, + { + "name": "getScanInfoList", + "value": "ȡɨ" + }, + { + "name": "wifi_Connect", + "value": "" + }, + { + "name": "cancel_button", + "value": "ȡ" + }, + { + "name": "confirm_button", + "value": "ȷ" + }, + { + "name": "input_candidate_wifi_bssid", + "value": "ѡWiFibssid(MAC) (ɲ)" + }, + { + "name": "input_candidate_wifi_preSharedKey", + "value": "ѡWiFi" + }, + { + "name": "input_candidate_wifi_isHiddenSsid", + "value": "10 (ɲ;1:ture,0:false)" + }, + { + "name": "add_task", + "value": "Ӻѡwifi" + }, + { + "name": "p2p_available", + "value": "Ե豸" + }, + { + "name": "p2p_test", + "value": "p2p" + }, + { + "name": "create_group_test", + "value": "Ⱥ" + }, + { + "name": "create_group", + "value": "Ⱥ" + }, + { + "name": "useful", + "value": "" + }, + { + "name": "p2pConnected", + "value": "" + }, + { + "name": "input_candidate_wifi", + "value": "ѡWiFi" + }, + { + "name": "input_candidate_wifi_ssid", + "value": "ѡWiFiSSID" + }, + { + "name": "p2p_Connect", + "value": "p2p" + }, + { + "name": "cancle_button", + "value": "cancle" + }, + { + "name": "wifi_direct", + "value": "WiFi-Direct Feature:" + }, + { + "name": "soft_ap", + "value": "Soft AP Feature:" + }, + { + "name": "wifi_aware", + "value": "WiFi Aware Feature:" + }, + { + "name": "encryption", + "value": "encrypted" + }, + { + "name": "open", + "value": "open" + }, + { + "name": "location_permission", + "value": "Allow app to obtain device location information" + }, + { + "name": "approximately_location_permission", + "value": "Allow app to obtain device ambiguous location information" + }, + { + "name": "GET_WIFI_INFO", + "value": "Allow applications to obtain Wi Fi information" + }, + { + "name": "SET_WIFI_INFO", + "value": "Allow applications to configure Wi Fi devices" + }, + { + "name": "GET_WIFI_INFO_INTERNAL", + "value": "Allow system processes to obtain Wi Fi related parameters" + }, + { + "name": "GET_WIFI_PEERS_MAC", + "value": "Allow applications to obtain the MAC address of peer Wi Fi devices" + }, + { + "name": "GET_WIFI_LOCAL_MAC", + "value": "Allow applications to obtain the MAC address of local Wi Fi devices" + }, + { + "name": "GET_WIFI_CONFIG", + "value": "Allow applications to obtain Wi Fi configuration information" + }, + { + "name": "SET_WIFI_CONFIG", + "value": "Allow applications to configure Wi Fi information" + }, + { + "name": "MANAGE_WIFI_CONNECTION", + "value": "Allow applications to manage Wi Fi connections" + }, + { + "name": "MANAGE_WIFI_HOTSPOT", + "value": "Allow applications to turn on or off Wi Fi hotspots" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/main/resources/zh_CN/element/string.json b/ConnectivityKit/Wlan/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..d8484995039bd0b90dfb845c4095af4da6a633b0 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,232 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Wlan" + }, + { + "name": "entry_MainAbility", + "value": "eTSWLAN" + }, + { + "name": "description_mainability", + "value": "eTSWLAN Ability" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "sure", + "value": "确定" + }, + { + "name": "wlan", + "value": "WLAN" + }, + { + "name": "available_wlan", + "value": "可用WLAN" + }, + { + "name": "connected", + "value": "已连接" + }, + { + "name": "about", + "value": "关于" + }, + { + "name": "ip_address", + "value": "IP地址:" + }, + { + "name": "gate_way", + "value": "网关:" + }, + { + "name": "net_mask", + "value": "掩码:" + }, + { + "name": "primary_dns", + "value": "主DNS服务器:" + }, + { + "name": "second_dns", + "value": "备DNS服务器:" + }, + { + "name": "server_ip", + "value": "DHCP服务端ip:" + }, + { + "name": "lease_duration", + "value": "IP地址租用时长:" + }, + { + "name": "country_code", + "value": "国家码:" + }, + { + "name": "infrastructure_feature", + "value": "基础结构模式特性:" + }, + { + "name": "ghz_feature", + "value": "5 GHz 宽带特性:" + }, + { + "name": "gas_anqp_feature", + "value": "GAS/ANQP特性:" + }, + { + "name": "wifi_List", + "value": "Wi-Fi 列表" + }, + { + "name": "getScanInfoList", + "value": "获取扫描结果" + }, + { + "name": "wifi_Connect", + "value": "建议网络连接" + }, + { + "name": "cancel_button", + "value": "取消" + }, + { + "name": "confirm_button", + "value": "确定" + }, + { + "name": "input_candidate_wifi_bssid", + "value": "输入候选WiFi的bssid(MAC) (可不填)" + }, + { + "name": "input_candidate_wifi_preSharedKey", + "value": "输入候选WiFi密码" + }, + { + "name": "input_candidate_wifi_isHiddenSsid", + "value": "输入1或0 (可不填;1:ture,0:false)" + }, + { + "name": "add_task", + "value": "添加候选wifi" + }, + { + "name": "p2p_available", + "value": "对等设备" + }, + { + "name": "p2p_test", + "value": "p2p测试" + }, + { + "name": "create_group_test", + "value": "创建群组测试" + }, + { + "name": "create_group", + "value": "创建群组" + }, + { + "name": "useful", + "value": "可用" + }, + { + "name": "p2pConnected", + "value": "已连接" + }, + { + "name": "input_candidate_wifi", + "value": "输入候选WiFi的配置" + }, + { + "name": "input_candidate_wifi_ssid", + "value": "输入候选WiFi的SSID" + }, + { + "name": "p2p_Connect", + "value": "p2p连接" + }, + { + "name": "cancle_button", + "value": "cancle" + }, + { + "name": "wifi_direct", + "value": "WiFi-Direct特性:" + }, + { + "name": "soft_ap", + "value": "Soft AP特性:" + }, + { + "name": "wifi_aware", + "value": "WiFi Aware组网特性:" + }, + { + "name": "encryption", + "value": "加密" + }, + { + "name": "open", + "value": "开放" + }, + { + "name": "location_permission", + "value": "允许应用获取设备位置信息" + }, + { + "name": "approximately_location_permission", + "value": "允许应用获取设备模糊位置信息" + }, + { + "name": "GET_WIFI_INFO", + "value": "允许应用获取Wi-Fi信息" + }, + { + "name": "SET_WIFI_INFO", + "value": "允许应用配置Wi-Fi设备" + }, + { + "name": "GET_WIFI_INFO_INTERNAL", + "value": "允许系统进程获取Wi-Fi相关参数" + }, + { + "name": "GET_WIFI_PEERS_MAC", + "value": "允许应用获取对端Wi-Fi设备的MAC地址" + }, + { + "name": "GET_WIFI_LOCAL_MAC", + "value": "允许应用获取本机的Wi-Fi设备的MAC地址" + }, + { + "name": "GET_WIFI_CONFIG", + "value": "允许应用获取Wi-Fi的配置信息" + }, + { + "name": "SET_WIFI_CONFIG", + "value": "允许应用配置Wi-Fi信息" + }, + { + "name": "MANAGE_WIFI_CONNECTION", + "value": "允许应用管理Wi-Fi的连接" + }, + { + "name": "MANAGE_WIFI_HOTSPOT", + "value": "允许应用开启或关闭Wi-Fi热点" + } + ] +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/mock/mock-config.json5 b/ConnectivityKit/Wlan/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fec94bcaee89632a26be6c4862a88acf88d0daad --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/ohosTest/ets/test/Ability.test.ets b/ConnectivityKit/Wlan/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ConnectivityKit/Wlan/entry/src/ohosTest/ets/test/List.test.ets b/ConnectivityKit/Wlan/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/ConnectivityKit/Wlan/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/ConnectivityKit/Wlan/entry/src/ohosTest/module.json5 b/ConnectivityKit/Wlan/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/ConnectivityKit/Wlan/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ConnectivityKit/Wlan/entry/src/test/List.test.ets b/ConnectivityKit/Wlan/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/ConnectivityKit/Wlan/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/ConnectivityKit/Wlan/entry/src/test/LocalUnit.test.ets b/ConnectivityKit/Wlan/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/ConnectivityKit/Wlan/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/ConnectivityKit/Wlan/hvigor/hvigor-config.json5 b/ConnectivityKit/Wlan/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..48fb346926eb36f8b2c028fd4319ac3e56165409 --- /dev/null +++ b/ConnectivityKit/Wlan/hvigor/hvigor-config.json5 @@ -0,0 +1,5 @@ +{ + "modelVersion": "5.0.5", + "dependencies": { + } +} diff --git a/ConnectivityKit/Wlan/hvigorfile.ts b/ConnectivityKit/Wlan/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..64b143a6ae9b2db7e61a01fbe50ae7b5634a80a1 --- /dev/null +++ b/ConnectivityKit/Wlan/hvigorfile.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { appTasks } from '@ohos/hvigor-ohos-plugin' + diff --git a/ConnectivityKit/Wlan/oh-package.json5 b/ConnectivityKit/Wlan/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5f609682201b4eeccf312f5e6781abddb98c23c7 --- /dev/null +++ b/ConnectivityKit/Wlan/oh-package.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.5", + "license": "ISC", + "devDependencies": { + "@ohos/hypium": "1.0.6" + }, + "name": "wlan", + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {}, +} diff --git a/ConnectivityKit/Wlan/ohosTest.md b/ConnectivityKit/Wlan/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..e02cd4bf9d24860a970a0dcdae8402b7dc317bc5 --- /dev/null +++ b/ConnectivityKit/Wlan/ohosTest.md @@ -0,0 +1,10 @@ +# P2P模式开发测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ------------ | ------------ | ------------------------------ | ------------ | -------- | -------- | +| 拉起应用 | 设备正常运行 |点击运行 | 成功拉起应用 | 否 | Pass | +| 主页点击create group按钮 | 打开WLAN,位于主页 |点击create group按钮 | 主页显示success文字 | 否 | Pass | +| 主页connect按钮点击 | 打开WLAN,点击create group按钮后,位于主页 |点击connect按钮 | 输出预期日志 | 否 | Pass | +| 主页delete group按钮点击 | 打开WLAN,点击create group按钮后,位于主页 |点击delete group按钮 | 主页显示的文字被清除 | 否 | Pass | \ No newline at end of file diff --git a/ConnectivityKit/Wlan/screenshots/GET_WIFI_PEERS_MAC.png b/ConnectivityKit/Wlan/screenshots/GET_WIFI_PEERS_MAC.png new file mode 100644 index 0000000000000000000000000000000000000000..9735598afc20df84495b15be119750bd92d62f87 Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/GET_WIFI_PEERS_MAC.png differ diff --git a/ConnectivityKit/Wlan/screenshots/connect_wifi.png b/ConnectivityKit/Wlan/screenshots/connect_wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..29cfe4907984c6cc08f7dbafe51e47e74a0bcb2b Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/connect_wifi.png differ diff --git a/ConnectivityKit/Wlan/screenshots/creatgroup.png b/ConnectivityKit/Wlan/screenshots/creatgroup.png new file mode 100644 index 0000000000000000000000000000000000000000..595e57bc6496d660ee664ea5cec294c43668cc4d Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/creatgroup.png differ diff --git a/ConnectivityKit/Wlan/screenshots/main.png b/ConnectivityKit/Wlan/screenshots/main.png new file mode 100644 index 0000000000000000000000000000000000000000..8c495d76df076285552397b93e61f7e45423dc15 Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/main.png differ diff --git a/ConnectivityKit/Wlan/screenshots/p2pconnect.png b/ConnectivityKit/Wlan/screenshots/p2pconnect.png new file mode 100644 index 0000000000000000000000000000000000000000..e97c119452864f0314a52a4214b3dad983277719 Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/p2pconnect.png differ diff --git a/ConnectivityKit/Wlan/screenshots/p2ptest.png b/ConnectivityKit/Wlan/screenshots/p2ptest.png new file mode 100644 index 0000000000000000000000000000000000000000..3253280d50a04e481c52386af3daaf838bb799e4 Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/p2ptest.png differ diff --git a/ConnectivityKit/Wlan/screenshots/wifi_list.png b/ConnectivityKit/Wlan/screenshots/wifi_list.png new file mode 100644 index 0000000000000000000000000000000000000000..b80efef376dc41afe8a990444e05dd5f612cc410 Binary files /dev/null and b/ConnectivityKit/Wlan/screenshots/wifi_list.png differ diff --git a/bluetoothSample/.gitignore b/bluetoothSample/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/bluetoothSample/.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/bluetoothSample/AppScope/app.json5 b/bluetoothSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..61caeed5dbf7384b2ef5286b72d2f4fa90ff6784 --- /dev/null +++ b/bluetoothSample/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.bluetoothsample", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/bluetoothSample/AppScope/resources/base/element/string.json b/bluetoothSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1407cd98b64bd01f972867509cd51773c70b1f73 --- /dev/null +++ b/bluetoothSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "bluetoothSample" + } + ] +} diff --git a/bluetoothSample/AppScope/resources/base/media/app_icon.png b/bluetoothSample/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/bluetoothSample/AppScope/resources/base/media/app_icon.png differ diff --git a/bluetoothSample/README.md b/bluetoothSample/README.md new file mode 100644 index 0000000000000000000000000000000000000000..46ad38cf598e77be8453c60ebb66e442c700650c --- /dev/null +++ b/bluetoothSample/README.md @@ -0,0 +1,153 @@ +# 蓝牙示例代码工程化 + +### 介绍 + +本示例为开发指南中[蓝牙服务开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/Readme-CN.md)章节中**蓝牙设置**,**广播与扫描**,**通用属性协议**示例代码的完整工程,该工程中展示的代码详细描述可查如下链接: + +[蓝牙设置](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/br-development-guide.md) +[广播与扫描](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/ble-development-guide.md) +[通用属性协议](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/connectivity/bluetooth/gatt-development-guide.md) + +### 效果预览 +|Scan界面| Bonded界面 | Adveriser界面| Switch界面| +|-------|---------|--------|----------| +| | | | | + +### 使用说明 + +1. 启动应用,蓝牙权限申请点击同意。 +2. 切换到SWITCH页面,单击开启蓝牙,等待上方蓝牙状态变为BlueTooth State: Connected。 +3. 在SCAN页面单击设置过滤参数,可以设置扫描的过滤参数。 +4. 单击开始扫描,设备开始扫描设备,扫描到的设备ID会以弹窗形式展示,单击刷新,可以更新下方的设备列表。 +5. 单击停止扫描,停止扫描设备。 +6. 单击设备列表里的connect,连接设备,设备信息会在上方循环播放展示。 +7. 切换GATT页面,填写读写特征值和描述符的过滤参数,上方输入框为写特征值和描述符的过滤参数。 +8. 单击发现服务,可以获取已连接设备的服务列表,获得的内容在上方显示。 +9. 单击写特征值或写描述符,根据上方过滤参数写入特征值和描述符。 +10. 单击读特征值或描述符,读取特征值和描述符,读取到的内容以弹窗形式显示。 +11. 单击断开连接,断开与当前设备的连接。 +12. 在Adveriser界面,单击注册服务,可以注册服务,单击注销服务,可以注销服务。 +13. 单击订阅读写特征值可以订阅读写特征值的操作。 +14. 单击设置广播内容,在打开的弹窗中设置广播的内容和参数。 +15. 单击开始广播,设备开始进行广播操作。 +16. 单击暂停广播,设备暂时停止广播。 +17. 单击继续广播,设备继续进行广播。 +18. 单击关闭广播,设备停止广播操作,关闭广播服务。 +19. 切换到SWITCH界面,单击关闭蓝牙,关闭设备的蓝牙服务。 + +### 工程目录 +``` ++--- src +| +--- main +| | +--- ets +| | | +--- bluetoothService +| | | | +--- BluetoothAdvertising.ets +| | | | +--- BluetoothScan.ets +| | | | +--- BluetoothSwitch.ets +| | | | +--- GattClientManager.ets +| | | | +--- GattServerManager.ets +| | | +--- common +| | | | +--- AdvertisingDialog.ets +| | | | +--- ScanData.ets +| | | | +--- ScanDialog.ets +| | | | +--- ToastReport.ets +| | | +--- entryability +| | | | +--- EntryAbility.ets +| | | +--- entrybackupability +| | | | +--- EntryBackupAbility.ets +| | | +--- pages +| | | | +--- Index.ets + +``` + +### 具体实现 + +#### 蓝牙设置 + +1. import需要的access模块。 + +2. 需要SystemCapability.Communication.Bluetooth.Core系统能力。 + +3. 开启蓝牙。 + +4. 关闭蓝牙。 + +5. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 + +6. 如何验证: 执行开启蓝牙代码,记录日志“bluetooth statues: STATE_ON”,则表示开启蓝牙成功。执行关闭蓝牙代码,记录日志“bluetooth statues: STATE_OFF”,则表示蓝牙关闭成功。 + +#### 广播与扫描开发指导 + +##### 开启/关闭广播 + +1. import需要的ble模块。 +2. 开启设备的蓝牙。 +3. 需要SystemCapability.Communication.Bluetooth.Core系统能力。 +4. 开启广播,对端设备扫描该广播。 +5. 关闭广播。 +6. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 + +##### 开启/关闭扫描 + +1. import需要的ble模块。 +2. 开启设备的蓝牙。 +3. 需要SystemCapability.Communication.Bluetooth.Core系统能力。 +4. 对端设备开启广播。 +5. 本端设备开启扫描,获取扫描结果。 +6. 关闭扫描。 +7. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 + +#### 通用属性协议开发指导 + +##### 连接server端读取和写入信息 + +1. import需要的ble模块。 +2. 创建gattClient实例对象。 +3. 连接gattServer。 +4. 读取gattServer的特征值和描述符。 +5. 向gattServer写入特征值和描述符。 +6. 断开连接,销毁gattClient实例。 +7. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 + +##### server端操作services和通知客户端信息 + +1. import需要的ble模块。 +2. 创建gattServer实例对象。 +3. 添加services信息。 +4. 当向gattServer写入特征值通知gattClient。 +5. 移除services信息。 +6. 注销gattServer实例。 +7. 错误码请参见[蓝牙服务子系统错误码](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-connectivity-kit/errorcode-bluetoothManager.md)。 + +### 相关权限 + +[ohos.permission.USE_BLUETOOTH](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissionuse_bluetooth) + +[ohos.permission.DISCOVER_BLUETOOTH](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all.md#ohospermissiondiscover_bluetooth) + +[ohos.permission.ACCESS_BLUETOOTH](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/AccessToken/permissions-for-all-user.md#ohospermissionaccess_bluetooth) +### 依赖 + +不涉及 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 + +3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo bluetoothSample/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/bluetoothSample/build-profile.json5 b/bluetoothSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..51fb5b5e20c1d0fee9e4950e526867440b4eb48f --- /dev/null +++ b/bluetoothSample/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.2(14)", + "targetSdkVersion": "5.0.2(14)", + "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/bluetoothSample/code-linter.json5 b/bluetoothSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/bluetoothSample/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/bluetoothSample/entry/.gitignore b/bluetoothSample/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/bluetoothSample/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/bluetoothSample/entry/build-profile.json5 b/bluetoothSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/bluetoothSample/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/bluetoothSample/entry/hvigorfile.ts b/bluetoothSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/bluetoothSample/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/bluetoothSample/entry/obfuscation-rules.txt b/bluetoothSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/oh-package.json5 b/bluetoothSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c9cb6c8174858277c9b0d465a51547dcab16d5ff --- /dev/null +++ b/bluetoothSample/entry/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothAdvertising.ets b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothAdvertising.ets new file mode 100644 index 0000000000000000000000000000000000000000..bcba2b8db0f36d93056e5cad460cf48707182874 --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothAdvertising.ets @@ -0,0 +1,184 @@ +/* + * 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 open_close_advertising] +import { ble } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ToastReport } from '../common/ToastReport'; + +const TAG: string = 'BleAdvertisingManager'; + +export class BleAdvertisingManager { + private advHandle: number = 0xFF; // default invalid value + private manufactureValueBuffer: Uint8Array = new Uint8Array(); + private serviceUuids: string = '00001888-0000-1000-8000-00805f9b34fb'; + private serviceBuffer = new Uint8Array(); + private manufactureId: number = 0; + private includeDeviceName: boolean = false; + public toastReport: ToastReport = new ToastReport(); + + public setAdvertisingParameter(manufactureId?: number, manufactureValueBuffer?: Uint8Array, + serviceUuids?: string, serviceBuffer?: Uint8Array, includeDeviceName?: boolean) { + if (manufactureId != undefined) { + this.manufactureId = Number(manufactureId); + console.info(TAG, 'manufactureId is ' + manufactureId); + } + if (manufactureValueBuffer != undefined) { + console.info(TAG, 'manufactureValueBuffer is ' + manufactureValueBuffer); + this.manufactureValueBuffer = manufactureValueBuffer; + } else { + + } + if (serviceUuids) { + this.serviceUuids = serviceUuids; + } + if (serviceBuffer) { + this.serviceBuffer = serviceBuffer; + } + this.includeDeviceName = includeDeviceName ? true : false; + } + + // 1 订阅广播状态 + public onAdvertisingStateChange() { + try { + ble.on('advertisingStateChange', (data: ble.AdvertisingStateChangeInfo) => { + console.info(TAG, 'bluetooth advertising state = ' + JSON.stringify(data)); + AppStorage.setOrCreate('advertiserState', data.state); + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 2 首次启动广播 + public async startAdvertising() { + // 2.1 设置广播发送的参数 + console.info('startAdvertising 2.1') + let setting: ble.AdvertiseSetting = { + interval: 160, + txPower: 0, + connectable: true + }; + // 2.2 构造广播数据 + console.info('startAdvertising 2.2') + let manufactureValueBuffer = new Uint8Array(4); + manufactureValueBuffer[0] = 1; + manufactureValueBuffer[1] = 2; + manufactureValueBuffer[2] = 3; + manufactureValueBuffer[3] = 4; + let serviceValueBuffer = new Uint8Array(4); + serviceValueBuffer[0] = 5; + serviceValueBuffer[1] = 6; + serviceValueBuffer[2] = 7; + serviceValueBuffer[3] = 8; + let manufactureDataUnit: ble.ManufactureData = { + manufactureId: this.manufactureId, + manufactureValue: this.manufactureValueBuffer.buffer + }; + let serviceDataUnit: ble.ServiceData = { + serviceUuid: this.serviceUuids, + serviceValue: this.serviceBuffer.buffer + }; + let advData: ble.AdvertiseData = { + serviceUuids: [this.serviceUuids], + manufactureData: [manufactureDataUnit], + serviceData: [serviceDataUnit], + includeDeviceName: this.includeDeviceName // 表示是否携带设备名,可选参数。注意带上设备名时广播包长度不能超出31个字节。 + }; + let advResponse: ble.AdvertiseData = { + serviceUuids: [this.serviceUuids], + manufactureData: [manufactureDataUnit], + serviceData: [serviceDataUnit] + }; + // 2.3 构造广播启动完整参数AdvertisingParams + console.info('startAdvertising 2.3') + let advertisingParams: ble.AdvertisingParams = { + advertisingSettings: setting, + advertisingData: advData, + advertisingResponse: advResponse, + duration: 0 // 可选参数,若大于0,则广播发送一段时间后,则会临时停止,可重新启动发送 + } + + // 2.4 首次启动广播,且获取所启动广播的标识ID + console.info('startAdvertising 2.4') + try { + this.onAdvertisingStateChange(); + this.advHandle = await ble.startAdvertising(advertisingParams); + this.toastReport.showResult('bluetooth startAdvertising start success'); + console.info('startAdvertising succeed'); + } catch (err) { + this.toastReport.showResult('bluetooth startAdvertising start fail'); + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 4 临时停止广播,该广播资源仍然存在 + public async disableAdvertising() { + // 4.1 构造临时停止广播参数 + console.info('disableAdvertising 4.1') + let advertisingDisableParams: ble.AdvertisingDisableParams = { + advertisingId: this.advHandle // 使用首次启动广播时获取到的广播标识ID + } + // 4.2 临时停止 + console.info('disableAdvertising 4.2') + try { + await ble.disableAdvertising(advertisingDisableParams); + this.toastReport.showResult('bluetooth disableAdvertising'); + console.info('bluetooth disableAdvertising success'); + } catch (err) { + this.toastReport.showResult('bluetooth disableAdvertising fail'); + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 5 再次启动广播 + public async enableAdvertising(enableDuration: number) { + // 5.1 构造临时启动广播参数 + console.info('enableAdvertising 5.1') + let advertisingEnableParams: ble.AdvertisingEnableParams = { + advertisingId: this.advHandle, // 使用首次启动广播时获取到的广播标识ID + duration: enableDuration + } + // 5.2 再次启动 + console.info('enableAdvertising 5.2') + try { + this.toastReport.showResult('bluetooth enableAdvertising continue'); + await ble.enableAdvertising(advertisingEnableParams); + } catch (err) { + this.toastReport.showResult('bluetooth enableAdvertising fail'); + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 6 完全关闭广播,释放广播资源 + public async stopAdvertising() { + try { + this.toastReport.showResult('bluetooth advertising stop success'); + await ble.stopAdvertising(this.advHandle); + ble.off('advertisingStateChange', (data: ble.AdvertisingStateChangeInfo) => { + console.info(TAG, 'bluetooth advertising state = ' + JSON.stringify(data)); + this.toastReport.showResult('bluetooth advertising stop'); + }); + } catch (err) { + this.toastReport.showResult('bluetooth advertising stop fail'); + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } +} + +let bleAdvertisingManager = new BleAdvertisingManager(); + +export default bleAdvertisingManager as BleAdvertisingManager; +// [End open_close_advertising] \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothScan.ets b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothScan.ets new file mode 100644 index 0000000000000000000000000000000000000000..8aa2cecd90b87c3bae89f8d6fc682c9d145093e4 --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothScan.ets @@ -0,0 +1,295 @@ +/* + * 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 open_close_scan] +import { ble } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ScanData } from '../common/ScanData'; +import { ToastReport } from '../common/ToastReport'; + +const TAG: string = 'BleScanManager'; + +const BLE_ADV_TYPE_FLAG = 0x01; +const BLE_ADV_TYPE_16_BIT_SERVICE_UUIDS_INCOMPLETE = 0x02; +const BLE_ADV_TYPE_16_BIT_SERVICE_UUIDS_COMPLETE = 0x03; +const BLE_ADV_TYPE_32_BIT_SERVICE_UUIDS_INCOMPLETE = 0x04; +const BLE_ADV_TYPE_32_BIT_SERVICE_UUIDS_COMPLETE = 0x05; +const BLE_ADV_TYPE_128_BIT_SERVICE_UUIDS_INCOMPLETE = 0x06; +const BLE_ADV_TYPE_128_BIT_SERVICE_UUIDS_COMPLETE = 0x07; +const BLE_ADV_TYPE_LOCAL_NAME_SHORT = 0x08; +const BLE_ADV_TYPE_LOCAL_NAME_COMPLETE = 0x09; +const BLE_ADV_TYPE_TX_POWER_LEVEL = 0x0A; +const BLE_ADV_TYPE_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14; +const BLE_ADV_TYPE_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15; +const BLE_ADV_TYPE_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F; +const BLE_ADV_TYPE_16_BIT_SERVICE_DATA = 0x16; +const BLE_ADV_TYPE_32_BIT_SERVICE_DATA = 0x20; +const BLE_ADV_TYPE_128_BIT_SERVICE_DATA = 0x21; +const BLE_ADV_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF; + +const BLUETOOTH_UUID_16_BIT_LENGTH = 2; +const BLUETOOTH_UUID_32_BIT_LENGTH = 4; +const BLUETOOTH_UUID_128_BIT_LENGTH = 16; + +const BLUETOOTH_MANUFACTURE_ID_LENGTH = 2; + +export class BleScanManager { + private interval: number = 0; + private manufactureId: number = 4567; + private deviceName: string | undefined = ''; + private deviceId: string | undefined = ''; + private scanDataList: ScanData[] = []; + public toastReport: ToastReport = new ToastReport(); + + public setScanParameter(interval?: string, manufactureId?: string, deviceName?: string | undefined, + deviceId?: string | undefined) { + if (interval != undefined) { + this.interval = Number(interval); + console.info(TAG, 'interval is' + interval); + } + if (manufactureId != undefined) { + console.info(TAG, 'manufactureId is' + manufactureId); + this.manufactureId = Number(manufactureId); + } + this.deviceName = deviceName; + this.deviceId = deviceId; + } + + public getScanData(): ScanData[] { + return this.scanDataList; + } + + // 1 订阅扫描结果 + public onScanResult() { + ble.on('BLEDeviceFind', (data: Array) => { + if (data.length > 0) { + console.info(TAG, 'BLE scan result = ' + data[0].deviceId); + this.parseScanResult(data[0].data); + // [StartExclude open_close_scan] + this.toastReport.showResult(data[0].deviceId); + if (!this.scanDataList.some(item => item.getDeviceName() === data[0].deviceName)) { + this.scanDataList.push(new ScanData(data[0].deviceId, data[0].deviceName, data[0].rssi, data[0].connectable, + new Uint8Array(data[0].data))); + } + // [EndExclude open_close_scan] + } + }); + } + + private parseScanResult(data: ArrayBuffer) { + let advData = new Uint8Array(data); + if (advData.byteLength == 0) { + console.warn(TAG, 'nothing, adv data length is 0'); + return; + } + console.info(TAG, 'advData: ' + JSON.stringify(advData)); + + let advFlags: number = -1; + let txPowerLevel: number = -1; + let localName: string = ''; + let serviceUuids: string[] = []; + let serviceSolicitationUuids: string[] = []; + let serviceDatas: Record = {}; + let manufactureSpecificDatas: Record = {}; + + let curPos = 0; + while (curPos < advData.byteLength) { + let length = advData[curPos++]; + if (length == 0) { + break; + } + let advDataLength = length - 1; + let advDataType = advData[curPos++]; + switch (advDataType) { + case BLE_ADV_TYPE_FLAG: + advFlags = advData[curPos]; + break; + case BLE_ADV_TYPE_LOCAL_NAME_SHORT: + case BLE_ADV_TYPE_LOCAL_NAME_COMPLETE: + localName = advData.slice(curPos, curPos + advDataLength).toString(); + break; + case BLE_ADV_TYPE_TX_POWER_LEVEL: + txPowerLevel = advData[curPos]; + break; + case BLE_ADV_TYPE_16_BIT_SERVICE_UUIDS_INCOMPLETE: + case BLE_ADV_TYPE_16_BIT_SERVICE_UUIDS_COMPLETE: + this.parseServiceUuid(BLUETOOTH_UUID_16_BIT_LENGTH, curPos, advDataLength, advData, serviceUuids); + break; + case BLE_ADV_TYPE_32_BIT_SERVICE_UUIDS_INCOMPLETE: + case BLE_ADV_TYPE_32_BIT_SERVICE_UUIDS_COMPLETE: + this.parseServiceUuid(BLUETOOTH_UUID_32_BIT_LENGTH, curPos, advDataLength, advData, serviceUuids); + break; + case BLE_ADV_TYPE_128_BIT_SERVICE_UUIDS_INCOMPLETE: + case BLE_ADV_TYPE_128_BIT_SERVICE_UUIDS_COMPLETE: + this.parseServiceUuid(BLUETOOTH_UUID_128_BIT_LENGTH, curPos, advDataLength, advData, serviceUuids); + break; + case BLE_ADV_TYPE_16_BIT_SERVICE_SOLICITATION_UUIDS: + this.parseServiceSolicitationUuid(BLUETOOTH_UUID_16_BIT_LENGTH, curPos, advDataLength, + advData, serviceSolicitationUuids); + break; + case BLE_ADV_TYPE_32_BIT_SERVICE_SOLICITATION_UUIDS: + this.parseServiceSolicitationUuid(BLUETOOTH_UUID_32_BIT_LENGTH, curPos, advDataLength, + advData, serviceSolicitationUuids); + break; + case BLE_ADV_TYPE_128_BIT_SERVICE_SOLICITATION_UUIDS: + this.parseServiceSolicitationUuid(BLUETOOTH_UUID_128_BIT_LENGTH, curPos, advDataLength, + advData, serviceSolicitationUuids); + break; + case BLE_ADV_TYPE_16_BIT_SERVICE_DATA: + this.parseServiceData(BLUETOOTH_UUID_16_BIT_LENGTH, curPos, advDataLength, advData, serviceDatas); + break; + case BLE_ADV_TYPE_32_BIT_SERVICE_DATA: + this.parseServiceData(BLUETOOTH_UUID_32_BIT_LENGTH, curPos, advDataLength, advData, serviceDatas); + break; + case BLE_ADV_TYPE_128_BIT_SERVICE_DATA: + this.parseServiceData(BLUETOOTH_UUID_128_BIT_LENGTH, curPos, advDataLength, advData, serviceDatas); + break; + case BLE_ADV_TYPE_MANUFACTURER_SPECIFIC_DATA: + this.parseManufactureData(curPos, advDataLength, advData, manufactureSpecificDatas); + break; + default: + break; + } + curPos += advDataLength; + } + } + + private parseServiceUuid(uuidLength: number, curPos: number, advDataLength: number, + advData: Uint8Array, serviceUuids: string[]) { + while (advDataLength > 0) { + let tmpData: Uint8Array = advData.slice(curPos, curPos + uuidLength); + serviceUuids.push(this.getUuidFromUint8Array(uuidLength, tmpData)); + advDataLength -= uuidLength; + curPos += uuidLength; + } + } + + private parseServiceSolicitationUuid(uuidLength: number, curPos: number, advDataLength: number, + advData: Uint8Array, serviceSolicitationUuids: string[]) { + while (advDataLength > 0) { + let tmpData: Uint8Array = advData.slice(curPos, curPos + uuidLength); + serviceSolicitationUuids.push(this.getUuidFromUint8Array(uuidLength, tmpData)); + advDataLength -= uuidLength; + curPos += uuidLength; + } + } + + private getUuidFromUint8Array(uuidLength: number, uuidData: Uint8Array): string { + let uuid = ''; + let temp: string = ''; + for (let i = uuidLength - 1; i > -1; i--) { + temp += uuidData[i].toString(16).padStart(2, '0'); + } + switch (uuidLength) { + case BLUETOOTH_UUID_16_BIT_LENGTH: + uuid = `0000${temp}-0000-1000-8000-00805F9B34FB`; + break; + case BLUETOOTH_UUID_32_BIT_LENGTH: + uuid = `${temp}-0000-1000-8000-00805F9B34FB`; + break; + case BLUETOOTH_UUID_128_BIT_LENGTH: + uuid = `${temp.substring(0, 8)}-${temp.substring(8, 12)}-${temp.substring(12, 16)}-${temp.substring(16, + 20)}-${temp.substring(20, 32)}`; + break; + default: + break; + } + return uuid; + } + + private parseServiceData(uuidLength: number, curPos: number, advDataLength: number, + advData: Uint8Array, serviceDatas: Record) { + let tmpUuid: Uint8Array = advData.slice(curPos, curPos + uuidLength); + let tmpValue: Uint8Array = advData.slice(curPos + uuidLength, curPos + advDataLength); + serviceDatas[tmpUuid.toString()] = tmpValue; + } + + private parseManufactureData(curPos: number, advDataLength: number, + advData: Uint8Array, manufactureSpecificDatas: Record) { + let manufactureId: number = (advData[curPos + 1] << 8) + advData[curPos]; + let tmpValue: Uint8Array = advData.slice(curPos + BLUETOOTH_MANUFACTURE_ID_LENGTH, curPos + advDataLength); + manufactureSpecificDatas[manufactureId] = tmpValue; + } + + // 2 开启扫描 + public startScan() { + console.info(TAG, 'startBleScan success 1'); + // 2.1 构造扫描过滤器,需要能够匹配预期的广播包内容 + let manufactureId = this.manufactureId; + let manufactureDataMask: Uint8Array = new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF]); + let scanFilter: ble.ScanFilter = { + // 根据业务实际情况定义过滤器 + manufactureId: manufactureId, + // manufactureData: manufactureData.buffer, + manufactureDataMask: manufactureDataMask.buffer, + }; + // [StartExclude open_close_scan] + if (this.deviceName) { + console.info('===lyk=== deviceName is not null ' + this.deviceName) + scanFilter.name = this.deviceName; + } + if (this.deviceId) { + scanFilter.deviceId = this.deviceId; + } + // [EndExclude open_close_scan] + + // 2.2 构造扫描参数 + let scanOptions: ble.ScanOptions = { + interval: this.interval, + dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER, + matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE, + } + try { + // [StartExclude open_close_scan] + this.scanDataList = []; + // [EndExclude open_close_scan] + this.onScanResult(); // 订阅扫描结果 + ble.startBLEScan([scanFilter], scanOptions); + // [StartExclude open_close_scan] + this.toastReport.showResult('startBleScan success'); + // [EndExclude open_close_scan] + console.info(TAG, 'startBleScan success'); + } catch (err) { + // [StartExclude open_close_scan] + this.toastReport.showResult('startBleScan fail'); + // [EndExclude open_close_scan] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 3 关闭扫描 + public stopScan() { + try { + ble.off('BLEDeviceFind', (data: Array) => { // 取消订阅扫描结果 + console.info(TAG, 'off success'); + }); + ble.stopBLEScan(); + // [StartExclude open_close_scan] + this.toastReport.showResult('stopBleScan success'); + // [EndExclude open_close_scan] + console.info(TAG, 'stopBleScan success'); + } catch (err) { + // [StartExclude open_close_scan] + this.toastReport.showResult('stopBleScan fail'); + // [EndExclude open_close_scan] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } +} + +let bleScanManager = new BleScanManager(); + +export default bleScanManager as BleScanManager; +// [End open_close_scan] diff --git a/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothSwitch.ets b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothSwitch.ets new file mode 100644 index 0000000000000000000000000000000000000000..5b10dd2adb8c4e4c2203f8d15408b98ee53e5e2e --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/bluetoothService/BluetoothSwitch.ets @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +// [Start open_close_bluetooth] +import { access } from '@kit.ConnectivityKit'; + +export class BluetoothSwitch { + public openBluetooth() { + + access.off('stateChange'); + access.enableBluetooth(); + access.on('stateChange', (data) => { + let btStateMessage = ''; + switch (data) { + case 0: + btStateMessage += 'STATE_OFF'; + break; + case 1: + btStateMessage += 'STATE_TURNING_ON'; + break; + case 2: + btStateMessage += 'STATE_ON'; + break; + case 3: + btStateMessage += 'STATE_TURNING_OFF'; + break; + case 4: + btStateMessage += 'STATE_BLE_TURNING_ON'; + break; + case 5: + btStateMessage += 'STATE_BLE_ON'; + break; + case 6: + btStateMessage += 'STATE_BLE_TURNING_OFF'; + break; + default: + btStateMessage += 'unknown status'; + break; + } + if (btStateMessage == 'STATE_ON') { + access.off('stateChange'); + } + console.info('bluetooth statues: ' + btStateMessage); + }); + } + + public closeBluetooth() { + access.off('stateChange'); + access.disableBluetooth(); + access.on('stateChange', (data) => { + let btStateMessage = ''; + switch (data) { + case 0: + btStateMessage += 'STATE_OFF'; + break; + case 1: + btStateMessage += 'STATE_TURNING_ON'; + break; + case 2: + btStateMessage += 'STATE_ON'; + break; + case 3: + btStateMessage += 'STATE_TURNING_OFF'; + break; + case 4: + btStateMessage += 'STATE_BLE_TURNING_ON'; + break; + case 5: + btStateMessage += 'STATE_BLE_ON'; + break; + case 6: + btStateMessage += 'STATE_BLE_TURNING_OFF'; + break; + default: + btStateMessage += 'unknown status'; + break; + } + if (btStateMessage == 'STATE_OFF') { + access.off('stateChange'); + } + }); + } +} +// [End open_close_bluetooth] \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/bluetoothService/GattClientManager.ets b/bluetoothSample/entry/src/main/ets/bluetoothService/GattClientManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..745998b1d900c8c1ac7fe3bd76253b7cadac20af --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/bluetoothService/GattClientManager.ets @@ -0,0 +1,405 @@ +/* + * 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 generic_attribute] +import { ble } from '@kit.ConnectivityKit'; +import { constant } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ToastReport } from '../common/ToastReport'; +import util from '@ohos.util'; + +const TAG: string = 'GattClientManager'; +// [StartExclude generic_attribute] +let encoder = new util.TextEncoder(); +// [EndExclude generic_attribute] + +export class GattData { + public serviceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; + public characteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; + public descriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; + public characteristicValue: string = ''; + public descriptorValue: string = ''; +} + +export class GattClientManager { + public device: string | undefined = undefined; + public gattClient: ble.GattClientDevice | undefined = undefined; + public connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; + public myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; + public myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; + public myDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902一般用于notification或者indication + public myCharacteristicValue: string = '' + public myDescriptorValue: string = '' + public serviceResult: string = ''; + public found: boolean = false; + public toastReport: ToastReport = new ToastReport(); + + // 构造BLEDescriptor + private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { + let descriptor: ble.BLEDescriptor = { + serviceUuid: this.myServiceUuid, + characteristicUuid: this.myCharacteristicUuid, + descriptorUuid: des, + descriptorValue: value + }; + return descriptor; + } + + // 构造BLECharacteristic + private initCharacteristic(): ble.BLECharacteristic { + let descriptors: ble.BLEDescriptor[] = []; + let desLength = this.myDescriptorValue.length; + let descBuffer = new ArrayBuffer(desLength); + let descValue = new Uint8Array(descBuffer); + encoder.encodeIntoUint8Array(this.myCharacteristicValue, descValue); + descriptors[0] = this.initDescriptor(this.myDescriptorUuid, descBuffer); + let length = this.myCharacteristicValue.length; + let charBuffer = new ArrayBuffer(length); + let charValue = new Uint8Array(charBuffer); + encoder.encodeIntoUint8Array(this.myCharacteristicValue, charValue); + let characteristic: ble.BLECharacteristic = { + serviceUuid: this.myServiceUuid, + characteristicUuid: this.myCharacteristicUuid, + characteristicValue: charBuffer, + descriptors: descriptors + }; + return characteristic; + } + + private logCharacteristic(char: ble.BLECharacteristic) { + let message = 'logCharacteristic uuid:' + char.characteristicUuid + '\n'; + let value = new Uint8Array(char.characteristicValue); + message += 'logCharacteristic value: '; + for (let i = 0; i < char.characteristicValue.byteLength; i++) { + message += value[i] + ' '; + } + console.info(TAG, message); + // [StartExclude generic_attribute] + this.toastReport.showResult(message); + // [EndExclude generic_attribute] + } + + private logDescriptor(des: ble.BLEDescriptor) { + let message = 'logDescriptor uuid:' + des.descriptorUuid + '\n'; + let value = new Uint8Array(des.descriptorValue); + message += 'logDescriptor value: '; + for (let i = 0; i < des.descriptorValue.byteLength; i++) { + message += value[i] + ' '; + } + console.info(TAG, message); + // [StartExclude generic_attribute] + this.toastReport.showResult(message); + // [EndExclude generic_attribute] + } + + private checkService(services: Array): boolean { + for (let i = 0; i < services.length; i++) { + if (services[i].serviceUuid != this.myServiceUuid) { + continue; + } + for (let j = 0; j < services[i].characteristics.length; j++) { + if (services[i].characteristics[j].characteristicUuid != this.myCharacteristicUuid) { + continue; + } + for (let k = 0; k < services[i].characteristics[j].descriptors.length; k++) { + if (services[i].characteristics[j].descriptors[k].descriptorUuid == this.myDescriptorUuid) { + console.info(TAG, 'find expected service from server'); + return true; + } + } + } + } + console.error(TAG, 'no expected service from server'); + return false; + } + + public getResult(): string { + return this.serviceResult; + } + + public setGattData(data: GattData) { + this.myServiceUuid = data.serviceUuid; + this.myCharacteristicUuid = data.characteristicUuid; + this.myDescriptorUuid = data.descriptorUuid; + this.myCharacteristicValue = data.characteristicValue; + this.myDescriptorValue = data.descriptorValue; + } + + // 1. 订阅连接状态变化事件 + public onGattClientStateChange() { + if (!this.gattClient) { + console.error(TAG, 'no gattClient'); + return; + } + try { + this.gattClient.on('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { + let state = ''; + switch (stateInfo.state) { + case 0: + state = 'DISCONNECTED'; + break; + case 1: + state = 'CONNECTING'; + break; + case 2: + state = 'CONNECTED'; + break; + case 3: + state = 'DISCONNECTING'; + break; + default: + state = 'undefined'; + break; + } + console.info(TAG, 'onGattClientStateChange: device=' + stateInfo.deviceId + ', state=' + state); + if (stateInfo.deviceId == this.device) { + this.connectState = stateInfo.state; + } + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 2. client端主动连接时调用 + public startConnect(peerDevice: string | undefined) { // 对端设备一般通过ble scan获取到 + if (this.connectState != constant.ProfileConnectionState.STATE_DISCONNECTED || peerDevice == undefined) { + console.error(TAG, 'startConnect failed'); + return; + } + console.info(TAG, 'startConnect ' + peerDevice); + this.device = peerDevice; + // 2.1 使用device构造gattClient,后续的交互都需要使用该实例 + this.gattClient = ble.createGattClientDevice(peerDevice); + try { + this.onGattClientStateChange(); // 2.2 订阅连接状态 + this.gattClient.connect(); // 2.3 发起连接 + // [StartExclude generic_attribute] + this.toastReport.showResult('startConnect success'); + console.info(TAG, 'startConnect success'); + // [EndExclude generic_attribute] + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('startConnect fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 3. client端连接成功后,需要进行服务发现 + public async discoverServices() { + if (!this.gattClient) { + console.info(TAG, 'no gattClient'); + return; + } + console.info(TAG, 'discoverServices'); + try { + await this.gattClient.getServices().then((result: Array) => { + console.info(TAG, 'getServices success: ' + JSON.stringify(result)); + // [StartExclude generic_attribute] + this.serviceResult = JSON.stringify(result); + this.toastReport.showResult('getServices success: ' + JSON.stringify(result)); + // [EndExclude generic_attribute] + this.found = this.checkService(result); // 要确保server端的服务内容有业务所需要的服务 + }); + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('getServices fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 4. 在确保拿到了server端的服务结果后,he + public readCharacteristicValue() { + if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { + console.error(TAG, 'no gattClient or not connected'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no gattClient or not connected'); + // [EndExclude generic_attribute] + return; + } + if (!this.found) { // 要确保server端有对应的characteristic + console.error(TAG, 'no characteristic from server'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no characteristic from server'); + // [EndExclude generic_attribute] + return; + } + + let characteristic = this.initCharacteristic(); + console.info(TAG, 'readCharacteristicValue'); + try { + this.gattClient.readCharacteristicValue(characteristic).then((outData: ble.BLECharacteristic) => { + this.logCharacteristic(outData); + }) + // [StartExclude generic_attribute] + this.toastReport.showResult('readCharacteristicValue success'); + // [EndExclude generic_attribute] + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('readCharacteristicValue fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 5. 在确保拿到了server端的服务结果后,写入server端特定服务的特征值时调用 + public writeCharacteristicValue() { + if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { + console.error(TAG, 'no gattClient or not connected'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no gattClient or not connected'); + // [EndExclude generic_attribute] + return; + } + if (!this.found) { // 要确保server端有对应的characteristic + console.error(TAG, 'no characteristic from server'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no characteristic from server'); + // [EndExclude generic_attribute] + return; + } + + let characteristic = this.initCharacteristic(); + console.info(TAG, 'writeCharacteristicValue'); + try { + this.gattClient.writeCharacteristicValue(characteristic, ble.GattWriteType.WRITE, (err) => { + if (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + return; + } + // [StartExclude generic_attribute] + this.toastReport.showResult('writeCharacteristicValue success'); + // [EndExclude generic_attribute] + console.info(TAG, 'writeCharacteristicValue success'); + }); + } catch (err) { + // [StartExclude generic_attribute] + console.info(TAG, 'writeCharacteristicValue fail'); + this.toastReport.showResult('writeCharacteristicValue fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 6. 在确保拿到了server端的服务结果后,读取server端特定服务的描述符时调用 + public readDescriptorValue() { + if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { + console.error(TAG, 'no gattClient or not connected'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no gattClient or not connected'); + // [EndExclude generic_attribute] + return; + } + if (!this.found) { // 要确保server端有对应的descriptor + console.error(TAG, 'no descriptor from server'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no descriptor from server'); + // [EndExclude generic_attribute] + return; + } + + let descBuffer = new ArrayBuffer(0); + let descriptor = this.initDescriptor(this.myDescriptorUuid, descBuffer); + console.info(TAG, 'readDescriptorValue'); + try { + this.gattClient.readDescriptorValue(descriptor).then((outData: ble.BLEDescriptor) => { + this.logDescriptor(outData); + }); + // [StartExclude generic_attribute] + this.toastReport.showResult('readDescriptorValue success'); + // [EndExclude generic_attribute] + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('readDescriptorValue fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 7. 在确保拿到了server端的服务结果后,写入server端特定服务的描述符时调用 + public writeDescriptorValue() { + if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { + console.error(TAG, 'no gattClient or not connected'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no gattClient or not connected'); + // [EndExclude generic_attribute] + return; + } + if (!this.found) { // 要确保server端有对应的descriptor + console.error(TAG, 'no descriptor from server'); + // [StartExclude generic_attribute] + this.toastReport.showResult('no descriptor from server'); + // [EndExclude generic_attribute] + return; + } + + let length = this.myDescriptorValue.length; + let descBuffer = new ArrayBuffer(length); + let descValue = new Uint8Array(descBuffer); + encoder.encodeIntoUint8Array(this.myDescriptorValue, descValue); + let descriptor = this.initDescriptor(this.myDescriptorUuid, descBuffer); + console.info(TAG, 'writeDescriptorValue'); + try { + this.gattClient.writeDescriptorValue(descriptor, (err) => { + if (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + return; + } + console.info(TAG, 'writeDescriptorValue success'); + // [StartExclude generic_attribute] + this.toastReport.showResult('writeDescriptorValue success'); + // [EndExclude generic_attribute] + }); + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('writeDescriptorValue fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 8.client端主动断开时调用 + public stopConnect() { + if (!this.gattClient || this.connectState != constant.ProfileConnectionState.STATE_CONNECTED) { + console.error(TAG, 'no gattClient or not connected'); + return; + } + + console.info(TAG, 'stopConnect ' + this.device); + try { + this.gattClient.disconnect(); // 8.1 断开连接 + this.gattClient.off('BLEConnectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { + }); + this.gattClient.close() // 8.2 如果不再使用此gattClient,则需要close + // [StartExclude generic_attribute] + this.toastReport.showResult('stopConnect success'); + // [EndExclude generic_attribute] + } catch (err) { + // [StartExclude generic_attribute] + this.toastReport.showResult('stopConnect fail'); + // [EndExclude generic_attribute] + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } +} + +let gattClientManager = new GattClientManager(); + +export default gattClientManager as GattClientManager; +// [End generic_attribute] \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/bluetoothService/GattServerManager.ets b/bluetoothSample/entry/src/main/ets/bluetoothService/GattServerManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..aa38c2fb43a87c6f629c9894e4e3283cdc51546e --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/bluetoothService/GattServerManager.ets @@ -0,0 +1,297 @@ +/* + * 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 gatt_server_manage] +import { ble } from '@kit.ConnectivityKit'; +import { constant } from '@kit.ConnectivityKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { ToastReport } from '../common/ToastReport' + +const TAG: string = 'GattServerManager'; + +export class GattServerManager { + public gattServer: ble.GattServer = ble.createGattServer(); + public connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; + public myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; + public myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; + public myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902一般用于notification或者indication + public mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; + public toastReport: ToastReport = new ToastReport(); + + // 构造BLEDescriptor + private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { + let descriptor: ble.BLEDescriptor = { + serviceUuid: this.myServiceUuid, + characteristicUuid: this.myCharacteristicUuid, + descriptorUuid: des, + descriptorValue: value + }; + return descriptor; + } + + // 构造BLECharacteristic + private initCharacteristic(): ble.BLECharacteristic { + let descriptors: ble.BLEDescriptor[] = []; + let descBuffer = new ArrayBuffer(2); + let descValue = new Uint8Array(descBuffer); + descValue[0] = 31; + descValue[1] = 32; + descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); + descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); + let charBuffer = new ArrayBuffer(2); + let charValue = new Uint8Array(charBuffer); + charValue[0] = 21; + charValue[1] = 22; + let characteristic: ble.BLECharacteristic = { + serviceUuid: this.myServiceUuid, + characteristicUuid: this.myCharacteristicUuid, + characteristicValue: charBuffer, + descriptors: descriptors + }; + return characteristic; + } + + // 1. 订阅连接状态变化事件 + public onGattServerStateChange() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + try { + this.gattServer.on('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { + let state = ''; + switch (stateInfo.state) { + case 0: + state = 'DISCONNECTED'; + break; + case 1: + state = 'CONNECTING'; + break; + case 2: + state = 'CONNECTED'; + break; + case 3: + state = 'DISCONNECTING'; + break; + default: + state = 'undefined'; + break; + } + console.info(TAG, 'onGattServerStateChange: device=' + stateInfo.deviceId + ', state=' + state); + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 2. server端注册服务时调用 + public registerServer() { + let characteristics: ble.BLECharacteristic[] = []; + let characteristic = this.initCharacteristic(); + characteristics.push(characteristic); + let gattService: ble.GattService = { + serviceUuid: this.myServiceUuid, + isPrimary: true, + characteristics: characteristics + }; + + console.info(TAG, 'registerServer ' + this.myServiceUuid); + try { + // this.gattServer = ble.createGattServer(); 初始化时已经构造,去除报错// 2.1 构造gattServer,后续的交互都需要使用该实例 + this.onGattServerStateChange(); // 2.2 订阅连接状态 + this.gattServer.addService(gattService); + this.toastReport.showResult('registerServer success'); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + this.toastReport.showResult('registerServer failed'); + } + } + + // 3. 订阅来自gattClient的读取特征值请求时调用 + public onCharacteristicRead() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + + console.info(TAG, 'onCharacteristicRead'); + try { + this.gattServer.on('characteristicRead', (charReq: ble.CharacteristicReadRequest) => { + let deviceId: string = charReq.deviceId; + let transId: number = charReq.transId; + let offset: number = charReq.offset; + console.info(TAG, 'receive characteristicRead'); + let rspBuffer = new ArrayBuffer(2); + let rspValue = new Uint8Array(rspBuffer); + rspValue[0] = 21; + rspValue[1] = 22; + let serverResponse: ble.ServerResponse = { + deviceId: deviceId, + transId: transId, + status: 0, // 0表示成功 + offset: offset, + value: rspBuffer + }; + + try { + this.gattServer.sendResponse(serverResponse); + } catch (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 4. 订阅来自gattClient的写入特征值请求时调用 + public onCharacteristicWrite() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + + console.info(TAG, 'onCharacteristicWrite'); + try { + this.gattServer.on('characteristicWrite', (charReq: ble.CharacteristicWriteRequest) => { + let deviceId: string = charReq.deviceId; + let transId: number = charReq.transId; + let offset: number = charReq.offset; + console.info(TAG, 'receive characteristicWrite: needRsp=' + charReq.needRsp); + if (!charReq.needRsp) { + return; + } + let rspBuffer = new ArrayBuffer(0); + let serverResponse: ble.ServerResponse = { + deviceId: deviceId, + transId: transId, + status: 0, // 0表示成功 + offset: offset, + value: rspBuffer + }; + + try { + this.gattServer.sendResponse(serverResponse); + } catch (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 5. 订阅来自gattClient的读取描述符请求时调用 + public onDescriptorRead() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + + console.info(TAG, 'onDescriptorRead'); + try { + this.gattServer.on('descriptorRead', (desReq: ble.DescriptorReadRequest) => { + let deviceId: string = desReq.deviceId; + let transId: number = desReq.transId; + let offset: number = desReq.offset; + console.info(TAG, 'receive descriptorRead'); + let rspBuffer = new ArrayBuffer(2); + let rspValue = new Uint8Array(rspBuffer); + rspValue[0] = 31; + rspValue[1] = 32; + let serverResponse: ble.ServerResponse = { + deviceId: deviceId, + transId: transId, + status: 0, // 0表示成功 + offset: offset, + value: rspBuffer + }; + + try { + this.gattServer.sendResponse(serverResponse); + } catch (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 6. 订阅来自gattClient的写入描述符请求时调用 + public onDescriptorWrite() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + + console.info(TAG, 'onDescriptorWrite'); + try { + this.gattServer.on('descriptorWrite', (desReq: ble.DescriptorWriteRequest) => { + let deviceId: string = desReq.deviceId; + let transId: number = desReq.transId; + let offset: number = desReq.offset; + console.info(TAG, 'receive descriptorWrite: needRsp=' + desReq.needRsp); + if (!desReq.needRsp) { + return; + } + let rspBuffer = new ArrayBuffer(0); + let serverResponse: ble.ServerResponse = { + deviceId: deviceId, + transId: transId, + status: 0, // 0表示成功 + offset: offset, + value: rspBuffer + }; + + try { + this.gattServer.sendResponse(serverResponse); + } catch (err) { + console.error(TAG, + 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + }); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } + + // 7. server端删除服务,不再使用时调用 + public unRegisterServer() { + if (!this.gattServer) { + console.error(TAG, 'no gattServer'); + return; + } + + console.info(TAG, 'unRegisterServer ' + this.myServiceUuid); + try { + this.gattServer.removeService(this.myServiceUuid); // 7.1 删除服务 + this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 取消订阅连接状态 + }); + this.gattServer.close() // 7.3 如果不再使用此gattServer,则需要close + this.toastReport.showResult('unRegisterServer'); + } catch (err) { + console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); + } + } +} + +let gattServerManager = new GattServerManager(); + +export default gattServerManager as GattServerManager; +// [End gatt_server_manage] \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/common/AdvertisingDialog.ets b/bluetoothSample/entry/src/main/ets/common/AdvertisingDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..5fe1d7d47cefc85fa90a9a96ba9c99fe3a30b0ca --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/common/AdvertisingDialog.ets @@ -0,0 +1,159 @@ +/* + * 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 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 { util } from '@kit.ArkTS'; + +@CustomDialog +@Component +export struct AdvertisingDialog { + @Link textValueOfAdvManufactureId: string; + @Link inputValueOfAdvManufactureId: string; + @Link textValueOfAdvManufactureValueBuffer: string; + @Link inputValueOfAdvManufactureValueBuffer: Uint8Array; + @Link textValueOfAdvServiceUuids: string; + @Link inputValueOfAdvServiceUuids: string; + @Link textValueOfAdvServiceBuffer: string; + @Link inputValueOfAdvServiceBuffer: Uint8Array; + @Link textValueOfAdvIncludeDeviceName: string; + @Link inputValueOfAdvIncludeDeviceName: boolean; + decoder = new util.TextDecoder(); + controller?: CustomDialogController + cancel: () => void = () => { + } + confirm: () => void = () => { + } + + build() { + Column() { + Text('set advertising parameters').fontSize(20).margin({ top: 10, bottom: 10 }); + Row() { + Text('ManufactureValueBuffer') + .margin(5) + .width('30%') + TextInput({ text: this.textValueOfAdvManufactureValueBuffer }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfAdvManufactureValueBuffer = value; + }) + .margin(5) + } + + Row() { + Text('manufactureId') + .width('30%') + .margin(5) + TextInput({ text: this.textValueOfAdvManufactureId }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfAdvManufactureId = value; + }) + .margin(5) + } + + Row() { + Text('serviceBuffer') + .width('30%') + .margin(5) + TextInput({ text: this.textValueOfAdvServiceBuffer }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfAdvServiceBuffer = value; + }) + .margin(5) + } + + Row() { + Text('serviceUuids') + .width('30%') + .margin(5) + TextInput({ text: this.textValueOfAdvServiceUuids }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfAdvServiceUuids = value; + }) + .margin(5) + } + + Row() { + Text('enableIncludeDeviceName') + .width('30%') + .margin(5) + TextInput({ text: this.textValueOfAdvIncludeDeviceName }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfAdvIncludeDeviceName = value; + }) + .margin(5) + } + + + Flex({ justifyContent: FlexAlign.SpaceAround }) { + Button('cancel') + .onClick(() => { + if (this.controller != undefined) { + this.controller.close(); + this.cancel(); + } + }).backgroundColor(0xffffff).fontColor(Color.Black) + + Button('clean up') + .onClick(() => { + this.textValueOfAdvManufactureValueBuffer = ''; + this.textValueOfAdvManufactureId = ''; + this.textValueOfAdvServiceUuids = ''; + this.textValueOfAdvServiceBuffer = ''; + this.textValueOfAdvIncludeDeviceName = ''; + this.inputValueOfAdvManufactureValueBuffer = new Uint8Array(0); + this.inputValueOfAdvManufactureId = ''; + this.inputValueOfAdvServiceUuids = '00001888-0000-1000-8000-00805f9b34fb'; + this.inputValueOfAdvServiceBuffer = new Uint8Array(0); + this.inputValueOfAdvIncludeDeviceName = false; + }).backgroundColor(0xffffff).fontColor(Color.Red) + + Button('confirm') + .onClick(() => { + if (this.controller != undefined) { + let manufactureValueBuffer = new Uint8Array(this.textValueOfAdvManufactureValueBuffer.length); + for (let i = 0; i < this.textValueOfAdvManufactureValueBuffer.length; i++) { + manufactureValueBuffer[i] = parseInt(this.textValueOfAdvManufactureValueBuffer[i], 10); + } + let serviceBuffer = new Uint8Array(this.textValueOfAdvServiceBuffer.length); + for (let i = 0; i < this.textValueOfAdvManufactureValueBuffer.length; i++) { + manufactureValueBuffer[i] = parseInt(this.textValueOfAdvManufactureValueBuffer[i], 10); + } + this.inputValueOfAdvServiceBuffer = serviceBuffer; + this.inputValueOfAdvManufactureValueBuffer = manufactureValueBuffer; + this.inputValueOfAdvManufactureId = this.textValueOfAdvManufactureId; + if (this.textValueOfAdvServiceUuids) { + this.inputValueOfAdvServiceUuids = this.textValueOfAdvServiceUuids; + } + if (this.textValueOfAdvIncludeDeviceName) { + this.inputValueOfAdvIncludeDeviceName = true; + } else { + this.inputValueOfAdvIncludeDeviceName = false; + } + this.controller.close(); + this.confirm(); + } + }).backgroundColor(0xffffff).fontColor(Color.Red) + }.margin({ bottom: 10 }) + }.borderRadius(10) + } +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/common/ScanData.ets b/bluetoothSample/entry/src/main/ets/common/ScanData.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c5d3b83333bac97a2ca46df7aa81a78ef4bffee --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/common/ScanData.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ScanData { + private deviceId: string = ''; + private deviceName: string = ''; + private rssi: number = 0; + private connectable: boolean = false; + private data: Uint8Array = new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF]); + + constructor(deviceId: string = '', deviceName: string = 'null', rssi: number = 0, connectable: boolean = false, + data: Uint8Array = new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF])) { + this.deviceId = deviceId; + this.deviceName = deviceName; + this.rssi = rssi; + this.connectable = connectable; + this.data = data; + } + + public setDeviceId(deviceId: string) { + this.deviceId = deviceId; + } + + public setData(data: Uint8Array) { + this.data = data; + } + + public getDeviceId(): string { + return this.deviceId; + } + + public getData(): Uint8Array { + return this.data; + } + + public setDeviceName(deviceName: string) { + this.deviceName = deviceName; + } + + public getDeviceName(): string { + return this.deviceName; + } + + public setRssi(rssi: number) { + this.rssi = rssi; + } + + public getRssi(): number { + return this.rssi; + } + + public setConnectable(connectable: boolean) { + this.connectable = connectable; + } + + public getConnectable(): boolean { + return this.connectable; + } +} + +let scanData = new ScanData(); + +export default scanData as ScanData; + diff --git a/bluetoothSample/entry/src/main/ets/common/ScanDialog.ets b/bluetoothSample/entry/src/main/ets/common/ScanDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..a5d99a4f8d98f5798269e6f696772a918b15a5fa --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/common/ScanDialog.ets @@ -0,0 +1,120 @@ +/* + * 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. + */ + +@CustomDialog +@Component +export struct ScanDialog { + @Link textValueOfInterval: string; + @Link inputValueOfInterval: string; + @Link textValueOfManufactureId: string; + @Link inputValueOfManufactureId: string; + @Link textValueOfDeviceName: string; + @Link inputValueOfDeviceName: string; + @Link textValueOfDeviceId: string; + @Link inputValueOfDeviceId: string; + controller?: CustomDialogController + cancel: () => void = () => { + } + confirm: () => void = () => { + } + + build() { + Column() { + Text('set scan filtering parameters').fontSize(20).margin({ top: 10, bottom: 10 }); + Row() { + Text('interval') + .width('30%') + .margin(5) + TextInput({ placeholder: 'default is 0', text: this.textValueOfInterval }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfInterval = value; + }) + + } + + Row() { + Text('manufactureId') + .width('30%') + .margin(5) + TextInput({ placeholder: 'default is 4567', text: this.textValueOfManufactureId }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfManufactureId = value; + }) + } + + Row() { + Text('deviceName') + .width('30%') + .margin(5) + TextInput({ placeholder: 'default is \'\'', text: this.textValueOfDeviceName }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfDeviceName = value; + }) + } + + Row() { + Text('deviceId') + .width('30%') + .margin(5) + TextInput({ placeholder: 'default is \'\'', text: this.textValueOfDeviceId }) + .height(40) + .width('65%') + .onChange((value: string) => { + this.textValueOfDeviceId = value; + }) + } + + Flex({ justifyContent: FlexAlign.SpaceAround }) { + Button('cancel') + .onClick(() => { + if (this.controller != undefined) { + this.controller.close(); + this.cancel(); + } + }).backgroundColor(0xffffff).fontColor(Color.Black) + + Button('clean up') + .onClick(() => { + this.textValueOfInterval = ''; + this.inputValueOfInterval = '0'; + this.textValueOfManufactureId = ''; + this.inputValueOfManufactureId = '4567'; + this.textValueOfDeviceName = ''; + this.inputValueOfDeviceName = ''; + this.textValueOfDeviceId = ''; + this.inputValueOfDeviceId = ''; + }).backgroundColor(0xffffff).fontColor(Color.Red) + + Button('confirm') + .onClick(() => { + if (this.controller != undefined) { + this.inputValueOfInterval = this.textValueOfInterval; + this.inputValueOfManufactureId = this.textValueOfManufactureId; + this.inputValueOfDeviceName = this.textValueOfDeviceName; + this.inputValueOfDeviceId = this.textValueOfDeviceId; + this.controller.close(); + this.confirm(); + } + }).backgroundColor(0xffffff).fontColor(Color.Red) + }.margin({ bottom: 10 }) + }.borderRadius(10) + } +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/common/ToastReport.ets b/bluetoothSample/entry/src/main/ets/common/ToastReport.ets new file mode 100644 index 0000000000000000000000000000000000000000..80c12c4a9c04c5a82e2ed4e2278f2eceee52c93f --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/common/ToastReport.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { promptAction } from '@kit.ArkUI' + +export class ToastReport { + public showResult(message: string) { + promptAction.showToast({ + message: message, + duration: 2000, + showMode: promptAction.ToastShowMode.DEFAULT, + bottom: 80 + }) + } +} + +let toastReport = new ToastReport(); + +export default toastReport as ToastReport; \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/entryability/EntryAbility.ets b/bluetoothSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..6c3ac9ef7691afaed75b57159c9f757ab0f65208 --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,83 @@ +/* + * 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 from '@ohos.app.ability.AbilityConstant'; +import hilog from '@ohos.hilog'; +import UIAbility from '@ohos.app.ability.UIAbility'; +import Want from '@ohos.app.ability.Want'; +import window from '@ohos.window'; +import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl'; +import { BusinessError } from '@ohos.base'; + +const permissions: Permissions[] = ['ohos.permission.ACCESS_BLUETOOTH']; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + let context: Context = this.context; + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); + // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 + + atManager.requestPermissionsFromUser(context, permissions).then((data: PermissionRequestResult) => { + let grantStatus: number[] = data.authResults; + let length: number = grantStatus.length; + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // 用户授权,可以继续访问目标操作 + } else { + // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 + return; + } + } + // 授权成功 + }).catch((err: BusinessError) => { + console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); + }) + + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/bluetoothSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/bluetoothSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/ets/pages/Index.ets b/bluetoothSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..c4d89de113d5f77385eb2659cafc3d5209f45036 --- /dev/null +++ b/bluetoothSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,532 @@ +/* + * 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 { BleAdvertisingManager } from '../bluetoothService/BluetoothAdvertising'; +import { BleScanManager } from '../bluetoothService/BluetoothScan'; +import { BluetoothSwitch } from '../bluetoothService/BluetoothSwitch' +import { GattClientManager, GattData } from '../bluetoothService/GattClientManager'; +import { GattServerManager } from '../bluetoothService/GattServerManager'; +import { ScanData } from '../common/ScanData'; +import { ScanDialog } from '../common/ScanDialog'; +import { AdvertisingDialog } from '../common/AdvertisingDialog'; +import access from '@ohos.bluetooth.access'; +import { ToastReport } from '../common/ToastReport'; +import { ble } from '@kit.ConnectivityKit'; +import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit'; + + +@Entry +@Component +struct bluetoothSample { + private bluetoothSwitch: BluetoothSwitch = new BluetoothSwitch(); + private bleScanManager: BleScanManager = new BleScanManager(); + private bleAdvertisingManager: BleAdvertisingManager = new BleAdvertisingManager(); + private gattServerManager: GattServerManager = new GattServerManager(); + private gattClientManager: GattClientManager = new GattClientManager(); + @State scanData: ScanData[] = []; + @State textValueOfDeviceName: string | undefined = ''; + @State inputValueOfDeviceName: string | undefined = ''; + @State textValueOfDeviceId: string | undefined = ''; + @State inputValueOfDeviceId: string | undefined = ''; + @State scanFlag: Boolean = true; + @State textValueOfInterval: string = ''; + @State inputValueOfInterval: string = ''; + @State textValueOfManufactureId: string = ''; + @State textValueOfAdvManufactureId: string = ''; + @State inputValueOfManufactureId: string = ''; + @State inputValueOfAdvManufactureId: string = ''; + @State textValueOfManufactureValueBuffer: string = ''; + @State textValueOfAdvManufactureValueBuffer: string = ''; + @State inputValueOfAdvManufactureValueBuffer: Uint8Array = new Uint8Array; + @State inputValueOfAdvServiceBuffer: Uint8Array = new Uint8Array; + @State inputValueOfAdvServiceUuids: string = ''; + @State inputValueOfAdvIncludeDeviceName: boolean = false; + @State textValueOfAdvIncludeDeviceName: string = ''; + @State textValueOfAdvServiceBuffer: string = ''; + @State textValueOfAdvServiceUuids: string = ''; + @State currentIndex: number = 0; + @State gattState: number = 0; + @State serviceResult: string = ''; + @State refresh: boolean = false; + @State marText: string = ''; + gattData: GattData = new GattData(); + connectDeviceId: string = ''; + scroller: Scroller = new Scroller(); + @StorageLink('advertiserState') @Watch('onAdvertiserStateChange') advertiserState: ble.AdvertisingState = + ble.AdvertisingState.STOPPED; + + onAdvertiserStateChange() { + console.info(`onAdvertiserStateChange: advertiserState = ${JSON.stringify(this.advertiserState)}`) + } + + getAdvertiserStateDescription(): ResourceStr { + let description = 'Stopped' + switch (this.advertiserState) { + case ble.AdvertisingState.STARTED: + description = 'Started'; + break + case ble.AdvertisingState.ENABLED: + description = 'Enable'; + break + case ble.AdvertisingState.DISABLED: + description = 'Disabled'; + break + case ble.AdvertisingState.STOPPED: + description = 'Stopped'; + break + } + return description + } + + @Builder + tabBuilder(title: ResourceStr, targetIndex: number) { + Column() { + Text(title) + .fontColor(this.currentIndex === targetIndex ? '#F111C1' : '#6B6B6B') + } + } + + @State state: number = access.getState(); + + public FlushBlueToothState(): access.BluetoothState { + return this.state = access.getState(); + } + + advDialogController: CustomDialogController | null = new CustomDialogController({ + builder: AdvertisingDialog({ + cancel: () => { + this.onCancel() + }, + confirm: () => { + this.onAccept() + }, + textValueOfAdvManufactureId: $textValueOfAdvManufactureId, + inputValueOfAdvManufactureId: $inputValueOfAdvManufactureId, + textValueOfAdvManufactureValueBuffer: $textValueOfAdvManufactureValueBuffer, + inputValueOfAdvManufactureValueBuffer: $inputValueOfAdvManufactureValueBuffer, + textValueOfAdvServiceUuids: $textValueOfAdvServiceUuids, + inputValueOfAdvServiceUuids: $inputValueOfAdvServiceUuids, + textValueOfAdvServiceBuffer: $textValueOfAdvServiceBuffer, + inputValueOfAdvServiceBuffer: $inputValueOfAdvServiceBuffer, + textValueOfAdvIncludeDeviceName: $textValueOfAdvIncludeDeviceName, + inputValueOfAdvIncludeDeviceName: $inputValueOfAdvIncludeDeviceName + }), + cancel: this.exitApp, + autoCancel: true, + onWillDismiss: (dismissDialogAction: DismissDialogAction) => { + console.info('reason=' + JSON.stringify(dismissDialogAction.reason)) + console.log('dialog onWillDismiss') + if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { + dismissDialogAction.dismiss() + } + if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { + dismissDialogAction.dismiss() + } + }, + alignment: DialogAlignment.Top, + offset: { dx: 0, dy: -20 }, + gridCount: 4, + customStyle: false, + cornerRadius: 10, + }) + scanDialogController: CustomDialogController | null = new CustomDialogController({ + builder: ScanDialog({ + cancel: () => { + this.onCancel() + }, + confirm: () => { + this.onAccept() + }, + textValueOfInterval: $textValueOfInterval, + inputValueOfInterval: $inputValueOfInterval, + textValueOfManufactureId: $textValueOfManufactureId, + inputValueOfManufactureId: $inputValueOfManufactureId, + textValueOfDeviceName: $textValueOfDeviceName, + inputValueOfDeviceName: $inputValueOfDeviceName, + textValueOfDeviceId: $textValueOfDeviceId, + inputValueOfDeviceId: $inputValueOfDeviceId, + }), + cancel: this.exitApp, + autoCancel: true, + onWillDismiss: (dismissDialogAction: DismissDialogAction) => { + console.info('reason=' + JSON.stringify(dismissDialogAction.reason)) + console.log('dialog onWillDismiss') + if (dismissDialogAction.reason == DismissReason.PRESS_BACK) { + dismissDialogAction.dismiss() + } + if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) { + dismissDialogAction.dismiss() + } + }, + alignment: DialogAlignment.Top, + offset: { dx: 0, dy: -20 }, + gridCount: 4, + customStyle: false, + cornerRadius: 10, + }) + + aboutToDisappear() { + this.scanDialogController = null + } + + onCancel() { + } + + onAccept() { + } + + exitApp() { + } + + build() { + Column() { + Row() { + Text('Bluetooth') + .width('100%') + .textAlign(TextAlign.Center) + .fontSize(30) + } + + Column() { + Text('BlueTooth State: ' + (this.state ? 'Connected' : 'Disconnected')) + .margin(10) + Text('BleState: ' + this.getAdvertiserStateDescription()) + .fontColor(Color.Red) + .margin(10) + if (this.marText) { + Marquee({ src: this.marText, start: true }) + .margin(10) + } + } + + Tabs() { + TabContent() { + Column({ space: 5 }) { + Column({ space: 5 }) { + Button($r('app.string.Set_filtering_parameters')) + .width('80%') + .onClick(() => { + if (this.scanDialogController != null) { + this.scanDialogController.open(); + } + }) + Button($r('app.string.StartScan')) + .width('80%') + .onClick(() => { + this.bleScanManager.setScanParameter(this.inputValueOfInterval, this.inputValueOfManufactureId, + this.inputValueOfDeviceName, this.inputValueOfDeviceId); + this.bleScanManager.startScan(); + }) + Button($r('app.string.StopScan')) + .width('80%') + .onClick(() => { + this.bleScanManager.stopScan(); + this.scanFlag = false; + }) + Button($r('app.string.Refresh')) + .width('80%') + .backgroundColor(Color.Red) + .onClick(() => { + this.scanData = this.bleScanManager.getScanData(); + }) + } + .height('25%') + .margin({ top: 5 }) + + Scroll(this.scroller) { + Column() { + ForEach(this.scanData, (item: ScanData) => { + Row() { + Text('deviceId: ' + item.getDeviceId() + '\n' + 'deviceName: ' + item.getDeviceName() + '\n' + + 'rssi: ' + item.getRssi() + '\n' + 'connectable: ' + item.getConnectable()) + .width('70%') + .height(100) + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .fontSize(16) + .textAlign(TextAlign.JUSTIFY) + .margin(10) + + Button('connect') + .width('20%') + .margin(10) + .onClick(() => { + this.connectDeviceId = item.getDeviceId(); + this.gattClientManager.startConnect(this.connectDeviceId); + this.marText = 'deviceId: ' + item.getDeviceId() + ' deviceName: ' + item.getDeviceName() + + ' rssi: ' + item.getRssi() + ' connectable: ' + item.getConnectable(); + }) + } + .backgroundColor(0xFFFFFF) + .borderRadius(15) + .margin(10) + }); + + }.width('100%') + } + .margin({ top: 5 }) + .height('55%') + .scrollable(ScrollDirection.Vertical) + .scrollBar(BarState.On) + .scrollBarColor(Color.White) + .scrollBarWidth(10) + .friction(0.6) + .edgeEffect(EdgeEffect.None) + .onWillScroll((xOffset: number, yOffset: number) => { + console.info(xOffset + ' ' + yOffset); + }) + } + .height('100%') + } + .backgroundColor(Color.Gray) + .tabBar(this.tabBuilder('SCANNER', 0)) + + TabContent() { + Column({ space: 5 }) { + Scroll() { + Text(this.serviceResult) + .width('100%') + .height('100%') + .margin(30) + } + .width('80%') + .height('20%') + + Row() { + Text('serviceUuid: ') + + TextInput().onChange((value: string) => { + this.gattData.serviceUuid = value; + }).height('40vp').width('70%') + }.width('80%') + + Row() { + Text('characteristicUuid: ') + + TextInput().onChange((value: string) => { + this.gattData.characteristicUuid = value; + }).height('40vp').width('70%') + }.width('80%') + + Row() { + Text('descriptorUuid: ') + + TextInput().onChange((value: string) => { + this.gattData.descriptorUuid = value; + }).height('40vp').width('70%') + }.width('80%') + + Row() { + Text('characteristicValue: ') + + TextInput().onChange((value: string) => { + this.gattData.characteristicValue = value; + }).height('40vp').width('70%') + }.width('80%') + + Row() { + Text('descriptorValue: ') + + TextInput().onChange((value: string) => { + this.gattData.descriptorValue = value; + }).height('40vp').width('70%') + }.width('80%') + + Button($r('app.string.DiscoverService')) + .width('80%') + .onClick(() => { + this.gattClientManager.discoverServices().then(() => { + this.serviceResult = this.gattClientManager.getResult(); + }) + }) + + Row({ space: 30 }) { + Button($r('app.string.readChar')) + .width('30%') + .onClick(() => { + this.gattClientManager.readCharacteristicValue(); + }) + + Button($r('app.string.writeChar')) + .width('30%') + .onClick(() => { + this.gattClientManager.setGattData(this.gattData); + this.gattClientManager.writeCharacteristicValue(); + }) + } + + Row({ space: 30 }) { + + Button($r('app.string.readDes')) + .width('30%') + .onClick(() => { + this.gattClientManager.readDescriptorValue(); + }) + + Button($r('app.string.writeDes')) + .width('30%') + .onClick(() => { + this.gattClientManager.setGattData(this.gattData); + this.gattClientManager.writeDescriptorValue(); + }) + } + + Button($r('app.string.disconnect')) + .width('80%') + .backgroundColor(Color.Red) + .onClick(() => { + this.gattClientManager.stopConnect(); + this.marText = ''; + this.serviceResult = ''; + }) + } + .width('100%') + .height('100%') + } + .backgroundColor(Color.Pink) + .tabBar(this.tabBuilder('GATT', 1)) + .width('100%') + .height('100%') + + TabContent() { + Row() { + Column({ space: 12 }) { + Button($r('app.string.registerServer')) + .width('80%') + .onClick(() => { + this.gattServerManager.registerServer(); + }) + + Button($r('app.string.unRegisterServer')) + .width('80%') + .onClick(() => { + this.gattServerManager.unRegisterServer(); + }) + + Button($r('app.string.RegisterReadChar')) + .width('80%') + .onClick(() => { + this.gattServerManager.onCharacteristicRead(); + }) + + Button($r('app.string.RegisterWriteChar')) + .width('80%') + .onClick(() => { + this.gattServerManager.onCharacteristicWrite(); + }) + + Button($r('app.string.RegisterReadDes')) + .width('80%') + .onClick(() => { + this.gattServerManager.onDescriptorRead(); + }) + + Button($r('app.string.RegisterWriteDes')) + .width('80%') + .onClick(() => { + this.gattServerManager.onDescriptorWrite(); + }) + } + .width('50%') + + Column({ space: 12 }) { + Button($r('app.string.setAdv')) + .width('80%') + .onClick(() => { + this.advDialogController?.open(); + }) + + Button($r('app.string.startAdv')) + .width('80%') + .onClick(() => { + this.bleAdvertisingManager.setAdvertisingParameter(Number(this.inputValueOfAdvManufactureId), + this.inputValueOfAdvManufactureValueBuffer, this.inputValueOfAdvServiceUuids, + this.inputValueOfAdvServiceBuffer, this.inputValueOfAdvIncludeDeviceName); + this.bleAdvertisingManager.startAdvertising(); + }) + + Button($r('app.string.stopAdv')) + .width('80%') + .onClick(() => { + console.info('disable Advertising'); + this.bleAdvertisingManager.disableAdvertising(); + console.info('Advertising over'); + }) + + Button($r('app.string.continueAdv')) + .width('80%') + .onClick(() => { + this.bleAdvertisingManager.enableAdvertising(0); + }) + + Button($r('app.string.closeAdv')) + .width('80%') + .onClick(() => { + this.bleAdvertisingManager.stopAdvertising(); + }) + } + .width('50%') + } + } + + .backgroundColor(Color.Orange) + .tabBar(this.tabBuilder('ADVERTISER', 2)) + + TabContent() { + Column({ space: 12 }) { + Button($r('app.string.openBlueTooth')) + .width('80%') + .onClick(() => { + this.state = access.getState(); + if (this.state == 0) { + this.bluetoothSwitch.openBluetooth(); + } + setTimeout(() => { + this.state = access.getState(); + }, 2000) + setTimeout(() => { + this.state = access.getState(); + }, 5000) + }) + + Button($r('app.string.closeBlueTooth')) + .width('80%') + .onClick(() => { + this.state = access.getState(); + if (this.state == 2) { + try { + this.bluetoothSwitch.closeBluetooth(); + } catch (err) { + console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + + (err as BusinessError).message); + } + } + setTimeout(() => { + this.state = access.getState(); + }, 2000) + }) + } + } + .backgroundColor(Color.Yellow) + .tabBar(this.tabBuilder('SWITCH', 3)) + } + .onChange((index: number) => { + this.currentIndex = index + }) + .backgroundColor('#F1F3F5') + } + } +} + diff --git a/bluetoothSample/entry/src/main/module.json5 b/bluetoothSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..34afbf7be55e682e1b5f892898bb9a8b732199df --- /dev/null +++ b/bluetoothSample/entry/src/main/module.json5 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": 'ohos.permission.USE_BLUETOOTH', + "reason": "$string:USE_BLUETOOTH" + }, + { + "name": 'ohos.permission.DISCOVER_BLUETOOTH', + "reason": "$string:DISCOVER_BLUETOOTH" + }, + { + "name": "ohos.permission.ACCESS_BLUETOOTH", + "reason": "$string:ACCESS_BLUETOOTH", + "usedScene": { + "when": "always" + } + } + ], + "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/bluetoothSample/entry/src/main/resources/base/element/color.json b/bluetoothSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/src/main/resources/base/element/string.json b/bluetoothSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..6de3499e04e0d44732c2a453022b25feda1cf467 --- /dev/null +++ b/bluetoothSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,119 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "bluetoothSample" + }, + { + "name": "ACCESS_BLUETOOTH", + "value": "允许应用接入蓝牙并使用蓝牙能力,例如配对、连接外围设备等。" + }, + { + "name": "DISCOVER_BLUETOOTH", + "value": "允许应用配置本地蓝牙,查找远端设备且与之配对连接。" + },{ + "name": "USE_BLUETOOTH", + "value": "允许应用查看蓝牙的配置。" + }, + { + "name": "RegisterReadChar", + "value": "订阅读特征值" + }, + { + "name": "RegisterWriteChar", + "value": "订阅写特征值" + }, + { + "name": "RegisterReadDes", + "value": "订阅读描述符" + }, + { + "name": "RegisterWriteDes", + "value": "订阅写描述符" + }, + { + "name": "registerServer", + "value": "注册服务" + }, + { + "name": "unRegisterServer", + "value": "注销服务" + }, + { + "name": "Set_filtering_parameters", + "value": "设置过滤参数" + }, + { + "name": "StartScan", + "value": "开始扫描" + }, + { + "name": "StopScan", + "value": "停止扫描" + }, + { + "name": "Refresh", + "value": "刷新" + }, + { + "name": "DiscoverService", + "value": "发现服务" + }, + { + "name": "readChar", + "value": "读特征值" + }, + { + "name": "writeChar", + "value": "写特征值" + }, + { + "name": "readDes", + "value": "读描述符" + }, + { + "name": "writeDes", + "value": "写描述符" + }, + { + "name": "disconnect", + "value": "断开连接" + }, + { + "name": "startAdv", + "value": "开始广播" + }, + { + "name": "stopAdv", + "value": "暂停广播" + }, + { + "name": "continueAdv", + "value": "继续广播" + }, + { + "name": "closeAdv", + "value": "关闭广播" + }, + { + "name": "setAdv", + "value": "设置广播内容" + }, + { + "name": "openBlueTooth", + "value": "开启蓝牙" + }, + { + "name": "closeBlueTooth", + "value": "关闭蓝牙" + } + ] +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/resources/base/media/background.png b/bluetoothSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/bluetoothSample/entry/src/main/resources/base/media/background.png differ diff --git a/bluetoothSample/entry/src/main/resources/base/media/foreground.png b/bluetoothSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/bluetoothSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/bluetoothSample/entry/src/main/resources/base/media/layered_image.json b/bluetoothSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/src/main/resources/base/media/startIcon.png b/bluetoothSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/bluetoothSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/bluetoothSample/entry/src/main/resources/base/profile/backup_config.json b/bluetoothSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/bluetoothSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/main/resources/base/profile/main_pages.json b/bluetoothSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/bluetoothSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/bluetoothSample/entry/src/main/resources/dark/element/color.json b/bluetoothSample/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/src/mock/mock-config.json5 b/bluetoothSample/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b9a78e201535765168a92d3543c690273ecdc019 --- /dev/null +++ b/bluetoothSample/entry/src/mock/mock-config.json5 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/ohosTest/ets/test/Ability.test.ets b/bluetoothSample/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/bluetoothSample/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/bluetoothSample/entry/src/ohosTest/ets/test/List.test.ets b/bluetoothSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/src/ohosTest/module.json5 b/bluetoothSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..be4685a172af804c5b26c0e3618bf770cf138e98 --- /dev/null +++ b/bluetoothSample/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + { + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/bluetoothSample/entry/src/test/List.test.ets b/bluetoothSample/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/entry/src/test/LocalUnit.test.ets b/bluetoothSample/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/bluetoothSample/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/bluetoothSample/hvigor/hvigor-config.json5 b/bluetoothSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/bluetoothSample/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/bluetoothSample/hvigorfile.ts b/bluetoothSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/bluetoothSample/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/bluetoothSample/oh-package.json5 b/bluetoothSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/bluetoothSample/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/bluetoothSample/ohosTest.md b/bluetoothSample/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..ed4f1cc491b31ec684327d49506f8387bfd5502e --- /dev/null +++ b/bluetoothSample/ohosTest.md @@ -0,0 +1,32 @@ +# 蓝牙示例代码工程化 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ----------------- | ------------ | ----------------- | ------------------------|--------- | -------- | +| 应用正常启动 | 设备支持蓝牙 | 启动应用 | 进入应用界面,弹出申请蓝牙权限的弹窗 |否 | Pass | +| 应用正常获取蓝牙权限 | 设备支持蓝牙,申请蓝牙权限的弹窗点击“允许” | 切换到SIWITCH界面,点击打开蓝牙 | 弹出三方应用申请蓝牙权限的弹窗 |否 | Pass | +| 应用成功打开蓝牙 | 设备支持蓝牙,蓝牙权限申请成功。 | 切换到SIWITCH界面,点击开启蓝牙,在弹窗中点击“开启” | 设备打开蓝牙功能,上方Bluetooth State变为Connected |否 | Pass | +| 可以正确设置扫描的过滤参数 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开。 | 在SCAN界面,点击“设置过滤参数”,输入过滤参数,点击confirm,点击开始扫描 | 设备根据过滤参数正确过滤扫描设备 |否 | Pass | +| 正常扫描设备 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在SCAN界面,点击开始扫描 | 设备开始扫描设备,设备Id在下方以弹窗形式显示 |否 | Pass | +| 显示扫描到的设备 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在SCAN界面,出现过设备Id的弹窗后,点击刷新 | 扫描到的设备信息在下方以列表形式展示 |否 | Pass | +| 关闭扫描 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在SCAN界面,点击开始扫描后,点击关闭扫描 | 弹出停止扫描的弹窗 |否 | Pass | +| 连接设备 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已扫描到设备 | 在SCAN界面,点击下方设备列表的connect按钮 | 弹出连接成功的弹窗,设备信息开始在上方循环播放 |否 | Pass | +| 发现服务 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,点击发现服务按钮 | 弹出扫描到的服务内容的弹窗,并在上方文本框显示 |否 | Pass | +| 读特征值 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,设置过滤参数后,点击读特征值 | 弹出弹窗,显示读取结果 |否 | Pass | +| 读描述符 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,设置过滤参数后,点击读描述符 | 弹出弹窗,显示读取结果 |否 | Pass | +| 写特征值 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,设置过滤参数后,点击写特征值 | 弹出弹窗,显示写入结果 |否 | Pass | +| 写描述符 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,设置过滤参数后,点击写描述符 | 弹出弹窗,显示写入结果 |否 | Pass | +| 断开连接 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开,已连接到设备 | 在GATT界面,点击断开连接 | 弹出弹窗,显示断开连接成功 |否 | Pass | +| 注册服务 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击注册服务按钮 | 弹出弹窗,显示注册服务成功 |否 | Pass | +| 注销服务 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击注销服务按钮 | 弹出弹窗,显示注销服务成功 |否 | Pass | +| 订阅读特征值 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击订阅读特征值按钮 | 弹出弹窗,显示订阅读特征值成功 |否 | Pass | +| 订阅写特征值 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击订阅写特征值按钮 | 弹出弹窗,显示订阅写特征值成功 |否 | Pass | +| 订阅读描述符 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击订阅读描述符按钮 | 弹出弹窗,显示订阅读描述符成功 |否 | Pass | +| 订阅写描述符 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击订阅写描述符按钮 | 弹出弹窗,显示订阅写描述符成功 |否 | Pass | +| 设置广播内容 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击设置广播内容按钮 | 弹出参数弹窗,输入信息设置广播内容 |否 | Pass | +| 开始广播 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击开始广播按钮 | 弹出弹窗,提示开始广播 |否 | Pass | +| 暂停广播 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击暂停广播按钮 | 弹出弹窗,提示暂停广播 |否 | Pass | +| 继续广播 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击继续广播按钮 | 弹出弹窗,提示继续广播 |否 | Pass | +| 停止广播 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在ADVERISER界面,点击停止广播按钮 | 弹出弹窗,提示停止广播 |否 | Pass | +| 关闭蓝牙 | 设备支持蓝牙,蓝牙权限申请成功,蓝牙已打开 | 在SWITCH界面,点击关闭蓝牙按钮 | 设备关闭蓝牙,上方BlueTooth State变为 Disconnected |否 | Pass | diff --git a/bluetoothSample/screenshots/ADVERISER.jpeg b/bluetoothSample/screenshots/ADVERISER.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b0f2594ab6497ebc164c1dcbd168d546af2cf648 Binary files /dev/null and b/bluetoothSample/screenshots/ADVERISER.jpeg differ diff --git a/bluetoothSample/screenshots/BONDED.jpeg b/bluetoothSample/screenshots/BONDED.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..da73c70a851c4679a221b379e491e5e8fcf85a4c Binary files /dev/null and b/bluetoothSample/screenshots/BONDED.jpeg differ diff --git a/bluetoothSample/screenshots/SCAN.jpeg b/bluetoothSample/screenshots/SCAN.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..7b4fcb903d500c6a3bfdedc2b430444e57ea29e8 Binary files /dev/null and b/bluetoothSample/screenshots/SCAN.jpeg differ diff --git a/bluetoothSample/screenshots/SWITCH.jpeg b/bluetoothSample/screenshots/SWITCH.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..cc3838867521b92fb7fc8c1eafbe423372276834 Binary files /dev/null and b/bluetoothSample/screenshots/SWITCH.jpeg differ