From 1772df726f89eb3f1f8203d5e1112d7df0621838 Mon Sep 17 00:00:00 2001 From: "hepeipei (C)" Date: Fri, 9 Apr 2021 18:44:44 +0800 Subject: [PATCH 01/41] update LICENSE --- VoiceCamera/LICENSE | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/VoiceCamera/LICENSE b/VoiceCamera/LICENSE index eb44b24a..6c25c86a 100644 --- a/VoiceCamera/LICENSE +++ b/VoiceCamera/LICENSE @@ -4,14 +4,36 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - + + We use Alibaba's open-source fastjson.jar. The details are as follows: + + ### License + + Fastjson is released under the [Apache 2.0 license](LICENSE). + + ``` + Copyright 1999-2021 Alibaba Group Holding Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at the following link. + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ``` + Apache License, Version 2.0 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -- Gitee From 7f31407b3ad6ce6c98774b8a2da4f4d4866ee542 Mon Sep 17 00:00:00 2001 From: "hepeipei (C)" Date: Mon, 12 Apr 2021 15:48:06 +0800 Subject: [PATCH 02/41] xuzi --- ComponentCodelab/README.md | 40 +++++++++++++------------- DistributedMail/README.md | 26 ++++++++++++++--- DistributedVideoCodelab/README.md | 48 +++++++++++++++---------------- EducationSystem/README.md | 43 +++++++++++++-------------- HarmonyOSNewsClient/README.md | 47 +++++++++++++++--------------- README.md | 7 +++-- ShoppingJs/README.md | 24 +++++++++++++++- SimpleVideoCodelab/README.md | 44 ++++++++++++++-------------- VoiceCamera/README.md | 16 +++++------ 9 files changed, 169 insertions(+), 126 deletions(-) diff --git a/ComponentCodelab/README.md b/ComponentCodelab/README.md index f748c2b6..2b6de728 100644 --- a/ComponentCodelab/README.md +++ b/ComponentCodelab/README.md @@ -1,25 +1,25 @@ ComponentCodelab -What is it? -•This CodeLab aims to let developers understand the common layouts and usage methods of common components for mobile HarmonyOS application development, and experience the whole process from project creation to code and layout writing, to compilation, construction, deployment, and operation. +简介 + • 本CodeLab旨在使开发人员了解用于HarmonyOS手机应用程序开发的通用组件的通用布局和使用方法,并体验从项目创建到代码和布局编写,再到编译、构造、部署和运行的全过程。 -Installation requirements -• Install DevEco Studio and Node.js -• Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations -1. If you can directly access the Internet, just download the HarmonyOS SDK -2. If the network cannot access the Internet directly, it can be accessed through a proxy server -• Generate secret key and apply for certificate +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 -User guide -• Download this ComponentCodelab -• Open HUAWEI DevEco Studio, click File> Open to select this ComponentCodelab -• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package -• Click Run> Run 'entry' to run the hap package +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 -Note -• The storage directory of ComponentCodelab must be in English, not Chinese -• You can choose to run the hap package on the simulator or the phone. -• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing -Please see LICENSE for more info. +注意 +• 项目代码的存储目录需使用英语字符。 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/DistributedMail/README.md b/DistributedMail/README.md index 97eda338..d7fbe336 100644 --- a/DistributedMail/README.md +++ b/DistributedMail/README.md @@ -1,6 +1,24 @@ -# Distributed Mail Client +# 分布式邮件客户端 -In this article, we make a simple demonstration by simulating the collaborative email editing between different devices. We can complete the task of cross device migration through the migration button, and call the cross device pictures through the attachment button. +简介 +在本文中,我们模拟演示了跨设备的电子邮件编辑页面。我们可以通过迁移按钮完成跨设备迁移的任务,并通过附件按钮调用跨设备图片。 -Licensing -Please see LICENSE for more info. \ No newline at end of file +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 + +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 + +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/DistributedVideoCodelab/README.md b/DistributedVideoCodelab/README.md index f3a2ae7b..14cb9adb 100644 --- a/DistributedVideoCodelab/README.md +++ b/DistributedVideoCodelab/README.md @@ -1,29 +1,29 @@ DistributedVideoCodelab -What is it? -The DistributedVideoCodelab application is to show the cross-device migration video capability. -You can easily play a video from local or the network through the application. -You can start to play,pause,forward,backward and so on. -More than that ,you can transfer the video to other devices on the local area network (LAN) . -You can control the transferred video through the control dialog. -This example code is complete and you can learn from the beginning with us. +简介 +此应用程序展示了视频跨设备迁移的功能。 +您可以通过该应用程序轻松播放来自本地或网络的视频。 +您可以开始播放,暂停,前进,后退等。 +不仅如此,您还可以将视频迁移到局域网(LAN)上的其他设备。 +您可以通过控制对话框控制迁移的视频。 +该示例代码是一个完整的示例,您可以从头开始学习。 -Installation requirements -• Install DevEco Studio and Node.js -• Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations -1. If you can directly access the Internet, just download the HarmonyOS SDK -2. If the network cannot access the Internet directly, it can be accessed through a proxy server -• Generate secret key and apply for certificate +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 -User guide -• Download this project -• Open DevEco Studio, click File> Open> Then select and open this Project -• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package -• Click Run> Run 'entry' to run the hap package +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 -Note -• You can choose to run the hap package on the simulator or the phone. -• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing -Please see LICENSE for more info. \ No newline at end of file +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/EducationSystem/README.md b/EducationSystem/README.md index 707a05f0..41b43a16 100644 --- a/EducationSystem/README.md +++ b/EducationSystem/README.md @@ -1,27 +1,28 @@ Education System -What is it? -•Distance education and multi-screen collaboration are an important scene of smart education. -•In this article, CodeLab uses a parent-child early education system to complete two comprehensive cases of distributed early education arithmetic problems and distributed puzzle games. -•It aims to help developers quickly understand the experience of HarmonyOS application development, multi-screen collaborative interaction, and distributed cross-device transfer. -•From project creation, code writing, to compilation, construction, deployment and operation. +简介 +• 远程教育和多屏幕协作是智能教育的重要场景。 +• 在本文中,CodeLab使用亲子早期教育系统来完成两个有关分布式早期教育算术问题和分布式益智游戏的综合案例。 +• 它旨在帮助开发人员快速了解HarmonyOS应用程序开发,多屏协作交互和分布式跨设备传输的经验。 +• 从项目创建、代码编写到编译、构造、部署和操作。 -Installation requirements -• Install DevEco Studio and Node.js -• Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations -1. If you can directly access the Internet, just download the HarmonyOS SDK -2. If the network cannot access the Internet directly, it can be accessed through a proxy server -• Generate secret key and apply for certificate -User guide -• Download this EducationSystem -• Open HUAWEI DevEco Studio, click File> Open to select this EducationSystem -• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package -• Click Run> Run 'entry' to run the hap package +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 -Note -• You can choose to run the hap package on the simulator or the phone. -• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 -Licensing -Please see LICENSE for more info. \ No newline at end of file +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/HarmonyOSNewsClient/README.md b/HarmonyOSNewsClient/README.md index f1cf3626..b35b5921 100644 --- a/HarmonyOSNewsClient/README.md +++ b/HarmonyOSNewsClient/README.md @@ -1,28 +1,27 @@ -HarmonyOS News Client +HarmonyOS新闻客户端 -What is it? -The HarmonyOS news client is a simple news application. Here, -we want to show developers some common controls and components of the HarmonyOS. In addition, -we also demonstrate the cross-device migration function. -You can seamlessly transfer your FA to other devices on the local area network (LAN) to complete news sharing. -This example code is complete and you can learn from the beginning with us. +简介 +HarmonyOS新闻客户端是一个简单的新闻应用程序。 +我们想向开发人员展示HarmonyOS的一些常见控件和组件,以及跨设备协同功能。 +您可以在局域网(LAN)上的其他设备拉起FA,以完成新闻共享。 +该示例代码已完成,您可以从头开始学习。 -Installation requirements -• Install DevEco Studio and Node.js -• Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations -1. If you can directly access the Internet, just download the HarmonyOS SDK -2. If the network cannot access the Internet directly, it can be accessed through a proxy server -• Generate secret key and apply for certificate +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 -User guide -• Download this News Client Project -• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project -• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package -• Click Run> Run 'entry' to run the hap package +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 -Note -• You can choose to run the hap package on the simulator or the phone. -• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing -Please see LICENSE for more info. \ No newline at end of file +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/README.md b/README.md index 3465bc64..3bff79ac 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # codelabs 该Codelabs旨在向开发人员展示如何通过趣味场景来展示如何使用HarmonyOS能力的示例应用程序文档教程。 -注意:IDE版本及配套SDK问题可前往https://devecostudio.rnd.huawei.com/download/aide/#download查看配套的IDE、鸿蒙SDK、插件及Gradle版本。 +注意:IDE版本及配套SDK问题可前往https://devecostudio.rnd.huawei.com/download/aide/#download 查看配套的IDE、鸿蒙SDK、插件及Gradle版本。 ComponentCodelab:展示JAVA通用组件用法,链接:https://gitee.com/openharmony/codelabs/tree/master/ComponentCodelab @@ -10,7 +10,10 @@ DistributedVideoCodelab:如何使用分布式能力进行视频跨设备播放 EducationSystem:展示了分布式的早教算术题和拼图游戏的案例,链接:https://gitee.com/openharmony/codelabs/tree/master/EducationSystem - HarmonyOSNewsClient:展示了一个可以分享新闻详情页面的简易新闻客户端,链接:https://gitee.com/openharmony/codelabs/tree/master/HarmonyOSNewsClient +DistributedMail:展示了一个可以跨设备协同和分布式文件调用的简易邮件编辑页面,链接:https://gitee.com/openharmony/codelabs/tree/master/DistributedMail + +ShoppingJs:使用HarmonyOS JS UI开发出一个购物应用,链接:https://gitee.com/openharmony/codelabs/tree/master/ShoppingJs +VoiceCamera:展示了一个使用分布式文件系统和AI语音识别功能开发的分布式语音照相机,链接:https://gitee.com/openharmony/codelabs/tree/master/VoiceCamera \ No newline at end of file diff --git a/ShoppingJs/README.md b/ShoppingJs/README.md index 01121a03..4e38501e 100644 --- a/ShoppingJs/README.md +++ b/ShoppingJs/README.md @@ -1,3 +1,25 @@ # ShoppingDemoJs -ShoppingDemoJs \ No newline at end of file +简介 +本篇Codelab使用UI组件开发了一个购物应用。 +应用包含两级页面,分别是主页和商品详情页,都展示了丰富的HarmonyOS UI组件。 + +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 + +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 + +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/SimpleVideoCodelab/README.md b/SimpleVideoCodelab/README.md index e838a997..9e6090d3 100644 --- a/SimpleVideoCodelab/README.md +++ b/SimpleVideoCodelab/README.md @@ -1,27 +1,27 @@ SimpleVideoCodelab -What is it? -The SimpleVideoCodelab application is to show the simple HarmonyOS video capability. -You can easily play a video from local or the network through the application. -You can start to play,pause,forward,backward and so on. -This example code is complete and you can learn from the beginning with us. +简介 +此应用程序将展示简单的HarmonyOS视频播放功能。 +您可以通过此应用程序轻松播放来自本地或网络的视频。 +您可以控制视频开始播放、暂停、前进和后退等。 +该示例代码已完成,您可以从头开始学习。 -Installation requirements -• Install DevEco Studio and Node.js -• Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations -1. If you can directly access the Internet, just download the HarmonyOS SDK -2. If the network cannot access the Internet directly, it can be accessed through a proxy server -• Generate secret key and apply for certificate +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 -User guide -• Download this Project -• Open DevEco Studio, click File> Open> Then select and open this Project -• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package -• Click Run> Run 'entry' to run the hap package +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 -Note -• You can choose to run the hap package on the simulator or the phone. -• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing -Please see LICENSE for more info. \ No newline at end of file +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/VoiceCamera/README.md b/VoiceCamera/README.md index ebcc6429..e2043ba9 100644 --- a/VoiceCamera/README.md +++ b/VoiceCamera/README.md @@ -1,10 +1,10 @@ -# Distributed Voice Camera +# 分布式语音照相机 -What is it? -In this article, Codelab uses the HarmonyOS distributed file system and AI voice recognition function to develop a distributed voice camera. -Using this camera application, different devices under the same distributed network can see the photos taken by the main device in real time. -This effectively solves the pain point of the need to run back and forth to pass the mobile phone when taking pictures of each other. -In addition, the main device also supports a voice-controlled camera function, allowing you to control the camera from a distance. +简介 +在本Codelab中,使用了HarmonyOS分布式文件系统和AI语音识别功能来开发分布式语音照相机。 +使用此相机应用程序,同一分布式网络下的不同设备可以实时查看主设备拍摄的照片。 +这有效地解决了彼此拍照时需要来回传递手机的麻烦。 +此外,主设备还支持语音控制​​摄像头功能,可让您从远处控制摄像头。 -Licensing -Please see LICENSE for more info. \ No newline at end of file +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file -- Gitee From 897f3ec6d6e8064b94b16fa278908372243db55a Mon Sep 17 00:00:00 2001 From: "hepeipei (C)" Date: Wed, 14 Apr 2021 17:13:26 +0800 Subject: [PATCH 03/41] update --- JSPlaygroundDemo/LICENSE | 78 +++++++++ JSPlaygroundDemo/README.md | 26 +++ JSPlaygroundDemo/RELEASE-NOTES.md | 2 + JSPlaygroundDemo/build.gradle | 36 ++++ JSPlaygroundDemo/entry/build.gradle | 13 ++ JSPlaygroundDemo/entry/src/main/config.json | 62 +++++++ .../java/com/example/jsdemo/MainAbility.java | 36 ++++ .../com/example/jsdemo/MyApplication.java | 30 ++++ .../entry/src/main/js/default/app.js | 23 +++ .../main/js/default/common/checkbutton.png | Bin 0 -> 936 bytes .../src/main/js/default/common/delete.png | Bin 0 -> 1451 bytes .../entry/src/main/js/default/common/done.png | Bin 0 -> 32768 bytes .../entry/src/main/js/default/i18n/en-US.json | 6 + .../entry/src/main/js/default/i18n/zh-CN.json | 6 + .../src/main/js/default/pages/index/index.css | 165 ++++++++++++++++++ .../src/main/js/default/pages/index/index.hml | 32 ++++ .../src/main/js/default/pages/index/index.js | 93 ++++++++++ .../main/resources/base/element/string.json | 12 ++ .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + JSPlaygroundDemo/settings.gradle | 1 + README.md | 4 +- 23 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 JSPlaygroundDemo/LICENSE create mode 100644 JSPlaygroundDemo/README.md create mode 100644 JSPlaygroundDemo/RELEASE-NOTES.md create mode 100644 JSPlaygroundDemo/build.gradle create mode 100644 JSPlaygroundDemo/entry/build.gradle create mode 100644 JSPlaygroundDemo/entry/src/main/config.json create mode 100644 JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MainAbility.java create mode 100644 JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MyApplication.java create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/app.js create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/common/checkbutton.png create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/common/delete.png create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/common/done.png create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/i18n/en-US.json create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/i18n/zh-CN.json create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.css create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.hml create mode 100644 JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.js create mode 100644 JSPlaygroundDemo/entry/src/main/resources/base/element/string.json create mode 100644 JSPlaygroundDemo/entry/src/main/resources/base/media/icon.png create mode 100644 JSPlaygroundDemo/gradle/wrapper/gradle-wrapper.jar create mode 100644 JSPlaygroundDemo/gradle/wrapper/gradle-wrapper.properties create mode 100644 JSPlaygroundDemo/settings.gradle diff --git a/JSPlaygroundDemo/LICENSE b/JSPlaygroundDemo/LICENSE new file mode 100644 index 00000000..eb44b24a --- /dev/null +++ b/JSPlaygroundDemo/LICENSE @@ -0,0 +1,78 @@ + Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +Apache License, Version 2.0 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: +1.You must give any other recipients of the Work or Derivative Works a copy of this License; and +2.You must cause any modified files to carry prominent notices stating that You changed the files; and +3.You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +4.If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/JSPlaygroundDemo/README.md b/JSPlaygroundDemo/README.md new file mode 100644 index 00000000..a5c4b2d0 --- /dev/null +++ b/JSPlaygroundDemo/README.md @@ -0,0 +1,26 @@ +JSPlaygroundDemo + +简介 +•在本文中,CodeLab使用JavaScript演示来完成TODOLIST案例。 +•它旨在帮助开发人员快速了解HarmonyOS应用一次部署的经验,以进行多设备部署。 +•从项目创建、代码编写到编译、构造、部署和运行。 + +安装要求 +• 安装DevEco Studio和Node.js +• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 + +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 + +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 \ No newline at end of file diff --git a/JSPlaygroundDemo/RELEASE-NOTES.md b/JSPlaygroundDemo/RELEASE-NOTES.md new file mode 100644 index 00000000..ea23a13e --- /dev/null +++ b/JSPlaygroundDemo/RELEASE-NOTES.md @@ -0,0 +1,2 @@ +1.0.0 +1.Initial version \ No newline at end of file diff --git a/JSPlaygroundDemo/build.gradle b/JSPlaygroundDemo/build.gradle new file mode 100644 index 00000000..a55f3275 --- /dev/null +++ b/JSPlaygroundDemo/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.2.5' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} diff --git a/JSPlaygroundDemo/entry/build.gradle b/JSPlaygroundDemo/entry/build.gradle new file mode 100644 index 00000000..f946795e --- /dev/null +++ b/JSPlaygroundDemo/entry/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testCompile 'junit:junit:4.12' +} diff --git a/JSPlaygroundDemo/entry/src/main/config.json b/JSPlaygroundDemo/entry/src/main/config.json new file mode 100644 index 00000000..bef74643 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/config.json @@ -0,0 +1,62 @@ +{ + "app": { + "bundleName": "com.example.jsdemo", + "vendor": "example", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 4, + "target": 5, + "releaseType": "Beta1" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.example.jsdemo", + "name": ".MyApplication", + "deviceType": [ + "phone", + "tv", + "wearable" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "name": "com.example.jsdemo.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "JsDemo", + "type": "page", + "launchType": "standard" + } + ], + "js": [ + { + "pages": [ + "pages/index/index" + ], + "name": "default", + "window": { + "designWidth": 720, + "autoDesignWidth": false + } + } + ] + } +} \ No newline at end of file diff --git a/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MainAbility.java b/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MainAbility.java new file mode 100644 index 00000000..18469547 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MainAbility.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.jsdemo; + +import ohos.ace.ability.AceAbility; +import ohos.aafwk.content.Intent; + +/** + * MainAbility + * + * @since 2021-03-26 + */ +public class MainAbility extends AceAbility { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + } + + @Override + public void onStop() { + super.onStop(); + } +} diff --git a/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MyApplication.java b/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MyApplication.java new file mode 100644 index 00000000..36e0f40b --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/java/com/example/jsdemo/MyApplication.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.jsdemo; + +import ohos.aafwk.ability.AbilityPackage; + +/** + * MyApplication + * + * @since 2021-03-26 + */ +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/JSPlaygroundDemo/entry/src/main/js/default/app.js b/JSPlaygroundDemo/entry/src/main/js/default/app.js new file mode 100644 index 00000000..8e47afff --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/app.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 default { + onCreate() { + console.info('AceApplication onCreate'); + }, + onDestroy() { + console.info('AceApplication onDestroy'); + } +}; diff --git a/JSPlaygroundDemo/entry/src/main/js/default/common/checkbutton.png b/JSPlaygroundDemo/entry/src/main/js/default/common/checkbutton.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bc3d10a7a159af55cb2f8c2140be73b685f5e3 GIT binary patch literal 936 zcmV;Z16TZsP)Px&Vo5|nR9FeknY&IEQ51&HfdnrJN=z)Iput8Hk|VqTVCd)w4Hb>N0?)uJU}Hr? z=Aa3sf!)9Cz)JxFb{mHi zpMguWs(X67_AX;vSgCuj)WMcQxlMgjWE6X)55fWQsoUz3;p0ObpV|Bu5T{<73^{lkt>Do1+J@gj22UYd?X|-1QFe4< zb0#28dgwQcMvw!SaqyP5Wk!tWIGaW?tf5!L_(NN;Q-G1V7xWVDCt76S$HJ%<9T4j& zuIA7kB;?DJne5`^N%OWQxP^AX88mz^uxlcWY3za(0Qp5e5O(smnz_$~-fcLD7>f~e zG8pnmIUpB&mH4!3{>`=Jwl>`tw-IYO&dvl&c9;WlRm658kY!X~2{66gogvD$#Nd2i z>mrqYmGmR$)-6=F$skL=Y-TWJZ<7=smQ5E7o59f#(C;~|W3QEFxO2CDA!!2w_GP=Z z+P7${(D?bL^&JP?Yo4pbHnC)Y$3N36K?g+s;cEsfZ35=B6(Y^=s(|_Zt`J~)aQBV_ zy1=Q5C6)|uC#YO~RmBp^jv3qtsv)M9?y?DkVJJ8@x|mvA@w=#Y-Rjb?Y?DEjUD?c_ zma;hBJS=sa7}ljofbZFN#or*sX}#+8j#|WS5LA{`gJ*!Ga-V(65!zIWnG9kGaIl|i#!lNXiJ-(Yry3l?&$ zl~{3@W8kCgLK`;`!|H-Dt^*5O57yj+k#}Cd2o9#4@I_3wEkD<5dRs(9EI{ z4^efBN5EtTr0~@&zXf9g9cIUpNN=3?rCxpkGhniYY@SyFcCqDpW)B_zw(R5BuM#JI z=T@gLt+gfKrqAXUP)j6Z$hW;~>8sc-ot?f~UqnBP0@#lH8{#iAmmpKU(6g2R0000< KMNUMnLSTX_HN18J literal 0 HcmV?d00001 diff --git a/JSPlaygroundDemo/entry/src/main/js/default/common/delete.png b/JSPlaygroundDemo/entry/src/main/js/default/common/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a749c50a249e958a50fba36ee7ae390a908b5e GIT binary patch literal 1451 zcmV;c1yuTpP)Px)Wl2OqRA>d=T3c*XMHrr$vxl;6*-Nb@HKkM(wkc4o8%=5qF>0GoHL(PY@d0Cu z@*tu#5`!_Z@d3OPBv_5@{MUY--M4{S?=+^G;8Rt7>PEJqH z?w;8_z2LmeIWzPB|M$)L=l0K`#D~<_*ce>3a$O76STkX~ig8-ODXCzDl|#Kjj4{f| z6@&6C#Gs=*ZJfOH`_IRFdU_Itny2|HXnmmdre%@vla!Jc#@IcS(x8ei&UwNxjITK- z$7d!cKRWu=(LYq=Wm{ze_4Umqv9*=^^nms}B{U=z6_Rtpr;@4kyBCN4+~3=K>>m|f zo(aU`as9T{b$bGVWqU=ho35c^$V*%CHO34h^=9pcTMxCjw;Nt$JQ3KkWouQWB>V-_ zSc4a(g|^`a|E81#n!7&fn#`puCxPv)JMPu>z^B5;SLRaYYdt5U(TeEi&d!d(YBW7G*)V4O0svp6>mOtjUZA>}%F2rSIu0M`akJ-2 z;JVwO=Sh*9&_b7q+3v5%&5=!R?lgx025fXi3h+X!4YpUT0yR^@4exG3}0Q9kG~ol(M@9ej04EW3UKdg~cLeuUv}Hj0Ikf z#~&${*en9r9?aJYD~W!SL(*UnOmOcadOlxhe)z2C~qhN&=fmV73T|&(flbU~+Pb3=fTv)iu@R zx!unykpN-HKo&ZnOEpQ%8V)06k%~?+b?Pcg#D1Qf{=Sc_i`{MlL5}xSDwS1@6a0He zx=1pa%qrtnDezX7hL#`F8t=aU(SW8s;npZu8NjNLa08!6Oy@G=T8|DdDUST0ZLGWV z1;%LHwUviLuO$2gFJW;`C&aOpSIL5WbMzuyA=8+c5AY^dfnBSwYuG~>y(M4pQZCb% z5NC;50~SQ{bsK5R$_+9}AK(7eu*O)mRaoGIv$w^RN2+U9nP10O@B(MrFh;~uay|4> zAZ|Uz=d}0-f1mTa$utjb$%vbXNZ{jrBwRA-EHLT zgfi6?I~OisXJ)uBS4$7|61?0V$N}pd6Mm8ac7|A`2YgwZWCAaR=8Z(!xTLL*Z7R|N z>@jIfHO~cJ>dUlFpgiA{PVqOiP_%d`5-M*~-ORzLSMU;`pCk|*9{%;*GYlbaM2V#l zuQ?7Q_ARmW`CRgD?v&4=2$+H0Tn7;1&SltH9}b7CsnRQWsl!PEx>S?IY{rFfJPVdb zFRF&iagxGeMD&KLeX~7!9^l8vCzRw7j!%q@ufd&y2FZcJfkbU>eW}7U3Ni91k8o^45=Twp|IJVgK2_UP0nFjcH9H zh!k)Wp6@dBJiuqVoq_#1W55Y&sbBKtBmhF@HLJMzSg5-L&W&$Nx!&aF^Ue;==tA~} z7cQKgDhg^JhF6qb6C@ghOIh)Gd%HrPu}Fz|{A6t;x&pHU>|h8ohkJ+mGLE{sZeaxz$d{q&WZp002ovPDHLk FV1n)P!^8jp literal 0 HcmV?d00001 diff --git a/JSPlaygroundDemo/entry/src/main/js/default/common/done.png b/JSPlaygroundDemo/entry/src/main/js/default/common/done.png new file mode 100644 index 0000000000000000000000000000000000000000..bfd44b664b5c75cde229536fd5b8b889af80180b GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/JSPlaygroundDemo/entry/src/main/js/default/i18n/en-US.json b/JSPlaygroundDemo/entry/src/main/js/default/i18n/en-US.json new file mode 100644 index 00000000..e63c70d9 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/i18n/en-US.json @@ -0,0 +1,6 @@ +{ + "strings": { + "hello": "Hello", + "world": "World" + } +} \ No newline at end of file diff --git a/JSPlaygroundDemo/entry/src/main/js/default/i18n/zh-CN.json b/JSPlaygroundDemo/entry/src/main/js/default/i18n/zh-CN.json new file mode 100644 index 00000000..de6ee574 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/i18n/zh-CN.json @@ -0,0 +1,6 @@ +{ + "strings": { + "hello": "您好", + "world": "世界" + } +} \ No newline at end of file diff --git a/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.css b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.css new file mode 100644 index 00000000..3ba5a722 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.css @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + flex-direction: column; + background-color: black; +} + +.title { + font-weight: 600; + color: #ccc; + background-color: black; +} + +.tag-list { + width: 100%; +} + +.todo-list-item { + width: 100%; +} + +.todo-item { + height: 120px; + width: 100%; + border-radius: 5px; + align-items: center; +} + +.flex-row { + flex-direction: row; + align-item: center; +} + +.todo-name-mark { + width: 100%; + height: 100%; + align-items: center; +} + +.todo-name { + font-size: 32px; + color: white; + height: 100px; + margin-right: 5px; + max-lines: 1; + text-overflow: ellipsis; +} + +.text-default { + color: white; +} + +.text-gray { + color: gray; +} + +.todo-mark { + width: 18px; + height: 30%; + margin-left: 16px; + border-radius: 50px; + background-color: lightslategrey; +} + +.todo-time { + font-size: 32px; + width: 100%; + height: 100%; + text-align: left; + color: gray; + margin-top:2px; +} + +.urgent { + background-color: firebrick; +} + +.senior { + background-color: gold; +} + +.middle { + background-color: mediumaquamarine; +} + +.low { + background-color: #0D9FFB; +} + +.hide { + display: none; +} + +.show { + display: flex; +} + +.todo-image { + width: 50px; + height: 50%; + object-fit: contain; + margin-left: 10px; + margin-top: 3px; +} + +.todo-text-wrapper { + height: 100%; + flex-grow: 1; + margin: 0px 32px; + flex-direction: column; +} + +@media (device-type: tv) { + .todo-item { + height: 50px; + } + + .todo-name { + font-size: 18px; + } + + .todo-time { + font-size: 16px; + } + + .todo-mark { + width: 10px; + height: 10px; + } +} + +@media (device-type: phone) { + .title { + font-size: 42px; + margin-top: 36px; + margin-bottom: 36px; + margin-left: 24px; + } +} + +@media (device-type: wearable) { + .title { + font-size: 52px; + height: 20%; + text-align: center; + } + + .todo-list-item { + padding-left: 100px; + padding-right: 50px; + } +} \ No newline at end of file diff --git a/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.hml b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.hml new file mode 100644 index 00000000..1cf7129a --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.hml @@ -0,0 +1,32 @@ + + +
+ + {{ $t('strings.hello') }} {{title}} + + + +
+ +
+
+ {{$item.event}} + +
+ {{$item.time}} +
+
+
+
+
diff --git a/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.js b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.js new file mode 100644 index 00000000..f523d635 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/js/default/pages/index/index.js @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 device from '@system.device'; + +const BUTTON_STATE_IMAGE = ['/common/checkbutton.png', '/common/done.png']; +const TAG_STATE = ['show', 'hide']; +const TEXT_COLOR = ['text-default', 'text-gray']; +const EVENT_LEVEL = ['urgent', 'senior', 'middle', 'low']; + +export default { + data: { + title: "", + eventList: [ + "拿/获取", + "约会/安排", + "电子邮件", + "清除", + "购买"], + initialIndex: 0 + }, + onInit() { + this.title = this.$t('strings.world'); + this.$set('taskList', []); + }, + onShow() { + for (var index = 0; index < this.eventList.length; index++) { + const element = {}; + element.id = 'id-' + index; + element.event = this.eventList[index]; + element.time = this.getRandomTime(); + var completeState = this.getRandom(100) % 2; + element.checkBtn = BUTTON_STATE_IMAGE[completeState]; + element.color = TEXT_COLOR[completeState]; + element.showTag = TAG_STATE[completeState]; + element.tag = EVENT_LEVEL[this.getRandom(EVENT_LEVEL.length)]; + this.taskList.push(element); + } + + const _this = this; + device.getInfo({ + success: function (data) { + if (data.deviceType && data.deviceType === 'wearable') { + _this.initialIndex = 2; + } + }, + }); + }, + completeEvent(e) { + for (var i of this.taskList) { + if (i.id == e) { + if (i.checkBtn == "/common/done.png") { + i.checkBtn = "/common/checkbutton.png"; + i.showTag = 'show'; + i.color = 'text-default'; + i.completeState = false; + } else { + i.checkBtn = "/common/done.png"; + i.showTag = 'hide'; + i.color = 'text-gray'; + i.completeState = true; + } + return; + } + } + }, + getRandomTime() { + var hour = this.getRandom(24); + var minute = this.getRandom(60); + if (minute < 10) { + minute = '0' + minute; + } + return hour + ':' + minute; + }, + getRandom(range) { + var num = Math.random(); + num = num * range; + num = Math.floor(num); + return num; + } +} diff --git a/JSPlaygroundDemo/entry/src/main/resources/base/element/string.json b/JSPlaygroundDemo/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..55aa37a1 --- /dev/null +++ b/JSPlaygroundDemo/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "JsDemo" + }, + { + "name": "mainability_description", + "value": "JS_Phone_Empty Feature Ability" + } + ] +} \ No newline at end of file diff --git a/JSPlaygroundDemo/entry/src/main/resources/base/media/icon.png b/JSPlaygroundDemo/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 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 literal 0 HcmV?d00001 diff --git a/JSPlaygroundDemo/gradle/wrapper/gradle-wrapper.properties b/JSPlaygroundDemo/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..f59159e8 --- /dev/null +++ b/JSPlaygroundDemo/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/JSPlaygroundDemo/settings.gradle b/JSPlaygroundDemo/settings.gradle new file mode 100644 index 00000000..4773db73 --- /dev/null +++ b/JSPlaygroundDemo/settings.gradle @@ -0,0 +1 @@ +include ':entry' diff --git a/README.md b/README.md index 3bff79ac..1a0024ab 100644 --- a/README.md +++ b/README.md @@ -16,4 +16,6 @@ DistributedMail:展示了一个可以跨设备协同和分布式文件调用 ShoppingJs:使用HarmonyOS JS UI开发出一个购物应用,链接:https://gitee.com/openharmony/codelabs/tree/master/ShoppingJs -VoiceCamera:展示了一个使用分布式文件系统和AI语音识别功能开发的分布式语音照相机,链接:https://gitee.com/openharmony/codelabs/tree/master/VoiceCamera \ No newline at end of file +VoiceCamera:展示了一个使用分布式文件系统和AI语音识别功能开发的分布式语音照相机,链接:https://gitee.com/openharmony/codelabs/tree/master/VoiceCamera + +JSPlaygroundDemo:利用HarmonyOS“一次开发、多端部署”特性,开发一个能同时运行在手机、大屏、运动表的“To-Do List”Demo,链接:https://gitee.com/openharmony/codelabs/tree/master/JSPlaygroundDemo \ No newline at end of file -- Gitee From ad1310ee8cb6826947f9ab2ce7b3e6f26845000b Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 14 Apr 2021 17:28:23 +0800 Subject: [PATCH 04/41] update README.md. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3bded006..c2137b2c 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,5 @@ DistributedMail:展示了一个可以跨设备迁移和分布式文件调用 ShoppingJs:展示了一个使用JS UI组件开发的购物应用,链接:https://gitee.com/openharmony/codelabs/tree/master/ShoppingJs VoiceCamera:展示了一个基于分布式文件系统和AI语音识别功能开发的分布式语音照相机,链接:https://gitee.com/openharmony/codelabs/tree/master/VoiceCamera + +JSPlaygroundDemo:利用HarmonyOS“一次开发、多端部署”特性,开发一个能同时运行在手机、大屏、运动表的“To-Do List”Demo,链接:https://gitee.com/openharmony/codelabs/tree/master/JSPlaygroundDemo \ No newline at end of file -- Gitee From c16bf30340b1a36023e44c559b4e85d7137c41d4 Mon Sep 17 00:00:00 2001 From: pepper Date: Fri, 16 Apr 2021 15:49:43 +0800 Subject: [PATCH 05/41] update DistributedVideoCodelab/entry/src/main/java/com/huawei/codelab/VideoMigrateService.java. --- .../java/com/huawei/codelab/VideoMigrateService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DistributedVideoCodelab/entry/src/main/java/com/huawei/codelab/VideoMigrateService.java b/DistributedVideoCodelab/entry/src/main/java/com/huawei/codelab/VideoMigrateService.java index 0416b0ed..743bd7c1 100644 --- a/DistributedVideoCodelab/entry/src/main/java/com/huawei/codelab/VideoMigrateService.java +++ b/DistributedVideoCodelab/entry/src/main/java/com/huawei/codelab/VideoMigrateService.java @@ -55,21 +55,21 @@ public class VideoMigrateService extends Ability { @Override protected IRemoteObject onConnect(Intent intent) { - return new MyBinder(DESCRIPTOR); + return new MyRemote(DESCRIPTOR); } /** - * MyBinder + * MyRemote * * @since 2020-12-04 */ - private class MyBinder extends VideoMigrationStub { + private class MyRemote extends VideoMigrationStub { /** - * constructor of PlayerLoading + * constructor of MyRemote * * @param descriptor descriptor */ - MyBinder(String descriptor) { + MyRemote(String descriptor) { super(descriptor); } -- Gitee From e61eb3e1254ff2dc6a8465fcef2917718e25e187 Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 21 Apr 2021 11:18:49 +0800 Subject: [PATCH 06/41] update EducationSystem/entry/src/main/java/com/huawei/codelab/slice/PictureGameAbilitySlice.java. --- .../codelab/slice/PictureGameAbilitySlice.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/EducationSystem/entry/src/main/java/com/huawei/codelab/slice/PictureGameAbilitySlice.java b/EducationSystem/entry/src/main/java/com/huawei/codelab/slice/PictureGameAbilitySlice.java index 7eb33438..61648fd4 100644 --- a/EducationSystem/entry/src/main/java/com/huawei/codelab/slice/PictureGameAbilitySlice.java +++ b/EducationSystem/entry/src/main/java/com/huawei/codelab/slice/PictureGameAbilitySlice.java @@ -181,7 +181,7 @@ public class PictureGameAbilitySlice extends AbilitySlice { } } // Refresh the page display - setImageAndDecodeBounds(imageIndex); + setImages(imageIndex); // send data senDataToRemoteFun(); } @@ -205,7 +205,7 @@ public class PictureGameAbilitySlice extends AbilitySlice { clickImage.setVisibility(Component.INVISIBLE); } Image blankButton = (Image) findComponentById(blankResId); - blankButton.setImageAndDecodeBounds(imageList[imageIndex[position]]); + blankButton.setPixelMap(imageList[imageIndex[position]]); blankButton.setVisibility(Component.VISIBLE); int imageTemp = imageIndex[position]; @@ -278,7 +278,7 @@ public class PictureGameAbilitySlice extends AbilitySlice { if (loop) { LogUtil.info(TAG, "game is over"); setImageClickable(false); - imagePosition[imageCount - 1].setImageAndDecodeBounds(ResourceTable.Media_picture_09); + imagePosition[imageCount - 1].setPixelMap(ResourceTable.Media_picture_09); imagePosition[imageCount - 1].setVisibility(Component.VISIBLE); } } @@ -438,15 +438,15 @@ public class PictureGameAbilitySlice extends AbilitySlice { movePosition = intent.getIntParam(CommonData.KEY_MOVE_POSITION, -1); LogUtil.info(TAG, "receive moveImageId:" + moveImageId); LogUtil.info(TAG, "receive movePosition:" + movePosition); - getUITaskDispatcher().delayDispatch(() -> setImageAndDecodeBounds(imageIndex), DELAY_TIME); + getUITaskDispatcher().delayDispatch(() -> setImages(imageIndex), DELAY_TIME); } - private void setImageAndDecodeBounds(int[] imageIndex) { - LogUtil.info(TAG, "setImageAndDecodeBounds"); + private void setImages(int[] imageIndex) { + LogUtil.info(TAG, "setImages"); if (imageIndex != null && imageIndex.length > 0) { for (int index = 0; index < imageIndex.length; index++) { - imagePosition[index].setImageAndDecodeBounds(imageList[imageIndex[index]]); + imagePosition[index].setPixelMap(imageList[imageIndex[index]]); if (imageIndex[index] == 8) { imagePosition[index].setVisibility(Component.INVISIBLE); @@ -499,8 +499,8 @@ public class PictureGameAbilitySlice extends AbilitySlice { imageIndex[rand2] = imageTemp; } for (int i = 0; i < imageCount; i++) { - imagePosition[i].setImageAndDecodeBounds(imageList[imageIndex[i]]); + imagePosition[i].setPixelMap(imageList[imageIndex[i]]); } LogUtil.info(TAG, "pictureRandom end"); } -} +} \ No newline at end of file -- Gitee From 152f09c888705cb7bf622f47c3eb36023fd46c1a Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 21 Apr 2021 11:20:04 +0800 Subject: [PATCH 07/41] update EducationSystem/entry/src/main/resources/base/layout/ability_picture.xml. --- .../resources/base/layout/ability_picture.xml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/EducationSystem/entry/src/main/resources/base/layout/ability_picture.xml b/EducationSystem/entry/src/main/resources/base/layout/ability_picture.xml index 5f1c4084..f4df888d 100644 --- a/EducationSystem/entry/src/main/resources/base/layout/ability_picture.xml +++ b/EducationSystem/entry/src/main/resources/base/layout/ability_picture.xml @@ -41,7 +41,7 @@ ohos:id="$+id:pt_0000" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_01.jpg" + ohos:image_src="$media:picture_01" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -50,7 +50,7 @@ ohos:id="$+id:pt_0001" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_02.jpg" + ohos:image_src="$media:picture_02" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -59,7 +59,7 @@ ohos:id="$+id:pt_0002" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_03.jpg" + ohos:image_src="$media:picture_03" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -77,7 +77,7 @@ ohos:id="$+id:pt_0100" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_04.jpg" + ohos:image_src="$media:picture_04" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -86,7 +86,7 @@ ohos:id="$+id:pt_0101" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_05.jpg" + ohos:image_src="$media:picture_05" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -95,7 +95,7 @@ ohos:id="$+id:pt_0102" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_06.jpg" + ohos:image_src="$media:picture_06" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -114,7 +114,7 @@ ohos:id="$+id:pt_0200" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_07.jpg" + ohos:image_src="$media:picture_07" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -123,7 +123,7 @@ ohos:id="$+id:pt_0201" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_08.jpg" + ohos:image_src="$media:picture_08" ohos:padding="0" ohos:scale_mode="zoom_center"> @@ -132,7 +132,7 @@ ohos:id="$+id:pt_0202" ohos:height="70vp" ohos:width="70vp" - ohos:image_src="$media:picture_09.jpg" + ohos:image_src="$media:picture_09" ohos:padding="0" ohos:scale_mode="zoom_center" ohos:visibility="invisible"> @@ -177,7 +177,7 @@ ohos:id="$+id:final_image" ohos:height="210vp" ohos:width="210vp" - ohos:image_src="$media:picture.jpg" + ohos:image_src="$media:picture" ohos:layout_alignment="horizontal_center" ohos:scale_mode="zoom_center" ohos:top_margin="40vp"> -- Gitee From 72d7d2fed3b3e1470635936f54ef693ee493e40f Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 21 Apr 2021 11:25:09 +0800 Subject: [PATCH 08/41] update HarmonyOSNewsClient/entry/src/main/java/com/huawei/codelab/slice/NewsListAbilitySlice.java. --- .../huawei/codelab/slice/NewsListAbilitySlice.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/HarmonyOSNewsClient/entry/src/main/java/com/huawei/codelab/slice/NewsListAbilitySlice.java b/HarmonyOSNewsClient/entry/src/main/java/com/huawei/codelab/slice/NewsListAbilitySlice.java index b20ac1ef..264e358a 100644 --- a/HarmonyOSNewsClient/entry/src/main/java/com/huawei/codelab/slice/NewsListAbilitySlice.java +++ b/HarmonyOSNewsClient/entry/src/main/java/com/huawei/codelab/slice/NewsListAbilitySlice.java @@ -42,8 +42,8 @@ import java.util.List; * @since 2020-12-04 */ public class NewsListAbilitySlice extends AbilitySlice { - private static final float FOURCE_TEXT_SIZE = 1.2f; - private static final float UNFOURCE_TEXT_SIZE = 1.0f; + private static final float FORCUS_TEXT_SIZE = 1.2f; + private static final float UNFORCUS_TEXT_SIZE = 1.0f; private Text selectText; private ListContainer newsListContainer; @@ -131,13 +131,13 @@ public class NewsListAbilitySlice extends AbilitySlice { if (isFocus) { selectText.setTextColor( new Color(CommonUtils.getColor(NewsListAbilitySlice.this, ResourceTable.Color_news_type_text_on))); - selectText.setScaleX(FOURCE_TEXT_SIZE); - selectText.setScaleY(FOURCE_TEXT_SIZE); + selectText.setScaleX(FORCUS_TEXT_SIZE); + selectText.setScaleY(FORCUS_TEXT_SIZE); } else { selectText.setTextColor( new Color(CommonUtils.getColor(NewsListAbilitySlice.this, ResourceTable.Color_news_type_text_off))); - selectText.setScaleX(UNFOURCE_TEXT_SIZE); - selectText.setScaleY(UNFOURCE_TEXT_SIZE); + selectText.setScaleX(UNFORCUS_TEXT_SIZE); + selectText.setScaleY(UNFORCUS_TEXT_SIZE); } } @@ -156,4 +156,4 @@ public class NewsListAbilitySlice extends AbilitySlice { public void onForeground(Intent intent) { super.onForeground(intent); } -} +} \ No newline at end of file -- Gitee From 2a44f8347d422fc8f1896c16662ae1f8f80ec5bf Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 21 Apr 2021 11:26:06 +0800 Subject: [PATCH 09/41] update HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml. --- .../resources/base/layout/news_detail_layout.xml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml b/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml index 172464b9..1d43575f 100644 --- a/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml +++ b/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml @@ -23,14 +23,6 @@ ohos:alignment="vertical_center" ohos:orientation="horizontal"> - - @@ -126,7 +118,7 @@ ohos:id="$+id:button2" ohos:width="20vp" ohos:height="20vp" - ohos:image_src="$media:collect_icon.jpg" + ohos:image_src="$media:collect_icon" ohos:scale_mode="stretch" ohos:left_margin="20vp"/> @@ -134,7 +126,7 @@ ohos:id="$+id:button3" ohos:width="20vp" ohos:height="20vp" - ohos:image_src="$media:like_icon.jpg" + ohos:image_src="$media:like_icon" ohos:scale_mode="stretch" ohos:left_margin="20vp"/> @@ -142,7 +134,7 @@ ohos:id="$+id:button4" ohos:width="20vp" ohos:height="20vp" - ohos:image_src="$media:share_icon.jpg" + ohos:image_src="$media:share_icon" ohos:scale_mode="stretch" ohos:left_margin="20vp"/> -- Gitee From 214abdd66205d79db9d4e0dbbad4b67ff1548bfb Mon Sep 17 00:00:00 2001 From: pepper Date: Wed, 21 Apr 2021 11:28:44 +0800 Subject: [PATCH 10/41] update HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml. --- .../entry/src/main/resources/base/layout/news_detail_layout.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml b/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml index 1d43575f..63a79803 100644 --- a/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml +++ b/HarmonyOSNewsClient/entry/src/main/resources/base/layout/news_detail_layout.xml @@ -69,7 +69,7 @@ ohos:multiple_lines="true" ohos:text_color="#708090" ohos:text_size="16vp" - ohos:text_alignment="center_horizontal" + ohos:text_alignment="horizontal_center" ohos:top_margin="5vp"/> -- Gitee From 01a2eaa26492cce2e43392109005cd4cc9ba1410 Mon Sep 17 00:00:00 2001 From: "Xuzi(Fred" Date: Wed, 21 Apr 2021 22:00:15 +0800 Subject: [PATCH 11/41] UPDATE --- .../GameApplication/LICENSE | 78 ++ .../GameApplication/README.md | 17 + .../GameApplication/RELEASE-NOTES.MD | 1 + .../GameApplication/build.gradle | 36 + .../GameApplication/entry/build.gradle | 12 + .../entry/src/main/config.json | 126 +++ .../com/huawei/codelab/GameOverAbility.java | 36 + .../java/com/huawei/codelab/MainAbility.java | 36 + .../com/huawei/codelab/MyApplication.java | 32 + .../com/huawei/codelab/PlaneGameAbility.java | 36 + .../codelab/devices/DevicesListAdapter.java | 156 ++++ .../codelab/devices/SelectDeviceDialog.java | 146 ++++ .../java/com/huawei/codelab/game/Bomb.java | 46 + .../java/com/huawei/codelab/game/Bullet.java | 65 ++ .../com/huawei/codelab/game/EnemyPlane.java | 48 ++ .../com/huawei/codelab/game/Explosion.java | 54 ++ .../com/huawei/codelab/game/GameView.java | 625 ++++++++++++++ .../java/com/huawei/codelab/game/Handle.java | 201 +++++ .../java/com/huawei/codelab/game/MyPlane.java | 90 ++ .../java/com/huawei/codelab/game/Spirit.java | 196 +++++ .../codelab/service/GameServiceAbility.java | 119 +++ .../codelab/slice/GameOverAbilitySlice.java | 67 ++ .../codelab/slice/MainAbilitySlice.java | 225 +++++ .../codelab/slice/PlaneGameAbilitySlice.java | 69 ++ .../com/huawei/codelab/util/Constants.java | 122 +++ .../com/huawei/codelab/util/GameUtils.java | 136 +++ .../main/resources/base/element/string.json | 28 + .../graphic/background_ability_game_over.xml | 8 + .../base/graphic/background_ability_main.xml | 6 + .../graphic/background_ability_plane_game.xml | 8 + .../base/graphic/background_card.xml | 6 + .../base/graphic/background_text_field.xml | 8 + .../resources/base/graphic/button_element.xml | 9 + .../base/layout/ability_game_over.xml | 64 ++ .../resources/base/layout/ability_main.xml | 23 + .../base/layout/ability_plane_game.xml | 14 + .../base/layout/dialog_select_device.xml | 47 + .../base/layout/item_device_list.xml | 45 + .../src/main/resources/base/media/bg.png | Bin 0 -> 79643 bytes .../src/main/resources/base/media/big.png | Bin 0 -> 450149 bytes .../src/main/resources/base/media/bomb.png | Bin 0 -> 80476 bytes .../src/main/resources/base/media/boom.png | Bin 0 -> 391816 bytes .../src/main/resources/base/media/bullet.png | Bin 0 -> 33470 bytes .../resources/base/media/bullet_award.png | Bin 0 -> 601720 bytes .../src/main/resources/base/media/device.png | Bin 0 -> 202 bytes .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/planeOne.png | Bin 0 -> 46302 bytes .../main/resources/base/media/planeTwo.png | Bin 0 -> 43093 bytes .../src/main/resources/base/media/small.png | Bin 0 -> 197777 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + .../GameApplication/settings.gradle | 1 + DistributionGamePad-master/GameHandle/LICENSE | 78 ++ .../GameHandle/README.md | 16 + .../GameHandle/RELEASE-NOTES.MD | 1 + .../GameHandle/build.gradle | 36 + .../GameHandle/entry/.gitignore | 1 + .../GameHandle/entry/build.gradle | 13 + .../GameHandle/entry/src/main/config.json | 124 +++ .../com/huawei/codelab/HandleAbility.java | 23 + .../java/com/huawei/codelab/MainAbility.java | 33 + .../com/huawei/codelab/MyApplication.java | 19 + .../codelab/devices/DevicesListAdapter.java | 155 ++++ .../codelab/devices/SelectDeviceDialog.java | 145 ++++ .../com/huawei/codelab/handle/Handle.java | 64 ++ .../huawei/codelab/proxy/GameRemoteProxy.java | 97 +++ .../codelab/service/GameServiceAbility.java | 102 +++ .../codelab/slice/HandleAbilitySlice.java | 358 ++++++++ .../codelab/slice/MainAbilitySlice.java | 74 ++ .../com/huawei/codelab/utils/CalculAngle.java | 262 ++++++ .../com/huawei/codelab/utils/Constants.java | 77 ++ .../com/huawei/codelab/utils/LogUtil.java | 56 ++ .../com/huawei/codelab/utils/ScreenUtils.java | 83 ++ .../main/resources/base/element/string.json | 24 + .../graphic/background_ability_handle.xml | 8 + .../base/graphic/background_ability_main.xml | 6 + .../base/graphic/background_card.xml | 6 + .../base/graphic/background_text_field.xml | 8 + .../resources/base/graphic/button_element.xml | 7 + .../resources/base/layout/ability_handle.xml | 107 +++ .../resources/base/layout/ability_main.xml | 9 + .../base/layout/dialog_select_device.xml | 47 + .../base/layout/item_device_list.xml | 45 + .../entry/src/main/resources/base/media/a.png | Bin 0 -> 11780 bytes .../entry/src/main/resources/base/media/b.png | Bin 0 -> 11699 bytes .../src/main/resources/base/media/bg.png | Bin 0 -> 582189 bytes .../main/resources/base/media/bigcircle.png | Bin 0 -> 12901 bytes .../src/main/resources/base/media/device.png | Bin 0 -> 202 bytes .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../src/main/resources/base/media/pause.png | Bin 0 -> 11669 bytes .../main/resources/base/media/smallcircle.png | Bin 0 -> 10868 bytes .../java/com/huawei/codelab/ExampleTest.java | 9 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + .../GameHandle/settings.gradle | 1 + DistributionGamePad-master/LICENSE | 78 ++ DistributionGamePad-master/README.md | 13 + DistributionGamePad-master/RELEASE-NOTES.MD | 1 + RemoteInputDemo-master/LICENSE | 78 ++ RemoteInputDemo-master/README.md | 19 + RemoteInputDemo-master/RELEASE-NOTES.MD | 1 + RemoteInputDemo-master/build.gradle | 36 + RemoteInputDemo-master/entry/build.gradle | 13 + .../entry/src/main/config.json | 123 +++ .../java/com/huawei/codelab/MainAbility.java | 51 ++ .../com/huawei/codelab/MoviePlayAbility.java | 35 + .../com/huawei/codelab/MyApplication.java | 31 + .../huawei/codelab/RemoteInputAbility.java | 35 + .../codelab/adapter/DevicesListAdapter.java | 101 +++ .../huawei/codelab/callback/MainCallBack.java | 63 ++ .../codelab/component/SelectDeviceDialog.java | 110 +++ .../component/SimplePlayerController.java | 73 ++ .../huawei/codelab/constants/Constants.java | 53 ++ .../codelab/constants/EventConstants.java | 33 + .../codelab/data/ComponentPointData.java | 94 ++ .../codelab/data/ComponentPointDataMgr.java | 87 ++ .../huawei/codelab/proxy/ConnectManager.java | 44 + .../codelab/proxy/ConnectManagerIml.java | 110 +++ .../huawei/codelab/proxy/MyRemoteProxy.java | 97 +++ .../huawei/codelab/service/RemoteService.java | 122 +++ .../codelab/slice/MainAbilitySlice.java | 403 +++++++++ .../codelab/slice/MoviePlayAbilitySlice.java | 122 +++ .../slice/RemoteInputAbilitySlice.java | 166 ++++ .../com/huawei/codelab/utils/AbilityMgr.java | 100 +++ .../com/huawei/codelab/utils/LogUtils.java | 76 ++ .../codelab/utils/MovieSearchUtils.java | 53 ++ .../codelab/utils/WindowManagerUtils.java | 40 + .../main/resources/base/element/string.json | 28 + .../base/graphic/background_ability_main.xml | 5 + .../graphic/background_ability_movie_play.xml | 7 + .../background_ability_remote_input.xml | 9 + .../base/graphic/background_button.xml | 8 + .../base/graphic/background_card.xml | 6 + .../base/graphic/background_keyboard.xml | 8 + .../base/graphic/background_round.xml | 9 + .../base/graphic/background_text_field.xml | 8 + .../resources/base/layout/ability_main.xml | 810 ++++++++++++++++++ .../base/layout/ability_movie_play.xml | 14 + .../base/layout/ability_remote_input.xml | 177 ++++ .../base/layout/dialog_select_device.xml | 45 + .../base/layout/item_device_list.xml | 45 + .../simple_player_controller_layout.xml | 28 + .../src/main/resources/base/media/OK.png | Bin 0 -> 3574 bytes .../src/main/resources/base/media/TV.png | Bin 0 -> 611 bytes .../main/resources/base/media/WATCHFIT.png | Bin 0 -> 234823 bytes .../main/resources/base/media/WATCHGT2.png | Bin 0 -> 220034 bytes .../main/resources/base/media/WATCHGT2PRO.png | Bin 0 -> 194025 bytes .../src/main/resources/base/media/close.png | Bin 0 -> 3861 bytes .../src/main/resources/base/media/device.png | Bin 0 -> 202 bytes .../src/main/resources/base/media/down.png | Bin 0 -> 3582 bytes .../src/main/resources/base/media/goback.png | Bin 0 -> 4669 bytes .../resources/base/media/gubeishuizhen.mp4 | Bin 0 -> 11270712 bytes .../src/main/resources/base/media/huyang.png | Bin 0 -> 271353 bytes .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../src/main/resources/base/media/left.png | Bin 0 -> 3447 bytes .../main/resources/base/media/qijiandian.png | Bin 0 -> 277974 bytes .../src/main/resources/base/media/right.png | Bin 0 -> 3536 bytes .../src/main/resources/base/media/shamo.png | Bin 0 -> 164187 bytes .../src/main/resources/base/media/up.png | Bin 0 -> 2580 bytes .../main/resources/base/media/video_play.png | Bin 0 -> 359 bytes .../main/resources/base/media/video_stop.png | Bin 0 -> 182 bytes .../main/resources/base/media/wuxianerji.png | Bin 0 -> 211661 bytes .../main/resources/base/media/xingkonglan.png | Bin 0 -> 213322 bytes .../main/resources/base/media/yinxiang.png | Bin 0 -> 81015 bytes .../resources/base/media/zhinengyanjing.png | Bin 0 -> 119481 bytes RemoteInputDemo-master/gradle.properties | 10 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + RemoteInputDemo-master/settings.gradle | 1 + 169 files changed, 8830 insertions(+) create mode 100644 DistributionGamePad-master/GameApplication/LICENSE create mode 100644 DistributionGamePad-master/GameApplication/README.md create mode 100644 DistributionGamePad-master/GameApplication/RELEASE-NOTES.MD create mode 100644 DistributionGamePad-master/GameApplication/build.gradle create mode 100644 DistributionGamePad-master/GameApplication/entry/build.gradle create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/config.json create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/GameOverAbility.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MainAbility.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MyApplication.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/PlaneGameAbility.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/DevicesListAdapter.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/SelectDeviceDialog.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bomb.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bullet.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/EnemyPlane.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Explosion.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/GameView.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Handle.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/MyPlane.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Spirit.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/service/GameServiceAbility.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/GameOverAbilitySlice.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/PlaneGameAbilitySlice.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/Constants.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/GameUtils.java create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/element/string.json create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_game_over.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_main.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_plane_game.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_card.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_text_field.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/button_element.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_game_over.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_main.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_plane_game.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/dialog_select_device.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/item_device_list.xml create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/bg.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/big.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/bomb.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/boom.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/bullet.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/bullet_award.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/device.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/icon.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/planeOne.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/planeTwo.png create mode 100644 DistributionGamePad-master/GameApplication/entry/src/main/resources/base/media/small.png create mode 100644 DistributionGamePad-master/GameApplication/gradle/wrapper/gradle-wrapper.jar create mode 100644 DistributionGamePad-master/GameApplication/gradle/wrapper/gradle-wrapper.properties create mode 100644 DistributionGamePad-master/GameApplication/settings.gradle create mode 100644 DistributionGamePad-master/GameHandle/LICENSE create mode 100644 DistributionGamePad-master/GameHandle/README.md create mode 100644 DistributionGamePad-master/GameHandle/RELEASE-NOTES.MD create mode 100644 DistributionGamePad-master/GameHandle/build.gradle create mode 100644 DistributionGamePad-master/GameHandle/entry/.gitignore create mode 100644 DistributionGamePad-master/GameHandle/entry/build.gradle create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/config.json create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/HandleAbility.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/MainAbility.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/MyApplication.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/devices/DevicesListAdapter.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/devices/SelectDeviceDialog.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/handle/Handle.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/proxy/GameRemoteProxy.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/service/GameServiceAbility.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/slice/HandleAbilitySlice.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/utils/CalculAngle.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/utils/Constants.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/utils/LogUtil.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/java/com/huawei/codelab/utils/ScreenUtils.java create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/element/string.json create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/graphic/background_ability_handle.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/graphic/background_ability_main.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/graphic/background_card.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/graphic/background_text_field.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/graphic/button_element.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/layout/ability_handle.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/layout/ability_main.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/layout/dialog_select_device.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/layout/item_device_list.xml create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/a.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/b.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/bg.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/bigcircle.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/device.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/icon.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/pause.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/main/resources/base/media/smallcircle.png create mode 100644 DistributionGamePad-master/GameHandle/entry/src/test/java/com/huawei/codelab/ExampleTest.java create mode 100644 DistributionGamePad-master/GameHandle/gradle/wrapper/gradle-wrapper.jar create mode 100644 DistributionGamePad-master/GameHandle/gradle/wrapper/gradle-wrapper.properties create mode 100644 DistributionGamePad-master/GameHandle/settings.gradle create mode 100644 DistributionGamePad-master/LICENSE create mode 100644 DistributionGamePad-master/README.md create mode 100644 DistributionGamePad-master/RELEASE-NOTES.MD create mode 100644 RemoteInputDemo-master/LICENSE create mode 100644 RemoteInputDemo-master/README.md create mode 100644 RemoteInputDemo-master/RELEASE-NOTES.MD create mode 100644 RemoteInputDemo-master/build.gradle create mode 100644 RemoteInputDemo-master/entry/build.gradle create mode 100644 RemoteInputDemo-master/entry/src/main/config.json create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/MainAbility.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/MoviePlayAbility.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/MyApplication.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/RemoteInputAbility.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/adapter/DevicesListAdapter.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/callback/MainCallBack.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/component/SelectDeviceDialog.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/component/SimplePlayerController.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/constants/Constants.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/constants/EventConstants.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/data/ComponentPointData.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/data/ComponentPointDataMgr.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/proxy/ConnectManager.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/proxy/ConnectManagerIml.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/proxy/MyRemoteProxy.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/service/RemoteService.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/slice/MoviePlayAbilitySlice.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/slice/RemoteInputAbilitySlice.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/utils/AbilityMgr.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/utils/LogUtils.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/utils/MovieSearchUtils.java create mode 100644 RemoteInputDemo-master/entry/src/main/java/com/huawei/codelab/utils/WindowManagerUtils.java create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/element/string.json create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_ability_main.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_ability_movie_play.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_ability_remote_input.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_button.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_card.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_keyboard.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_round.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/graphic/background_text_field.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/ability_main.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/ability_movie_play.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/ability_remote_input.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/dialog_select_device.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/item_device_list.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/layout/simple_player_controller_layout.xml create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/OK.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/TV.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/WATCHFIT.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/WATCHGT2.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/WATCHGT2PRO.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/close.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/device.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/down.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/goback.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/gubeishuizhen.mp4 create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/huyang.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/icon.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/left.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/qijiandian.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/right.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/shamo.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/up.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/video_play.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/video_stop.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/wuxianerji.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/xingkonglan.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/yinxiang.png create mode 100644 RemoteInputDemo-master/entry/src/main/resources/base/media/zhinengyanjing.png create mode 100644 RemoteInputDemo-master/gradle.properties create mode 100644 RemoteInputDemo-master/gradle/wrapper/gradle-wrapper.jar create mode 100644 RemoteInputDemo-master/gradle/wrapper/gradle-wrapper.properties create mode 100644 RemoteInputDemo-master/settings.gradle diff --git a/DistributionGamePad-master/GameApplication/LICENSE b/DistributionGamePad-master/GameApplication/LICENSE new file mode 100644 index 00000000..e6fcc656 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/LICENSE @@ -0,0 +1,78 @@ + Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +Apache License, Version 2.0 +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: +1.You must give any other recipients of the Work or Derivative Works a copy of this License; and +2.You must cause any modified files to carry prominent notices stating that You changed the files; and +3.You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +4.If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/DistributionGamePad-master/GameApplication/README.md b/DistributionGamePad-master/GameApplication/README.md new file mode 100644 index 00000000..cc182595 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/README.md @@ -0,0 +1,17 @@ +# GameApplication + +What is it? The GameApplication is a phone project of DistributionGamePad. It use HarmonyOS distribution and graphic feature. +After start GameApplication it will ask you to choose the handles, You can choose one or two handles. When the selection is complete it will start handles automaticly. + + +Installation requirements • Install DevEco Studio and Node.js • Set up the DevEco Studio development environment. +The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. +The development environment can be configured according to the following two situations + +1.If you can directly access the Internet, just download the HarmonyOS SDK +2.If the network cannot access the Internet directly, it can be accessed through a proxy server • Generate secret key and apply for certificate +User guide • Download this Project • Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project • Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package • Click Run> Run 'entry' to run the hap package + +Note • You can choose to run the hap package on the simulator or the phone. • If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing Please see LICENSE for more info. \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/RELEASE-NOTES.MD b/DistributionGamePad-master/GameApplication/RELEASE-NOTES.MD new file mode 100644 index 00000000..9087a148 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/RELEASE-NOTES.MD @@ -0,0 +1 @@ +1.0.0.1 Initial version \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/build.gradle b/DistributionGamePad-master/GameApplication/build.gradle new file mode 100644 index 00000000..429a89b7 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } +} + +buildscript { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.0.1' + } +} + +allprojects { + repositories { + maven { + url 'https://mirrors.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/build.gradle b/DistributionGamePad-master/GameApplication/entry/build.gradle new file mode 100644 index 00000000..78fc120f --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 4 + defaultConfig { + compatibleSdkVersion 3 + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testCompile'junit:junit:4.12' +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/config.json b/DistributionGamePad-master/GameApplication/entry/src/main/config.json new file mode 100644 index 00000000..058da7cd --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/config.json @@ -0,0 +1,126 @@ +{ + "app": { + "bundleName": "com.huawei.codelab", + "vendor": "huawei", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 3, + "target": 4, + "releaseType": "Beta1" + } + }, + "deviceConfig": {}, + "module": { + "package": "com.huawei.codelab", + "name": ".MyApplication", + "deviceType": [ + "phone" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "com.huawei.codelab.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "GameApplication", + "type": "page", + "launchType": "standard" + }, + { + "orientation": "unspecified", + "name": "com.huawei.codelab.PlaneGameAbility", + "icon": "$media:icon", + "description": "$string:planegameability_description", + "label": "entry", + "type": "page", + "launchType": "standard" + }, + { + "backgroundModes": [ + "dataTransfer" + ], + "name": "com.huawei.codelab.service.GameServiceAbility", + "icon": "$media:icon", + "description": "$string:gameserviceability_description", + "type": "service" + }, + { + "orientation": "unspecified", + "name": "com.huawei.codelab.GameOverAbility", + "icon": "$media:icon", + "description": "$string:gameoverability_description", + "label": "entry", + "type": "page", + "launchType": "standard" + } + ], + "reqPermissions": [ + { + "name": "ohos.permission.DISTRIBUTED_DATASYNC", + "reason": "demo use distribution", + "usedScene": { + "ability": [ + ".MainAbility", + ".PlaneGameAbility", + ".GameOverAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE", + "reason": "demo use distribution", + "usedScene": { + "ability": [ + ".MainAbility", + ".PlaneGameAbility", + ".GameOverAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO", + "reason": "demo use distribution", + "usedScene": { + "ability": [ + ".MainAbility", + ".PlaneGameAbility", + ".GameOverAbility" + ], + "when": "inuse" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "demo use distribution", + "usedScene": { + "ability": [ + ".MainAbility", + ".PlaneGameAbility", + ".GameOverAbility" + ], + "when": "inuse" + } + } + ] + } +} \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/GameOverAbility.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/GameOverAbility.java new file mode 100644 index 00000000..d17f245a --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/GameOverAbility.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab; + +import com.huawei.codelab.slice.GameOverAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +/** + * game over ability + * + * @since 2021-03-15 + * + */ +public class GameOverAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(GameOverAbilitySlice.class.getName()); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MainAbility.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MainAbility.java new file mode 100644 index 00000000..c3e1dde6 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MainAbility.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab; + +import com.huawei.codelab.slice.MainAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +/** + * main ability + * + * @since 2021-03-15 + * + */ +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MyApplication.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MyApplication.java new file mode 100644 index 00000000..447dee92 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/MyApplication.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab; + +import ohos.aafwk.ability.AbilityPackage; + +/** + * myApplication + * + * @since 2021-03-15 + * + */ +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/PlaneGameAbility.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/PlaneGameAbility.java new file mode 100644 index 00000000..38ec5580 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/PlaneGameAbility.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab; + +import com.huawei.codelab.slice.PlaneGameAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +/** + * plane game ability + * + * @since 2021-03-15 + * + */ +public class PlaneGameAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(PlaneGameAbilitySlice.class.getName()); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/DevicesListAdapter.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/DevicesListAdapter.java new file mode 100644 index 00000000..8f7e7d76 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/DevicesListAdapter.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.devices; + +import com.huawei.codelab.ResourceTable; + +import ohos.agp.colors.RgbPalette; +import ohos.agp.components.AbsButton; +import ohos.agp.components.BaseItemProvider; +import ohos.agp.components.Checkbox; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.ComponentState; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.components.element.StateElement; +import ohos.app.Context; +import ohos.distributedschedule.interwork.DeviceInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * 设备列表适配器 + * + * @since 2021-01-11 + */ +public class DevicesListAdapter extends BaseItemProvider { + private static final int FOUR = 4; + private List deviceInfoList; + private Context context; + private List selectPositions = new ArrayList<>(); + + /** + * 设备列表适配器 构造函数 + * + * @param listBasicInfo listBasicInfo + * @param context context + * @since 2021-01-11 + */ + public DevicesListAdapter(List listBasicInfo, Context context) { + this.deviceInfoList = listBasicInfo; + this.context = context; + } + + @Override + public int getCount() { + return deviceInfoList == null ? 0 : deviceInfoList.size(); + } + + @Override + public Object getItem(int position) { + return Optional.of(deviceInfoList.get(position)); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public Component getComponent(int position, Component component, ComponentContainer componentContainer) { + ViewHolder viewHolder = null; + Component mComponent = component; + if (mComponent == null) { + mComponent = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_device_list, null, false); + viewHolder = new ViewHolder(); + if (mComponent.findComponentById(ResourceTable.Id_device_name) instanceof Checkbox) { + viewHolder.devicesName = (Checkbox) mComponent.findComponentById(ResourceTable.Id_device_name); + viewHolder.devicesName.setButtonElement(viewHolder.getCheckElement()); + viewHolder.devicesName.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() { + @Override + public void onCheckedChanged(AbsButton absButton, boolean isSelected) { + if (isSelected) { + selectPositions.add(new Integer(position)); + } else { + selectPositions.remove(new Integer(position)); + } + } + }); + } + if (mComponent.findComponentById(ResourceTable.Id_device_id) instanceof Text) { + viewHolder.devicesId = (Text) mComponent.findComponentById(ResourceTable.Id_device_id); + } + mComponent.setTag(viewHolder); + } else { + if (mComponent.getTag() instanceof ViewHolder) { + viewHolder = (ViewHolder) mComponent.getTag(); + } + } + if (viewHolder != null) { + viewHolder.devicesName.setText(deviceInfoList.get(position).getDeviceName()); + String deviceId = deviceInfoList.get(position).getDeviceId(); + deviceId = deviceId.substring(0, FOUR) + "****** " + deviceId.substring(deviceId.length() - FOUR); + viewHolder.devicesId.setText(deviceId); + } + return mComponent; + } + + /** + * 设备列表(设备名、设备ID) + * + * @return selectDeviceInfos + */ + public List getSelectDevices() { + List selectDeviceInfos = new ArrayList<>(deviceInfoList.size()); + for (int selectPosition: selectPositions) { + selectDeviceInfos.add(deviceInfoList.get(selectPosition)); + } + return selectDeviceInfos; + } + + /** + * 设备列表(设备名、设备ID) + * + * @since 2021-01-11 + */ + private static class ViewHolder { + private Checkbox devicesName; + private Text devicesId; + + /** + * getCheckElement + * + * @return checkElement + * @since 2021-01-11 + */ + public static StateElement getCheckElement() { + ShapeElement elementButtonOn = new ShapeElement(); + elementButtonOn.setRgbColor(RgbPalette.GREEN); + ShapeElement elementButtonOff = new ShapeElement(); + elementButtonOff.setRgbColor(RgbPalette.BLACK); + StateElement checkElement = new StateElement(); + checkElement.addState(new int[]{ComponentState.COMPONENT_STATE_CHECKED}, elementButtonOn); + checkElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, elementButtonOff); + + return checkElement; + } + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/SelectDeviceDialog.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/SelectDeviceDialog.java new file mode 100644 index 00000000..72592469 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/devices/SelectDeviceDialog.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.devices; + +import static ohos.security.SystemPermission.DISTRIBUTED_DATASYNC; + +import com.huawei.codelab.ResourceTable; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.agp.components.Component; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.ListContainer; +import ohos.agp.utils.LayoutAlignment; +import ohos.agp.window.dialog.CommonDialog; +import ohos.app.Context; +import ohos.bundle.IBundleManager; +import ohos.distributedschedule.interwork.DeviceInfo; +import ohos.distributedschedule.interwork.DeviceManager; + +import java.util.ArrayList; +import java.util.List; + +/** + * 选择设备列表的弹窗 + * + * @since 2021-01-11 + */ +public class SelectDeviceDialog { + private static final int EIGHTHUNDREDFORTY = 840; + private static final int NINEHUNDRED = 900; + private CommonDialog commonDialog; + private DevicesListAdapter devicesListAdapter; + private List allDevices; + private AbilitySlice abilitySlice; + private SelectResultListener listener; + + /** + * Select Result Listener + * + * @since 2021-01-11 + */ + public interface SelectResultListener { + /** + * call back + * + * @param selectDevices selectDevices + * @since 2021-01-11 + */ + void callBack(List selectDevices); + } + + /** + * Select Device Dialog + * + * @param slice slice + * @param listener listener + * @since 2021-01-11 + */ + public SelectDeviceDialog(AbilitySlice slice, SelectResultListener listener) { + this.abilitySlice = slice; + this.listener = listener; + this.allDevices = new ArrayList<>(); + } + + private void getDevices() { + if (allDevices.size() > 0) { + allDevices.clear(); + } + allDevices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); + } + + private void grantPermission(AbilitySlice slice) { + if (slice.verifySelfPermission(DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) { + if (slice.canRequestPermission(DISTRIBUTED_DATASYNC)) { + slice.requestPermissionsFromUser(new String[]{DISTRIBUTED_DATASYNC}, 0); + } + } + } + + /** + * Select Device Dialog + * + * @return this + * @since 2021-03-15 + */ + public SelectDeviceDialog initDialog() { + grantPermission(abilitySlice); + getDevices(); + Context context = abilitySlice.getContext(); + commonDialog = new CommonDialog(context); + commonDialog.setAlignment(LayoutAlignment.CENTER); + commonDialog.setSize(EIGHTHUNDREDFORTY, NINEHUNDRED); + commonDialog.setAutoClosable(false); + Component dialogLayout = LayoutScatter.getInstance(context) + .parse(ResourceTable.Layout_dialog_select_device, null, false); + commonDialog.setContentCustomComponent(dialogLayout); + if (dialogLayout.findComponentById(ResourceTable.Id_list_devices) instanceof ListContainer) { + ListContainer devicesListContainer = + (ListContainer) dialogLayout.findComponentById(ResourceTable.Id_list_devices); + devicesListAdapter = new DevicesListAdapter(allDevices, context); + devicesListContainer.setItemProvider(devicesListAdapter); + } + + dialogLayout.findComponentById(ResourceTable.Id_confirm).setClickedListener(component -> { + listener.callBack(getSelectDevices()); + commonDialog.hide(); + }); + + return this; + } + + /** + * 弹窗显示 + */ + public void show() { + commonDialog.show(); + } + + /** + * Get Selected Devices + * + * @return ArrayList + * @since 2021-03-15 + * + */ + public List getSelectDevices() { + if (devicesListAdapter != null) { + return devicesListAdapter.getSelectDevices(); + } + return new ArrayList<>(0); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bomb.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bomb.java new file mode 100644 index 00000000..7aa85a11 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bomb.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import com.huawei.codelab.util.GameUtils; + +import ohos.agp.render.PixelMapHolder; + +/** + * bomb + * + * @since 2021-03-15 + * + */ +public class Bomb extends Spirit { + private static final int SPEED_RATE = 2; + private static final int BOMB_Y_POSITION = 120; + + /** + * bomb constructor + * + * @param pixelMapHolder pixelMapHolder + * @since 2021-03-15 + * + */ + public Bomb(PixelMapHolder pixelMapHolder) { + super(pixelMapHolder); + this.setPlaneX(getRandom().nextInt(GameUtils.getScreenWidth() - BOMB_Y_POSITION)); + this.setPlaneY(-BOMB_Y_POSITION); + this.setSpeed((getRandom().nextInt(SPEED_RATE) + SPEED_RATE) * SPEED_RATE); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bullet.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bullet.java new file mode 100644 index 00000000..5a76deb4 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Bullet.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.PixelMapHolder; + +/** + * bullet + * + * @since 2021-03-15 + * + */ +public class Bullet extends Spirit { + private static final int BULLET_X_OFFSET = 85; + private static final int BULLET_Y_OFFSET = 10; + private static final int BULLET_SPEED = -20; + private String deviceId; // 设备id + + /** + * bullet constructor + * + * @param pixelMapHolder pixelMapHolder + * @param planeX planeX + * @param planeY planeY + * @since 2021-03-15 + * + */ + public Bullet(PixelMapHolder pixelMapHolder, int planeX, int planeY) { + super(pixelMapHolder); + this.setPlaneX(planeX + BULLET_X_OFFSET); + this.setPlaneY(planeY - BULLET_Y_OFFSET); + this.setSpeed(BULLET_SPEED); + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + @Override + public void afterDraw(Canvas canvas, Paint paint) { + if (getPlaneY() < 0) { + destroy(); + } + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/EnemyPlane.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/EnemyPlane.java new file mode 100644 index 00000000..69440ade --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/EnemyPlane.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import com.huawei.codelab.util.Constants; +import com.huawei.codelab.util.GameUtils; + +import ohos.agp.render.PixelMapHolder; + +/** + * enemyPlane + * + * @since 2021-03-15 + * + */ +public class EnemyPlane extends Spirit { + private static final int SPEED_RATE = 2; + + /** + * enemyPlane constructor + * + * @param pixelMapHolder pixelMapHolder + * @param planeIndex planeIndex + * @since 2021-03-15 + * + */ + public EnemyPlane(PixelMapHolder pixelMapHolder, int planeIndex) { + super(pixelMapHolder); + int size = (planeIndex == SPEED_RATE) ? Constants.SMALL_PLANE_SIZE : Constants.BIG_PLANE_SIZE; + this.setPlaneX(getRandom().nextInt(GameUtils.getScreenWidth() - size)); + this.setPlaneY(-size); + this.setSpeed((getRandom().nextInt(SPEED_RATE) + SPEED_RATE) * SPEED_RATE); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Explosion.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Explosion.java new file mode 100644 index 00000000..40ab0723 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Explosion.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.PixelMapHolder; + +/** + * explosion + * + * @since 2021-03-15 + * + */ +public class Explosion extends Spirit { + private static final int CLEAN_DESTROY_FRAME = 8; // 清除失效飞机帧数 + + /** + * explosion + * + * @param pixelMapHolder pixelMapHolder + * @param planeX planeX + * @param planeY planeY + * @since 2021-03-15 + * + */ + public Explosion(PixelMapHolder pixelMapHolder, int planeX, int planeY) { + super(pixelMapHolder); + this.setPlaneX(planeX); + this.setPlaneY(planeY); + this.setSpeed(0); + } + + @Override + public void afterDraw(Canvas canvas, Paint paint) { + if (0 == GameView.getFrame() % CLEAN_DESTROY_FRAME) { + destroy(); + } + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/GameView.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/GameView.java new file mode 100644 index 00000000..a337e7d3 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/GameView.java @@ -0,0 +1,625 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import com.huawei.codelab.ResourceTable; +import com.huawei.codelab.slice.MainAbilitySlice; +import com.huawei.codelab.util.Constants; +import com.huawei.codelab.util.GameUtils; + +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.PixelMapHolder; +import ohos.agp.utils.Color; +import ohos.agp.utils.TextAlignment; +import ohos.app.Context; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * gameView + * + * @since 2021-03-05 + */ +public class GameView extends Component implements Component.DrawTask { + private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "gameView"); + private static int status; // 状态 0主页面 1游戏进行中 2游戏暂停 3游戏结束 + private static int frame; // 画面帧数 + private static final int CREATE_ENEMY_PLANE_FRAME = 50; // 生成敌机帧数 + private static final int CREATE_BOMB_FRAME = 2000; // 生成手榴弹帧数 + private static final int CREATE_EXPLOSION_FRAME = 8; // 最后一架飞机爆炸帧数 + private static final int SPEED_RATE = 2; + private static final int MAXMYPLANENUM = 2; + private static final int SMALL_ENEMY_PLANE_INDEX = 2; + + private static final int PAINT_SIZE = 50; // 字体大小 + private static final int SCORE = 100; // 分数 + + private static final int LEFT_BOMB_PIC_H_POSITION = 50; // 左下角炸弹图标水平位置 + private static final int LEFT_BOMB_PIC_V_POSITION = 300; // 左下角炸弹图标垂直位置 + private static final int LEFT_BOMB_NUM_H_POSITION = 150; // 左下角炸弹数量水平位置 + private static final int LEFT_BOMB_NUM_V_POSITION = 240; // 左下角炸弹数量垂直方向位置 + private static final int RIGHT_BOMB_PIC_H_POSITION = 200; // 右下角炸弹图标水平位置 + private static final int RIGHT_BOMB_PIC_V_POSITION = 300; // 右下角炸弹图标垂直位置 + private static final int RIGHT_BOMB_NUM_H_POSITION = 100; // 右下角炸弹数量水平位置 + private static final int RIGHT_BOMB_NUM_V_POSITION = 240; // 右下角炸弹数量垂直方向位置 + + private static final int MY_PLANE_H_LIMIT = 200; // 我的飞机水平边界 + private static final int MY_PLANE_V_LIMIT = 400; // 我的飞机垂直边界 + private static final int MY_PLANE_INITIAL_POSITION = 300; // 我的飞机初始位置 + + private static final int ANGULAR_180 = 180; + + private static List explosions = new ArrayList<>(); // 爆炸效果集合 + + private static PixelMapHolder myPlaneOnePixelMapHolder; // 我的飞机一 + private static PixelMapHolder myPlaneTwoPixelMapHolder; // 我的飞机二 + private static PixelMapHolder smallEnemyPlanePixelMapHolder; // 小敌机 + private static PixelMapHolder bigEnemyPlanePixelMapHolder; // 大敌机 + private static PixelMapHolder bulletPixelMapHolder; // 子弹 + private static PixelMapHolder boomPixelMapHolder; // 爆炸 + private static PixelMapHolder bulletAwardPixelMapHolder; // 降落伞 + private static PixelMapHolder bombPixelMapHolder; // 炸弹 + private static PixelMapHolder bgPixelMapHolder; // 背景 + + private int playerOneScore = 0; // 玩家一分数 + private int playerTwoScore = 0; // 玩家二分数 + private int screenWidth; + private int screenHeight; + private Canvas nowCanvas; + + private List deviceIds; // 连接手柄id集合 + private List myPlanes; // 创建飞机集合 + private List enemyPlanes = new ArrayList<>(); // 敌机集合 + private List bombs = new ArrayList<>(); // 炸弹集合 + private List bullets = new ArrayList<>(); // 子弹集合 + + private Paint paint; + private Paint textPaint; + + private MyEventHandler myEventHandler; + private SecureRandom random; + + /** + * GameView constructor + * + * @param context context + */ + public GameView(Context context) { + super(context); + init(context, null); + } + + /** + * GameView constructor + * + * @param context context + * @param attrSet attrSet + */ + public GameView(Context context, AttrSet attrSet) { + super(context, attrSet); + GameUtils.setContext(context); + this.screenWidth = GameUtils.getScreenWidth(); + this.screenHeight = GameUtils.getScreenHeight(); + this.frame = 0; + myEventHandler = new MyEventHandler(EventRunner.create(true)); + random = new SecureRandom(); + init(context, attrSet); + } + + @Override + public void onDraw(Component component, Canvas canvas) { + this.nowCanvas = canvas; + // 画背景 + drawBackground(); + // 画我的飞机 + drawMyPlane(); + // 画敌机 + drawEnemyPlane(); + // 画炸弹 + drawBomb(); + // 画爆炸效果 + drawExplosion(); + // 画子弹 + drawBullet(); + frame++; + // 销毁敌机 + destroyEnemyPlane(); + // 我的飞机被敌机摧毁 + destroyMyPlane(); + // 捡降落伞 + gainBomb(); + // 游戏结束 + if ((status == Constants.GAME_STOP) && (0 == frame % CREATE_EXPLOSION_FRAME)) { + gameOver(); + return; + } + // 通过调用Invalidate()方法使得View持续渲染,实现动态效果 + getContext().getUITaskDispatcher().asyncDispatch(new Runnable() { + @Override + public void run() { + if (status != Constants.GAME_PAUSE) { // 暂停 + invalidate(); + } + } + }); + } + + private void init(Context context, AttrSet attrSet) { + paint = new Paint(); + paint.setStyle(Paint.Style.STROKE_STYLE); + textPaint = new Paint(); + textPaint.setTextAlign(TextAlignment.CENTER); + textPaint.setColor(Color.WHITE); + textPaint.setTextSize(PAINT_SIZE); + addDrawTask(this); + } + + /** + * receive PlaneGameAbilitySlice send data + * + * @param deviceIdList handles deviceid + * @since 2021-03-05 + */ + public void start(List deviceIdList) { + this.deviceIds = deviceIdList; + this.myPlanes = new ArrayList<>(deviceIds.size()); + setPixelMapHolder(); + // 创建飞机 + createMyPlane(); + } + + // 将图片id转换成PixMapHolder + private void setPixelMapHolder() { + myPlaneOnePixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_planeOne, + Constants.MY_PLANE_SIZE, Constants.MY_PLANE_SIZE); // 我的飞机一 + myPlaneTwoPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_planeTwo, + Constants.MY_PLANE_SIZE, Constants.MY_PLANE_SIZE); // 我的飞机二 + smallEnemyPlanePixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_small, + Constants.SMALL_PLANE_SIZE, Constants.SMALL_PLANE_SIZE); // 小敌机 + bigEnemyPlanePixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_big, + Constants.BIG_PLANE_SIZE, Constants.BIG_PLANE_SIZE); // 大敌机 + bulletPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_bullet, + Constants.BULLET_SIZE, Constants.BULLET_SIZE); // 子弹 + boomPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_boom, + Constants.BOOM_SIZE, Constants.BOOM_SIZE); // 爆炸 + bulletAwardPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_bullet_award, + Constants.AWARD_WIDTH, Constants.AWARD_HEIGHT); // 降落伞 + bombPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_bomb, + Constants.BOMB_WIDTH, Constants.BOMB_HEIGHT); // 炸弹 + bgPixelMapHolder = GameUtils.transIdToPixelMapHolder(ResourceTable.Media_bg, + this.screenWidth, this.screenHeight); // 背景 + } + + // 画背景 + private void drawBackground() { + // 添加背景 + nowCanvas.drawPixelMapHolder(bgPixelMapHolder, 0, 0, paint); + // 添加左下角、右下角炸弹数量显示 + for (MyPlane myPlane: myPlanes) { + if (myPlane.getIndex() == 0) { + // 左下角添加炸弹 + nowCanvas.drawPixelMapHolder(bombPixelMapHolder, LEFT_BOMB_PIC_H_POSITION, + this.screenHeight - LEFT_BOMB_PIC_V_POSITION, paint); + nowCanvas.drawText(textPaint, "X" + myPlane.getBombNum(), LEFT_BOMB_NUM_H_POSITION, + this.screenHeight - LEFT_BOMB_NUM_V_POSITION); + } else { + // 右下角添加炸弹 + nowCanvas.drawPixelMapHolder(bombPixelMapHolder, + this.screenWidth - RIGHT_BOMB_PIC_H_POSITION, + this.screenHeight - RIGHT_BOMB_PIC_V_POSITION, paint); + nowCanvas.drawText(textPaint, "X" + myPlane.getBombNum(), + this.screenWidth - RIGHT_BOMB_NUM_H_POSITION, this.screenHeight - RIGHT_BOMB_NUM_V_POSITION); + } + } + } + + // 创建我的飞机 + private void createMyPlane() { + int index = 0; + MyPlane myPlane = null; + int position = this.screenWidth / MAXMYPLANENUM - MY_PLANE_INITIAL_POSITION; + for (String deviceId : deviceIds) { + if (index == 0) { + myPlane = new MyPlane(myPlaneOnePixelMapHolder, position + index * MY_PLANE_INITIAL_POSITION, + this.screenHeight - MY_PLANE_V_LIMIT); + } else { + myPlane = new MyPlane(myPlaneTwoPixelMapHolder, position + index * MY_PLANE_INITIAL_POSITION, + this.screenHeight - MY_PLANE_V_LIMIT); + } + myPlane.setDeviceId(deviceId); + myPlane.setIndex(index); + InnerEvent event = InnerEvent.get(1, 0, myPlane); + myEventHandler.sendEvent(event); + myPlanes.add(myPlane); + index++; + } + } + + // 画我的飞机 + private void drawMyPlane() { + Iterator iterator = myPlanes.iterator(); + while (iterator.hasNext()) { + MyPlane myPlane = iterator.next(); + if (!myPlane.isDestroyed()) { + myPlane.draw(nowCanvas, paint); + } + } + } + + /** + * handles moving plane + * + * @param angle handles send angle + * @param deviceId handles deviceid + * @since 2021-03-05 + */ + public void movePlaneByHandles(int angle, String deviceId) { + MyPlane myPlane = null; + for (MyPlane nowMyPlane : myPlanes) { + if (nowMyPlane.getDeviceId().equals(deviceId)) { + myPlane = nowMyPlane; + } + } + if (myPlane == null) { + return; + } + myPlane.setPlaneX(myPlane.getPlaneX() + + ((int) (myPlane.getSpeed() * Math.cos(angle * (Math.PI / ANGULAR_180))))); + myPlane.setPlaneY(myPlane.getPlaneY() + - ((int) (myPlane.getSpeed() * Math.sin(angle * (Math.PI / ANGULAR_180))))); + if (myPlane.getPlaneX() < 0) { + myPlane.setPlaneX(0); + } + if (myPlane.getPlaneX() > this.screenWidth - MY_PLANE_H_LIMIT) { + myPlane.setPlaneX(this.screenWidth - MY_PLANE_H_LIMIT); + } + if (myPlane.getPlaneY() < 0) { + myPlane.setPlaneY(0); + } + if (myPlane.getPlaneY() > this.screenHeight - MY_PLANE_V_LIMIT) { + myPlane.setPlaneY(this.screenHeight - MY_PLANE_V_LIMIT); + } + } + + // create enemy plane random + private void createEnemyPlane() { + // 随机生成敌机 + int planeIndex = random.nextInt(SPEED_RATE) + SPEED_RATE; + PixelMapHolder enemyPlanePixelMapHolder = planeIndex == SMALL_ENEMY_PLANE_INDEX + ? smallEnemyPlanePixelMapHolder : bigEnemyPlanePixelMapHolder; + EnemyPlane enemyPlane = new EnemyPlane(enemyPlanePixelMapHolder, planeIndex); + enemyPlanes.add(enemyPlane); + } + + // create bomb random + private void createBomb() { + // 随机生成炸弹 + Bomb bomb = new Bomb(bulletAwardPixelMapHolder); + bombs.add(bomb); + } + + // 画敌机 + private void drawEnemyPlane() { + // 随机生成敌机 + if (0 == frame % CREATE_ENEMY_PLANE_FRAME) { + createEnemyPlane(); + } + Iterator iterator = enemyPlanes.iterator(); + while (iterator.hasNext()) { + EnemyPlane enemyPlane = iterator.next(); + if (!enemyPlane.isDestroyed()) { + enemyPlane.draw(nowCanvas, paint); + } else { + iterator.remove(); + } + } + } + + // 画炸弹(屏幕中降落伞) + private void drawBomb() { + // 随机生成炸弹 + if (0 == frame % CREATE_BOMB_FRAME) { + frame = 0; + createBomb(); + } + Iterator iterator = bombs.iterator(); + while (iterator.hasNext()) { + Bomb bomb = iterator.next(); + if (!bomb.isDestroyed()) { + bomb.draw(nowCanvas, paint); + } else { + iterator.remove(); + } + } + } + + // 画爆炸效果 + private void drawExplosion() { + Iterator iterator = explosions.iterator(); + while (iterator.hasNext()) { + Explosion explosion = iterator.next(); + if (!explosion.isDestroyed()) { + explosion.draw(nowCanvas, paint); + } else { + iterator.remove(); + } + } + } + + /** + * Create a bullet based on deviceId. + * + * @param deviceId deviceId + */ + public void createBulletByDeviceId(String deviceId) { + createBullet(getMyPlaneByDeviceId(deviceId)); + } + + // 我的飞机创建子弹 + private void createBullet(MyPlane myPlane) { + if (myPlane == null) { + return; + } + Bullet bullet = new Bullet(bulletPixelMapHolder, myPlane.getPlaneX(), myPlane.getPlaneY()); + bullet.setDeviceId(myPlane.getDeviceId()); + bullets.add(bullet); + } + + // 画子弹 + private void drawBullet() { + Iterator iterator = bullets.iterator(); + while (iterator.hasNext()) { + Bullet bullet = iterator.next(); + if (!bullet.isDestroyed()) { + bullet.draw(nowCanvas, paint); + } else { + iterator.remove(); + } + } + } + + // 子弹碰撞敌机 + private void destroyEnemyPlane() { + MyPlane myPlane = null; + Iterator iterator = bullets.iterator(); + while (iterator.hasNext()) { + Bullet bullet = iterator.next(); + for (MyPlane nowMyPlane : myPlanes) { + if (nowMyPlane.getDeviceId().equals(bullet.getDeviceId())) { + myPlane = nowMyPlane; + break; + } + } + if (!bullet.isDestroyed() && (myPlane != null)) { + EnemyPlane enemyPlane = null; + Spirit spirit = bullet.collideWithOther(enemyPlanes); + if (spirit instanceof EnemyPlane) { + enemyPlane = (EnemyPlane) spirit; + } + if (enemyPlane != null) { + createExposion(enemyPlane.getPlaneX(), enemyPlane.getPlaneY()); + iterator.remove(); + enemyPlanes.remove(enemyPlane); + myPlane.setScore(myPlane.getScore() + SCORE); + InnerEvent event = InnerEvent.get(1, 0, myPlane); + myEventHandler.sendEvent(event); + } + } + } + } + + // 我的飞机碰撞敌机 + private void destroyMyPlane() { + Iterator iterator = myPlanes.iterator(); + while (iterator.hasNext()) { + MyPlane myPlane = iterator.next(); + if (!myPlane.isDestroyed()) { + EnemyPlane enemyPlane = null; + Spirit spirit = myPlane.collideWithOther(enemyPlanes); + if (spirit instanceof EnemyPlane) { + enemyPlane = (EnemyPlane) spirit; + } + if (enemyPlane != null) { + createExposion(myPlane.getPlaneX(), myPlane.getPlaneY()); + createExposion(enemyPlane.getPlaneX(), enemyPlane.getPlaneY()); + enemyPlanes.remove(enemyPlane); + myPlane.setBombNum(0); + myPlane.destroy(); + if (myPlanes.size() == MAXMYPLANENUM) { + iterator.remove(); + } else { + status = Constants.GAME_STOP; // 游戏结束标识 + } + } + } + } + } + + // 捡炸弹(我的飞机触碰降落伞) + private void gainBomb() { + Iterator iterator = bombs.iterator(); + while (iterator.hasNext()) { + Bomb bomb = iterator.next(); + if (!bomb.isDestroyed()) { + MyPlane myPlane = null; + Spirit spirit = bomb.collideWithOther(myPlanes); + if (spirit instanceof MyPlane) { + myPlane = (MyPlane) spirit; + } + if (myPlane != null) { + myPlane.setBombNum(myPlane.getBombNum() + 1); + bomb.destroy(); + iterator.remove(); + } + } + } + } + + // 游戏结束 + private void gameOver() { + MainAbilitySlice.getHandles().get(0).gameOver(playerOneScore, playerTwoScore); + } + + /** + * Use bombs to destroy enemy planes based on device IDs. + * + * @param deviceId deviceId + */ + public void bombEnemyPlaneByDeviceId(String deviceId) { + MyPlane myPlane = getMyPlaneByDeviceId(deviceId); + if (myPlane == null) { + return; + } + if (myPlane.getBombNum() == 0) { + return; + } + bombEnemyPlane(myPlane); + } + + // 使用炸弹摧毁敌机 + private void bombEnemyPlane(MyPlane myPlane) { + int score = 0; // 炸弹摧毁屏幕敌机获得分数 + myPlane.setBombNum(myPlane.getBombNum() - 1); + Iterator iteratorEnemyPlane = enemyPlanes.iterator(); + while (iteratorEnemyPlane.hasNext()) { + EnemyPlane enemyPlane = iteratorEnemyPlane.next(); + if (!enemyPlane.isDestroyed()) { + createExposion(enemyPlane.getPlaneX(), enemyPlane.getPlaneY()); + score += SCORE; + enemyPlane.destroy(); + } + } + myPlane.setScore(myPlane.getScore() + score); + InnerEvent event = InnerEvent.get(1, 0, myPlane); + myEventHandler.sendEvent(event); + } + + /** + * pause + * + * @param deviceId deviceId + */ + public void pause(String deviceId) { + if (getMyPlaneByDeviceId(deviceId) == null) { + return; + } + status = Constants.GAME_PAUSE; + } + + /** + * restart game + * + * @param deviceId deviceId + */ + public void restart(String deviceId) { + if (getMyPlaneByDeviceId(deviceId) == null) { + return; + } + status = Constants.GAME_START; + getContext().getUITaskDispatcher().asyncDispatch(new Runnable() { + @Override + public void run() { + invalidate(); + } + }); + } + + // 获取状态 + public static int getStatus() { + return status; + } + + // 设置状态 + public static void setStatus(int handleStatus) { + status = handleStatus; + } + + /** + * Obtain the number of frames. + * + * @return frame + */ + public static int getFrame() { + return frame; + } + + /** + * Obtains the MyPlane based on deviceId. + * + * @param deviceId deviceId + * @return myfPlane + */ + private MyPlane getMyPlaneByDeviceId(String deviceId) { + MyPlane myPlane = null; + for (MyPlane nowMyPlane : myPlanes) { + if (nowMyPlane.getDeviceId().equals(deviceId)) { + myPlane = nowMyPlane; + } + } + return myPlane; + } + + /** + * CircleProgressView + * + * @param planeX x Coordinates + * @param planeY y Coordinates + */ + public static void createExposion(int planeX, int planeY) { + Explosion explosion = new Explosion(boomPixelMapHolder, planeX, planeY); + explosions.add(explosion); + } + + /** + * myEventHandler + * + * @since 2021-03-15 + */ + private class MyEventHandler extends EventHandler { + MyEventHandler(EventRunner runner) throws IllegalArgumentException { + super(runner); + } + + @Override + protected void processEvent(InnerEvent event) { + super.processEvent(event); + int eventId = event.eventId; + if (eventId == 1) { + if (event.object instanceof MyPlane) { + MyPlane myPlane = (MyPlane) event.object; + if (myPlane.getIndex() == 0) { + playerOneScore = myPlane.getScore(); + } else { + playerTwoScore = myPlane.getScore(); + } + MainAbilitySlice.returnScore(myPlane.getScore(), myPlane.getDeviceId()); + } + } + } + } +} \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Handle.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Handle.java new file mode 100644 index 00000000..297b8d51 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Handle.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import com.huawei.codelab.slice.MainAbilitySlice; +import com.huawei.codelab.util.Constants; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.bundle.ElementName; + +/** + * handle + * + * @since 2021-03-15 + * + */ +public class Handle { + private String deviceId; // 连接设备id + private boolean isConn; // 是否连接 + private MainAbilitySlice.GameRemoteProxy proxy; // 远程连接类 + private AbilitySlice abilitySlice; // 当前slice对象 + private GameView gameView; + + /** + * handle constructor + * + * @param abilitySlice abilitySlice + * @since 2021-03-15 + * + */ + public Handle(AbilitySlice abilitySlice) { + this.abilitySlice = abilitySlice; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public boolean isConn() { + return isConn; + } + + public void setConn(boolean isNowConn) { + this.isConn = isNowConn; + } + + public MainAbilitySlice.GameRemoteProxy getProxy() { + return proxy; + } + + public void setProxy(MainAbilitySlice.GameRemoteProxy proxy) { + this.proxy = proxy; + } + + public GameView getGameView() { + return gameView; + } + + public void setGameView(GameView gameView) { + this.gameView = gameView; + } + + public AbilitySlice getAbilitySlice() { + return abilitySlice; + } + + public void setAbilitySlice(AbilitySlice abilitySlice) { + this.abilitySlice = abilitySlice; + } + + // 开始/重新开始 + private void startGame() { + Intent intent = new Intent(); + ElementName element = new ElementName("", abilitySlice.getBundleName(), + abilitySlice.getBundleName() + ".PlaneGameAbility"); + intent.setElement(element); + abilitySlice.startAbility(intent); + } + + // 退出到主页面 + private void quitGame() { + Intent intent = new Intent(); + ElementName element = new ElementName("", abilitySlice.getBundleName(), + abilitySlice.getBundleName() + ".MainAbility"); + intent.setElement(element); + abilitySlice.startAbility(intent); + } + + /** + * game over + * + * @param playerOneScore playerOneScore + * @param playerTwoScore playerTwoScore + */ + public void gameOver(int playerOneScore, int playerTwoScore) { + Intent intent = new Intent(); + intent.setParam("playerOneScore", playerOneScore); + intent.setParam("playerTwoScore", playerTwoScore); + ElementName element = new ElementName("", abilitySlice.getBundleName(), + abilitySlice.getBundleName() + ".GameOverAbility"); + intent.setElement(element); + abilitySlice.startAbility(intent); + GameView.setStatus(Constants.GAME_STOP); + } + + // 移动飞机 + private void movePlane(int angle) { + gameView.movePlaneByHandles(angle, deviceId); + } + + // 发射子弹 + private void createBullet() { + gameView.createBulletByDeviceId(deviceId); // 发射子弹 + } + + // 使用炸弹 + private void useBomb() { + gameView.bombEnemyPlaneByDeviceId(deviceId); + } + + // 暂停 + private void pause() { + gameView.pause(deviceId); + } + + // 取消暂停 + private void reStart() { + gameView.restart(deviceId); + } + + /** + * Processing Handle End Data + * + * @param angle angle + * @param buttonA buttonA + * @param buttonB buttonB + * @param pause pause + * @param start start + */ + public void operation(int angle, int buttonA, int buttonB, int pause, int start) { + switch (GameView.getStatus()) { + case Constants.GAME_UNREADY: // 0游戏未开始 + if (start != 0) { + startGame(); // 开始游戏 + GameView.setStatus(Constants.GAME_START); + } + break; + case Constants.GAME_START: // 1游戏进行中 + if (angle != 0) { + movePlane(angle); // 移动飞机 + } + if (buttonA != 0) { + createBullet(); // 发射子弹 + } + if (buttonB != 0) { + useBomb(); // 使用炸弹(清空屏幕敌机) + } + if (pause != 0) { + pause(); // 暂停 + } + break; + case Constants.GAME_PAUSE: // 2游戏暂停 + if (start != 0) { // 取消暂停 + reStart(); + GameView.setStatus(Constants.GAME_START); + } + break; + case Constants.GAME_STOP: // 3游戏结束 + if (pause != 0) { // 返回到主页 + quitGame(); + GameView.setStatus(Constants.GAME_UNREADY); + } + if (start != 0) { // 重新开始游戏 + startGame(); + GameView.setStatus(Constants.GAME_START); + } + break; + default: + break; + } + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/MyPlane.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/MyPlane.java new file mode 100644 index 00000000..560d319e --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/MyPlane.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.PixelMapHolder; + +/** + * myPlane + * + * @since 2021-03-15 + * + */ +public class MyPlane extends Spirit { + private static final int SPEED = 30; + private String deviceId; // 飞机id + private int score; // 分数 + private int index; // 飞机下标,目前两架飞机,取值0、1 + private int bombNum; // 炸弹数量 + + /** + * myPlane constructor + * + * @param pixelMapHolder pixelMapHolder + * @param planeX planeX + * @param planeY planeY + * @since 2021-03-15 + * + */ + public MyPlane(PixelMapHolder pixelMapHolder, int planeX, int planeY) { + super(pixelMapHolder); + this.setPlaneX(planeX); + this.setPlaneY(planeY); + this.setSpeed(SPEED); + this.setScore(0); + this.setBombNum(0); + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public int getBombNum() { + return bombNum; + } + + public void setBombNum(int bombNum) { + this.bombNum = bombNum; + } + + @Override + public void draw(Canvas canvas, Paint paint) { + canvas.drawPixelMapHolder(getPixelMapHolder(), getPlaneX(), getPlaneY(), paint); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Spirit.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Spirit.java new file mode 100644 index 00000000..e9c088ff --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/game/Spirit.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.game; + +import com.huawei.codelab.util.GameUtils; + +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.PixelMapHolder; +import ohos.agp.utils.RectFloat; + +import java.security.SecureRandom; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +/** + * spirit + * + * @since 2021-03-15 + * + */ +public abstract class Spirit { + private SecureRandom random = new SecureRandom(); + private Optional optionalEmpty = Optional.empty(); + private PixelMapHolder pixelMapHolder; // 图片 + private int planeX; // x坐标 + private int planeY; // y坐标 + private int width; // 宽 + private int height; // 高 + private int speed; // 速度 + private boolean destroyed; // 是否被销毁 + + /** + * spirit constructor + * + * @param pixelMapHolder pixelMapHolder + * @since 2021-03-15 + * + */ + public Spirit(PixelMapHolder pixelMapHolder) { + this.pixelMapHolder = pixelMapHolder; + this.destroyed = false; + this.width = pixelMapHolder.getPixelMap().getImageInfo().size.width; + this.height = pixelMapHolder.getPixelMap().getImageInfo().size.height; + } + + public SecureRandom getRandom() { + return random; + } + + public PixelMapHolder getPixelMapHolder() { + return pixelMapHolder; + } + + public int getPlaneX() { + return planeX; + } + + public void setPlaneX(int planeX) { + this.planeX = planeX; + } + + public int getPlaneY() { + return planeY; + } + + public void setPlaneY(int planeY) { + this.planeY = planeY; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public boolean isDestroyed() { + return destroyed; + } + + /** + * destroy + * + * @since 2021-03-15 + * + */ + public void destroy() { + pixelMapHolder = null; + destroyed = true; + } + + /** + * collideWithOther + * + * @param spirits spirits + * @return true + * + */ + public Spirit collideWithOther(List spirits) { + Iterator iterator = spirits.iterator(); + while (iterator.hasNext()) { + Spirit spirit = iterator.next(); + RectFloat r1 = new RectFloat(spirit.getPlaneX(), spirit.getPlaneY(), + spirit.getPlaneX() + spirit.getWidth(), + spirit.getPlaneY() + spirit.getHeight()); + RectFloat r2 = new RectFloat(planeX, planeY, planeX + width, + planeY + height); + if (r1.getIntersectRect(r2)) { // 碰撞 + return spirit; + } + } + return optionalEmpty.orElse(null); + } + + /** + * draw + * + * @param canvas canvas + * @param paint paint + * + */ + public void draw(Canvas canvas, Paint paint) { + beforeOndraw(); + onDraw(canvas, paint); + afterDraw(canvas, paint); + } + + /** + * before draw + * + * @since 2021-03-15 + * + */ + public void beforeOndraw() { + move(); + } + + /** + * on draw + * + * @param canvas canvas + * @param paint paint + * + */ + public void onDraw(Canvas canvas, Paint paint) { + canvas.drawPixelMapHolder(pixelMapHolder, planeX, planeY, paint); + } + + /** + * after draw + * + * @param canvas canvas + * @param paint paint + * + */ + public void afterDraw(Canvas canvas, Paint paint) { + if (GameUtils.getScreenHeight() < planeY) { + destroy(); + } + } + + /** + * myPlane + * + * @since 2021-03-15 + * + */ + public void move() { + planeY += speed; + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/service/GameServiceAbility.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/service/GameServiceAbility.java new file mode 100644 index 00000000..33a18145 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/service/GameServiceAbility.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.service; + +import com.huawei.codelab.game.Handle; +import com.huawei.codelab.slice.MainAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.app.dispatcher.TaskDispatcher; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; +import ohos.rpc.IRemoteBroker; +import ohos.rpc.IRemoteObject; +import ohos.rpc.MessageOption; +import ohos.rpc.MessageParcel; +import ohos.rpc.RemoteObject; + +/** + * game service ability + * + * @since 2021-03-15 + * + */ +public class GameServiceAbility extends Ability { + private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo"); + + private GameRemoteObject remoteObject = new GameRemoteObject(); + private TaskDispatcher taskDispatcher; + + @Override + public void onStart(Intent intent) { + HiLog.error(LABEL_LOG, "GameServiceAbility::onStart"); + super.onStart(intent); + taskDispatcher = this.getUITaskDispatcher(); + } + + @Override + public void onBackground() { + super.onBackground(); + HiLog.info(LABEL_LOG, "GameServiceAbility::onBackground"); + } + + @Override + public void onStop() { + super.onStop(); + HiLog.info(LABEL_LOG, "GameServiceAbility::onStop"); + } + + @Override + public void onCommand(Intent intent, boolean isRestart, int startId) { + } + + @Override + public IRemoteObject onConnect(Intent intent) { + super.onStart(intent); + return remoteObject; + } + + @Override + public void onDisconnect(Intent intent) { + } + + /** + * game remote object + * + * @since 2021-03-15 + * + */ + private class GameRemoteObject extends RemoteObject implements IRemoteBroker { + private static final int ERR_OK = 0; + private static final String TAG = "GameService"; + + GameRemoteObject() { + super("descriptor"); + } + + @Override + public IRemoteObject asObject() { + return this; + } + + @Override + public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) { + String deviceId = data.readString(); + int angle = data.readInt(); + int buttonA = data.readInt(); + int buttonB = data.readInt(); + int pause = data.readInt(); + int start = data.readInt(); + taskDispatcher.syncDispatch(new Runnable() { + @Override + public void run() { + for (Handle handle: MainAbilitySlice.getHandles()) { + if (deviceId.equals(handle.getDeviceId())) { + handle.operation(angle, buttonA, buttonB, pause, start); + break; + } + } + } + }); + return true; + } + } +} \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/GameOverAbilitySlice.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/GameOverAbilitySlice.java new file mode 100644 index 00000000..0a7098de --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/GameOverAbilitySlice.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.slice; + +import com.huawei.codelab.ResourceTable; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.components.Text; + +/** + * game over ability slice + * + * @since 2021-03-15 + * + */ +public class GameOverAbilitySlice extends AbilitySlice { + private static final String KEYONE = "playerOneScore"; + private static final String KEYTWO = "playerTwoScore"; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_game_over); + + // 获得玩家分数 + Object scoreOne = intent.getParams().getParam(KEYONE); + Object scoreTwo = intent.getParams().getParam(KEYTWO); + + // 设置分数 + Component componentOne = findComponentById(ResourceTable.Id_playerOne); + Component componentTwo = findComponentById(ResourceTable.Id_playerTwo); + if (componentOne instanceof Text) { + Text textOne = (Text) componentOne; + textOne.setText("玩家一分数:" + scoreOne); + } + if (componentTwo instanceof Text) { + Text textTwo = (Text) componentTwo; + textTwo.setText("玩家二分数:" + scoreTwo); + } + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java new file mode 100644 index 00000000..87a13e4a --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.slice; + +import com.huawei.codelab.MainAbility; +import com.huawei.codelab.ResourceTable; +import com.huawei.codelab.devices.SelectDeviceDialog; +import com.huawei.codelab.game.Handle; +import com.huawei.codelab.service.GameServiceAbility; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.ability.IAbilityConnection; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.bundle.ElementName; +import ohos.distributedschedule.interwork.DeviceInfo; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; +import ohos.rpc.IRemoteBroker; +import ohos.rpc.IRemoteObject; +import ohos.rpc.MessageOption; +import ohos.rpc.MessageParcel; +import ohos.rpc.RemoteException; + +import java.util.ArrayList; +import java.util.List; + +/** + * game over ability slice + * + * @since 2021-03-15 + * + */ +public class MainAbilitySlice extends AbilitySlice { + private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "mainAbilitySlice"); + private static List handles = new ArrayList<>(); // 保存手柄连接信息 + private SelectDeviceDialog dialog; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + + // 设备弹出框 + if (handles == null || handles.size() == 0) { // 清空连接信息 + dialog = showDialog(); + dialog.initDialog().show(); + startService(); + } + } + + // 设备选择弹出框 + private SelectDeviceDialog showDialog() { + return new SelectDeviceDialog(this, new SelectDeviceDialog.SelectResultListener() { + /** + * call back + * + * @param deviceInfos deviceInfos + * + */ + public void callBack(List deviceInfos) { + for (DeviceInfo deviceInfo : deviceInfos) { + Handle handleInfo = new Handle(MainAbilitySlice.this); // 连接信息 + Intent intent = new Intent(); + Operation operation = new Intent.OperationBuilder() + .withDeviceId(deviceInfo.getDeviceId()) + .withBundleName(getBundleName()) + .withAbilityName(MainAbility.class.getName()) + .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) + .build(); + intent.setOperation(operation); + startAbility(intent); + // 保存手柄连接信息 + boolean isConn = connectRemotePa(deviceInfo.getDeviceId(), 1, handleInfo); + handleInfo.setDeviceId(deviceInfo.getDeviceId()); + handleInfo.setConn(isConn); + handles.add(handleInfo); + } + } + }); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } + + private void startService() { + Intent intent = new Intent(); + Operation operation = new Intent.OperationBuilder() + .withDeviceId("") + .withBundleName(getBundleName()) + .withAbilityName(GameServiceAbility.class.getName()) + .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) + .build(); + intent.setOperation(operation); + startAbility(intent); + } + + private boolean connectRemotePa(String deviceId, int requestType, Handle handleInfo) { + Intent connectPaIntent = new Intent(); + Operation operation = new Intent.OperationBuilder() + .withDeviceId(deviceId) + .withBundleName(getBundleName()) + .withAbilityName(GameServiceAbility.class.getName()) + .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) + .build(); + connectPaIntent.setOperation(operation); + + IAbilityConnection conn = new IAbilityConnection() { + @Override + public void onAbilityConnectDone(ElementName elementName, IRemoteObject remote, int resultCode) { + GameRemoteProxy proxy = new GameRemoteProxy(remote); + handleInfo.setProxy(proxy); + } + + @Override + public void onAbilityDisconnectDone(ElementName elementName, int i) { + if (handleInfo.getProxy() != null) { + handleInfo.setProxy(null); + } + } + }; + + boolean ret = connectAbility(connectPaIntent, conn); + return ret; + } + + /** + * return score to handle + * + * @param score score + * @param deviceId deviceId + * + */ + public static void returnScore(int score, String deviceId) { + for (Handle handleInfo: handles) { + try { + if (handleInfo.getDeviceId().equals(deviceId) && handleInfo.isConn() && handleInfo.getProxy() != null) { + handleInfo.getProxy().senDataToRemote(1, score); + break; + } + } catch (RemoteException e) { + HiLog.error(TAG, handleInfo.getDeviceId() + "::GameServiceAbility::returnScore faild"); + } + } + } + + /** + * game remote proxy + * + * @since 2021-03-15 + * + */ + public class GameRemoteProxy implements IRemoteBroker { + private static final int ERR_OK = 0; + private static final int REQUEST_START_ABILITY = 1; + private static final int REQUEST_SEND_DATA = 2; + private final IRemoteObject remote; + + GameRemoteProxy(IRemoteObject remote) { + this.remote = remote; + } + + @Override + public IRemoteObject asObject() { + return remote; + } + + private void senDataToRemote(int requestType, int score) throws RemoteException { + MessageParcel data = MessageParcel.obtain(); + MessageParcel reply = MessageParcel.obtain(); + try { + data.writeInt(score); + MessageOption option = new MessageOption(MessageOption.TF_SYNC); + remote.sendRequest(requestType, data, reply, option); + } catch (RemoteException e) { + HiLog.error(TAG, "GameRemoteProxy::senDataToRemote faild"); + } finally { + data.reclaim(); + reply.reclaim(); + } + } + } + + /** + * Obtains the ID of the connected device. + * + * @return deviceIds + * + */ + public static List getDeviceIds() { + List deviceIds = new ArrayList<>(handles.size()); + for (Handle handleInfo: handles) { + if (handleInfo.isConn() && handleInfo.getProxy() != null) { + deviceIds.add(handleInfo.getDeviceId()); + } + } + return deviceIds; + } + + // 获取连接设备信息 + public static List getHandles() { + return handles; + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/PlaneGameAbilitySlice.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/PlaneGameAbilitySlice.java new file mode 100644 index 00000000..a3a706dd --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/slice/PlaneGameAbilitySlice.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.slice; + +import com.huawei.codelab.ResourceTable; +import com.huawei.codelab.game.GameView; +import com.huawei.codelab.game.Handle; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +import java.util.List; + +/** + * plane game ability slice + * + * @since 2021-03-15 + * + */ +public class PlaneGameAbilitySlice extends AbilitySlice { + private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "fxh"); + private static GameView gameView; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_plane_game); + + Component component = findComponentById(ResourceTable.Id_canvasView); + if (component instanceof GameView) { + gameView = (GameView) component; // 获取页面 + } + setGameView(MainAbilitySlice.getHandles()); + gameView.start(MainAbilitySlice.getDeviceIds()); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } + + private void setGameView(List handles) { + for (Handle handle: handles) { + handle.setGameView(gameView); + } + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/Constants.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/Constants.java new file mode 100644 index 00000000..9cc4e93c --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/Constants.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.util; + +/** + * constants + * + * @since 2021-03-15 + * + */ +public class Constants { + /** + * 我的飞机尺寸 + * + * @since 2021-03-15 + * + */ + public static final int MY_PLANE_SIZE = 200; + /** + * 大敌机尺寸 + * + * @since 2021-03-15 + * + */ + public static final int BIG_PLANE_SIZE = 120; + /** + * 小敌机尺寸 + * + * @since 2021-03-15 + * + */ + public static final int SMALL_PLANE_SIZE = 100; + /** + * 奖励宽度 + * + * @since 2021-03-15 + * + */ + public static final int AWARD_WIDTH = 50; + /** + * 奖励高度 + * + * @since 2021-03-15 + * + */ + public static final int AWARD_HEIGHT = 100; + /** + * 子弹尺寸 + * + * @since 2021-03-15 + * + */ + public static final int BULLET_SIZE = 15; + /** + * 降落伞尺寸 + * + * @since 2021-03-15 + * + */ + public static final int BOOM_SIZE = 120; + /** + * 炸弹宽度 + * + * @since 2021-03-15 + * + */ + public static final int BOMB_WIDTH = 50; + /** + * 炸弹高度 + * + * @since 2021-03-15 + * + */ + public static final int BOMB_HEIGHT = 100; + + /** + * 游戏未开始 + * + * @since 2021-03-15 + * + */ + public static final int GAME_UNREADY = 0; + /** + * 游戏中 + * + * @since 2021-03-15 + * + */ + public static final int GAME_START = 1; + /** + * 游戏暂停 + * + * @since 2021-03-15 + * + */ + public static final int GAME_PAUSE = 2; + /** + * 游戏结束 + * + * @since 2021-03-15 + * + */ + public static final int GAME_STOP = 3; + + // 工具类隐藏构造函数 + private Constants() { + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/GameUtils.java b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/GameUtils.java new file mode 100644 index 00000000..783f9438 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/java/com/huawei/codelab/util/GameUtils.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.huawei.codelab.util; + +import ohos.agp.render.PixelMapHolder; +import ohos.agp.utils.Point; +import ohos.agp.window.service.Display; +import ohos.agp.window.service.DisplayManager; +import ohos.app.Context; +import ohos.global.resource.NotExistException; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; +import ohos.media.image.ImageSource; +import ohos.media.image.common.Size; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; + +/** + * game util + * + * @since 2021-03-15 + * + */ +public class GameUtils { + private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0xD001400, "screenUtils"); + private static Context context; + private static int screenHeight = 0; + private static int screenWidth = 0; + + // 工具类隐藏构造函数 + private GameUtils() { + } + + /** + * Initialization + * + * @param slice slice + */ + public static void setContext(Context slice) { + GameUtils.context = slice; + } + + /** + * Obtains the screen height. + * + * @return screenHeight + * + */ + public static int getScreenHeight() { + if (screenHeight != 0) { + return screenHeight; + } else { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + screenHeight = (int) point.position[1]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + screenHeight = (int) point.position[1]; + } + return screenHeight; + } + } + + /** + * Obtains the screen width. + * + * @return screenWidth + * + */ + public static int getScreenWidth() { + if (screenWidth != 0) { + return screenWidth; + } else { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + screenWidth = (int) point.position[0]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + screenWidth = (int) point.position[0]; + } + return screenWidth; + } + } + + /** + * Convert the image ID to a PixelMap. + * + * @param resId resId + * @param width width + * @param height height + * @return deviceIds + * + */ + public static PixelMapHolder transIdToPixelMapHolder(int resId, int width, int height) { + InputStream source = null; + ImageSource imageSource = null; + try { + source = context.getResourceManager().getResource(resId); + imageSource = ImageSource.create(source, null); + ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions(); + decodingOpts.desiredSize = new Size(width, height); + return new PixelMapHolder(imageSource.createPixelmap(decodingOpts)); + } catch (IOException | NotExistException e) { + HiLog.error(TAG, "getPixelMap error"); + } finally { + try { + source.close(); + } catch (IOException e) { + HiLog.error(TAG, "getPixelMap source close error"); + } + } + return new PixelMapHolder(null); + } +} diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/element/string.json b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..4a41e855 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/element/string.json @@ -0,0 +1,28 @@ +{ + "string": [ + { + "name": "app_name", + "value": "GameApplication" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "planegameability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "HelloWorld", + "value": "Hello World" + }, + { + "name": "gameserviceability_description", + "value": "hap sample empty service" + }, + { + "name": "gameoverability_description", + "value": "Java_Phone_Empty Feature Ability" + } + ] +} \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_game_over.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_game_over.xml new file mode 100644 index 00000000..44c5332b --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_game_over.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_main.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 00000000..c0c0a3df --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_plane_game.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_plane_game.xml new file mode 100644 index 00000000..a002c235 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_ability_plane_game.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_card.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_card.xml new file mode 100644 index 00000000..6e6be810 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_card.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_text_field.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_text_field.xml new file mode 100644 index 00000000..5bad7183 --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/background_text_field.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/button_element.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/button_element.xml new file mode 100644 index 00000000..96bb0fbc --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/graphic/button_element.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_game_over.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_game_over.xml new file mode 100644 index 00000000..5b1cd91f --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_game_over.xml @@ -0,0 +1,64 @@ + + + + + + + + + + \ No newline at end of file diff --git a/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_main.xml b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 00000000..a5ca08cd --- /dev/null +++ b/DistributionGamePad-master/GameApplication/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,23 @@ + + + +