!309 Stage模型手工测试套示例

Merge pull request !309 from 王洋/master
This commit is contained in:
openharmony_ci 2022-07-27 01:09:12 +00:00 committed by Gitee
commit 894dbd492a
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
24 changed files with 820 additions and 0 deletions

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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.dms.stage_manual_test_suite",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"distributedNotificationEnabled": true
}
}

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,44 @@
# Stage模型手工测试套示例
本示例展示了分布式调度子系统基于stage模型手工测试套包含:
1、跨设备绑定ServiceExtensionAbility
效果图
![](screenshots/MainPage.png)
## 跨设备绑定ServiceExtensionAbility示例
### 简介
本示例展示了在eTS中如何构建stage模型跨设备绑定ServiceExtensionAbility包含:
1、远端实现待绑定 ServiceExtensionAbility
2、申请分布式权限DISTRIBUTED_DATASYNC
3、发起端调用 context.connectAbility() 接口,传入 deviceIdbundleNameabilityName 绑定远端 ServiceExtensionAbility
4、绑定成功获取远端 ServiceExtensionAbility 句柄,发起端使用句柄的 sendRequest() 接口调用远端定义的方法
效果图
![](screenshots/ConnectServiceExtensionAbility.png)
### 测试步骤
1、两台设备都安装此应用并组网成功计算器可以跨端拉起
2、在设置里给予此应用分布式权限
3、发起端设备 A 打开应用,选择待绑定远端设备 B 的 deviceId点击 connect 按钮发起绑定
4、发起端设备 A 日志区显示 “get proxy”代表绑定成功
5、发起端设备 A 在输入栏输入任意字符串,点击 send 按钮,信息被发送到远端设备 B
6、发起端设备 A 收到远端设备 B 的回复消息 “MyServiceExtensionAbility receive your message”
### 约束与限制
1、本示例仅支持标准系统上运行
2、本示例为Stage模型仅支持API version 9IDE版本3.0.1.900以上系统版本OpenHarmony3.1 release

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"app": {
"signingConfigs": [],
"compileSdkVersion": 9,
"compatibleSdkVersion": 9,
"products": [
{
"name": "default",
"signingConfig": "default"
}
],
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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",
}
]
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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.
module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks

View File

@ -0,0 +1,5 @@
{
"name": "entry",
"version": "1.0.0",
"lockfileVersion": 1
}

View File

@ -0,0 +1,14 @@
{
"name": "entry",
"version": "1.0.0",
"ohos": {
"org": "ohos",
"buildTool": "hvigor",
"directoryLevel": "module"
},
"description": "example description",
"repository": {},
"license": "ISC",
"dependencies": {}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 AbilityStage from "@ohos.application.AbilityStage"
export default class MyAbilityStage extends AbilityStage {
onCreate() {
console.log("[Demo] MyAbilityStage onCreate")
}
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import Ability from '@ohos.application.Ability'
import RemoteDeviceModel from '../Model/RemoteDeviceModel'
import rpc from '@ohos.rpc'
var printLog = '[MainAbility]'
var remoteDeviceModel = new RemoteDeviceModel
var messageProxy = null
var connectedAbility
var options = {
onConnect: async function (elementName, proxy) {
showLog(printLog + "service extension ability connect success")
if (proxy === null) {
showLog("can not get proxy")
return
}
messageProxy = proxy
showLog(printLog + "get proxy, elementName: " + elementName)
},
onDisconnect: function () {
showLog(printLog + "service extension ability disconnect success")
},
onFailed: function () {
showLog(printLog + "service extension ability connect fail")
}
}
function ConnectRemoteAbility() {
showLog(printLog + "connect service extension ability begin")
showLog(printLog + "connect remote device id is " + globalThis.selectDevice)
let want = {
bundleName: "com.dms.stage_manual_test_suite",
abilityName: "MyServiceExtensionAbility",
deviceId: globalThis.selectDevice
}
connectedAbility = globalThis.context.connectAbility(want, options)
showLog(printLog + "connect service extension ability, connectId = " + connectedAbility)
}
async function DisconnectRemoteAbility() {
showLog(printLog + "disconnect service extension ability begin")
showLog(printLog + "disconnect remote device id is " + globalThis.selectDevice)
await globalThis.context.disconnectAbility(connectedAbility)
showLog(printLog + "disconnect service extension ability, connectId = " + connectedAbility)
connectedAbility = null
}
async function SendMessage() {
if (messageProxy === null) {
showLog(printLog + "can not get proxy")
return
}
showLog(printLog + "send message : " + AppStorage.Get<string>("message"))
let option = new rpc.MessageOption()
let data = new rpc.MessageParcel()
let reply = new rpc.MessageParcel()
data.writeString(AppStorage.Get<string>("message"))
await messageProxy.sendRequest(1, data, reply, option)
showLog(printLog + "send message success")
globalThis.receiveMessage = reply.readString()
showLog(printLog + "receive reply message : " + globalThis.receiveMessage)
}
function showLog(logMessage) {
console.log(logMessage)
AppStorage.Set<string>("receiveMessage", AppStorage.Get<string>("receiveMessage") + logMessage + "\n")
}
function RegisterDeviceListCallback() {
remoteDeviceModel.registerDeviceListCallback(() => {
let deviceSize = remoteDeviceModel.deviceList.length
for (var i = 0; i < deviceSize; i++) {
globalThis.DeviceIdList.push(remoteDeviceModel.deviceList[i].deviceId)
}
})
}
export default class MainAbility extends Ability {
onCreate(want, launchParam) {
console.log("[ServiceExtensionDemo] MainAbility onCreate")
globalThis.abilityWant = want;
globalThis.context = this.context
globalThis.DeviceIdList = []
globalThis.selectDevice
globalThis.receiveMessage = ""
RegisterDeviceListCallback()
}
onDestroy() {
AppStorage.Set<string>("receiveMessage", "")
console.log("[ServiceExtensionDemo] MainAbility onDestroy")
}
onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability
console.log("[ServiceExtension] MainAbility onWindowStageCreate")
globalThis.ConnectRemoteAbility = ConnectRemoteAbility
globalThis.DisconnectRemoteAbility = DisconnectRemoteAbility
globalThis.SendMessage = SendMessage
windowStage.loadContent("pages/MainPage", (err, data) => {
if (err.code) {
console.error('Failed to load the content. Cause:' + JSON.stringify(err));
return;
}
console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data))
});
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
console.log("[ServiceExtension] MainAbility onWindowStageDestroy")
}
onForeground() {
// Ability has brought to foreground
console.log("[ServiceExtension] MainAbility onForeground")
}
onBackground() {
// Ability has back to background
console.log("[ServiceExtension] MainAbility onBackground")
}
};

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 deviceManager from '@ohos.distributedHardware.deviceManager';
var SUBSCRIBE_ID = 100;
export default class RemoteDeviceModel {
deviceList = [];
discoverList = [];
callback;
authCallback = null;
MyDeviceManager;
constructor() {
}
registerDeviceListCallback(callback) {
if (typeof (this.MyDeviceManager) === 'undefined') {
console.log('[ServiceExtensionDemo] deviceManager.createDeviceManager begin');
let self = this;
deviceManager.createDeviceManager('com.example.serviceextensiondemo', (error, value) => {
if (error) {
console.error('createDeviceManager failed.');
return;
}
self.MyDeviceManager = value;
self.registerDeviceListCallback_(callback);
console.log('[ServiceExtensionDemo] createDeviceManager callback returned, error=' + error + ' value=' + value);
});
console.log('[ServiceExtensionDemo] deviceManager.createDeviceManager end');
} else {
this.registerDeviceListCallback_(callback);
}
}
registerDeviceListCallback_(callback) {
console.info('[ServiceExtensionDemo] registerDeviceListCallback');
this.callback = callback;
if (this.MyDeviceManager == undefined) {
console.error('[ServiceExtensionDemo] deviceManager has not initialized');
this.callback();
return;
}
console.info('[ServiceExtensionDemo] getTrustedDeviceListSync begin');
var list = this.MyDeviceManager.getTrustedDeviceListSync();
console.info('[ServiceExtensionDemo] getTrustedDeviceListSync end, deviceList=' + JSON.stringify(list));
if (typeof (list) != 'undefined' && typeof (list.length) != 'undefined') {
this.deviceList = list;
}
this.callback();
console.info('[ServiceExtensionDemo] callback finished');
}
getTrustDeviceList(callback) {
console.info('[ServiceExtensionDemo] getTrustDeviceListSync begin');
var list = this.MyDeviceManager.getTrustedDeviceListSync();
console.info('[ServiceExtensionDemo] getTrustedDeviceListSync end, deviceList=' + JSON.stringify(list));
if (typeof (list) != 'undefined' && typeof (list.length) != 'undefined') {
this.deviceList = list;
}
console.info('[ServiceExtensionDemo] getTrustDeviceListSync end');
callback();
}
unregisterDeviceListCallback() {
console.info('[dmsDemo] stopDeviceDiscovery ' + SUBSCRIBE_ID);
this.MyDeviceManager.stopDeviceDiscovery(SUBSCRIBE_ID);
this.MyDeviceManager.off('deviceStateChange');
this.MyDeviceManager.off('deviceFound');
this.MyDeviceManager.off('discoverFail');
this.MyDeviceManager.off('serviceDie');
this.deviceList = [];
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import rpc from '@ohos.rpc';
import ServiceExtensionAbility from '@ohos.application.ServiceExtensionAbility';
var printLog = '[ServiceExtension]'
class MyServiceExtensionAbilityStub extends rpc.RemoteObject {
constructor(des) {
super(des)
}
onRemoteRequest(code, data, reply, option) {
showLog(printLog + "MyServiceExtensionAbility onRemoteRequest call")
if (code === 1) {
globalThis.receiveMessage = data.readString()
showLog(printLog + "receive message : " + globalThis.receiveMessage)
} else {
showLog(printLog + "unknown request code")
}
reply.writeString("MyServiceExtensionAbility receive your message")
return true
}
queryLocalInterface(descriptor) {
return null
}
getInterfaceDescriptor() {
return ''
}
sendRequest(code, data, reply, option) {
return null
}
getCallingPid() {
return 1
}
getCallingUid() {
return 1
}
attachLocalInterface(localInterface, descriptor) {}
}
function showLog(logMessage) {
console.log(logMessage)
AppStorage.Set<string>("receiveMessage", AppStorage.Get<string>("receiveMessage") + logMessage + "\n")
}
export default class MyServiceExtensionAbility extends ServiceExtensionAbility {
onCreate(want) {
console.log(printLog + 'MyServiceExtensionAbility OnCreate, want : ' + want.abilityName)
}
onRequest(want) {
console.log(printLog + 'MyServiceExtensionAbility onRequest, want : ' + want.abilityName)
}
onConnect(want) {
showLog(printLog + 'MyServiceExtensionAbility onConnect, want : ' + want.abilityName)
return new MyServiceExtensionAbilityStub('test')
}
onDisconnect(want) {
showLog(printLog + 'MyServiceExtensionAbility onDisconnect, want : ' + want.abilityName)
}
onDestroy() {
console.log(printLog + 'MyServiceExtensionAbility onDestroy')
}
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
var printLog = '[ServiceExtensionDemo]'
AppStorage.Link("message")
AppStorage.Link("receiveMessage")
@Entry
@Component
struct Index {
@State selectDeviceName : string = ""
@StorageLink("message") message : string = ""
@StorageLink("receiveMessage") receiveMessage : string = ""
build() {
Column() {
Row() {
Text("select device id : " + this.selectDeviceName)
.width('100%')
.height('100%')
.fontSize(20)
.textAlign(TextAlign.Start)
}
.height('10%')
.width('100%')
Row() {
Column() {
Button('connect')
.width(100)
.height(50)
.onClick(() => {
globalThis.ConnectRemoteAbility()
})
Button('discon')
.width(100)
.height(50)
.onClick(() => {
globalThis.DisconnectRemoteAbility()
})
List({ space: 10, initialIndex: 0}) {
ForEach(globalThis.DeviceIdList, (item : string) => {
ListItem() {
Button(item)
.width('100%').height(50).fontSize(10)
.onClick(() => {
console.log(printLog + "select device : " + item)
this.selectDeviceName = item
globalThis.selectDevice = item
AppStorage.Set<string>('receiveMessage', AppStorage.Get<string>("receiveMessage") + "select device:" + item + '\n')
})
}.editable(this.editFlag)
}, (item : string) => item.toString())
}.height('100%').width('100%').borderWidth(1).align(ItemAlign.Start)
}.width('30%').height('100%').padding(5)
Column() {
Text('日志')
.height('5%')
.width('100%')
.fontSize(20)
.borderWidth(1)
.textAlign(TextAlign.Center)
.backdropBlur(Color.Gray)
Scroll() {
Text(this.receiveMessage)
.width('100%')
.fontSize(15)
.textAlign(TextAlign.Start)
}.scrollBar(BarState.Auto)
.height('55%')
.align(ItemAlign.Start)
.borderWidth(1)
Text("待发送数据:")
.height('5%')
.width('100%')
.fontSize(20)
.borderWidth(1)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Gray)
Text(this.message)
.height('10%')
.width('100%')
.fontSize(15)
.borderWidth(1)
.textAlign(TextAlign.Start)
TextInput("输入消息")
.width('100%')
.height('10%')
.borderStyle(BorderStyle.Solid)
.type(InputType.Normal)
.onChange((value : string) => {
AppStorage.Set<string>('message', value)
})
Row() {
Button('send')
.width(100)
.height(50)
.onClick(() => {
globalThis.SendMessage()
})
}.height('15%')
}.width('70%').height('100%')
}.width('100%').height('90%')
}.width('100%').height('100%')
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import router from '@system.router'
@Entry
@Component
struct Index {
build() {
Column() {
Text("StageManualTestSuite")
.width('100%')
.height('10%')
.fontSize(20)
.textAlign(TextAlign.Center)
Button('ConnectServiceExtensionAbility')
.width("90%")
.height(50)
.onClick(() => {
router.push({uri : 'pages/ConnectServiceExtensionAbility'})
})
Button('other')
.width("90%")
.height(50)
.onClick(() => {
})
}.width('100%').height('100%')
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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",
"srcEntrance": "./ets/Application/MyAbilityStage.ts",
"description": "$string:entry_desc",
"mainElement": "MainAbility",
"deviceTypes": [
"default",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"uiSyntax": "ets",
"abilities": [
{
"name": "MainAbility",
"srcEntrance": "./ets/MainAbility/MainAbility.ts",
"description": "$string:MainAbility_desc",
"icon": "$media:icon",
"label": "$string:MainAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:white",
"visible": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "MyServiceExtensionAbility",
"icon": "$media:icon",
"description": "service",
"type": "service",
"visible": true,
"srcEntrance": "./ets/MyServiceExtensionAbility/MyServiceExtensionAbility.ts"
},
],
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
}
}

View File

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

View File

@ -0,0 +1,16 @@
{
"string": [
{
"name": "entry_desc",
"value": "description"
},
{
"name": "MainAbility_desc",
"value": "description"
},
{
"name": "MainAbility_label",
"value": "StageManualTestSuite"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,6 @@
{
"src": [
"pages/ConnectServiceExtensionAbility",
"pages/MainPage"
]
}

View File

@ -0,0 +1,17 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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.
module.exports = require('@ohos/hvigor-ohos-plugin').appTasks

View File

@ -0,0 +1,17 @@
{
"name": "stagemanualtestsuite",
"version": "1.0.0",
"ohos": {
"org": "ohos",
"buildTool": "hvigor",
"directoryLevel": "project"
},
"description": "example description",
"repository": {},
"license": "ISC",
"dependencies": {
"@ohos/hypium": "1.0.1",
"@ohos/hvigor": "1.1.6",
"@ohos/hvigor-ohos-plugin": "1.1.6"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB