diff --git a/AudioDemo/LICENSE b/AudioDemo/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..80576ef141485b36eea4aebf25af97020bc2de44
--- /dev/null
+++ b/AudioDemo/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/AudioDemo/README.md b/AudioDemo/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..fab531c09c7cbd2c4e2b24843555789217777ad5
--- /dev/null
+++ b/AudioDemo/README.md
@@ -0,0 +1,23 @@
+# AudioDemo
+
+简介 • 音频播放相关管理应用包括音频播放、声音采集和音频相关管理(快进、快退、暂停、播放、音量控制)等功能。
+
+安装要求 • 安装DevEco Studio • 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书
+
+用户指南 • 下载此项目 • 打开HUAWEI DevEco Studio,单击File> Open选择此AudioDemo • 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 • 单击Run> Run 'entry'以运行hap包
+
+注意 • 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。
+
+许可 请参阅LICENSE文件以获得更多信息。
+
+Introduction: Audio playback management applications include audio playback, audio capture, and audio management.
+
+Installation requirements • Install DevEco Studio • 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
+
+If you can directly access the Internet, just download the HarmonyOS SDK
+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 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/AudioDemo/RELEASE-NOTES.md b/AudioDemo/RELEASE-NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..ea23a13e3d4407d06cba3aa7155a23e5081b50b4
--- /dev/null
+++ b/AudioDemo/RELEASE-NOTES.md
@@ -0,0 +1,2 @@
+1.0.0
+1.Initial version
\ No newline at end of file
diff --git a/AudioDemo/build.gradle b/AudioDemo/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..b9012a0bc45264d55919d569d63d827a450ae549
--- /dev/null
+++ b/AudioDemo/build.gradle
@@ -0,0 +1,37 @@
+// 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 4
+ }
+}
+
+buildscript {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.huawei.ohos:hap:2.4.0.1'
+ classpath 'com.huawei.ohos:decctest:1.0.0.7'
+ }
+}
+
+allprojects {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+}
diff --git a/AudioDemo/entry/.gitignore b/AudioDemo/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..796b96d1c402326528b4ba3c12ee9d92d0e212e9
--- /dev/null
+++ b/AudioDemo/entry/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/AudioDemo/entry/build.gradle b/AudioDemo/entry/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..882341c674316a7ea63d617ccbc67585eab15b04
--- /dev/null
+++ b/AudioDemo/entry/build.gradle
@@ -0,0 +1,16 @@
+apply plugin: 'com.huawei.ohos.hap'
+apply plugin: 'com.huawei.ohos.decctest'
+ohos {
+ compileSdkVersion 4
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
+ testCompile'junit:junit:4.12'
+}
+decc {
+ supportType = ['html','xml']
+}
diff --git a/AudioDemo/entry/src/main/config.json b/AudioDemo/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..302e1f82ecde345aa277503b9f6dc56285f9c784
--- /dev/null
+++ b/AudioDemo/entry/src/main/config.json
@@ -0,0 +1,69 @@
+{
+ "app": {
+ "bundleName": "com.huawei.cookbook",
+ "vendor": "huawei",
+ "version": {
+ "code": 1,
+ "name": "1.0"
+ },
+ "apiVersion": {
+ "compatible": 4,
+ "target": 4
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.huawei.harmonyaudiodemo",
+ "name": ".MyApplication",
+ "deviceType": [
+ "default"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry",
+ "moduleType": "entry"
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home",
+ "action.sound.play.system",
+ "action.sound.play.music",
+ "action.sound.record",
+ "action.sound.volume"
+ ]
+ }
+ ],
+ "orientation": "unspecified",
+ "name": "com.huawei.harmonyaudiodemo.MainAbility",
+ "icon": "$media:icon",
+ "description": "$string:mainability_description",
+ "label": "HarmonyAudioDemo",
+ "type": "page",
+ "launchType": "standard"
+ }
+ ],
+ "reqPermissions": [
+ {
+ "name": "ohos.permission.MICROPHONE"
+ },
+ {
+ "name": "ohos.permission.WRITE_MEDIA"
+ },
+ {
+ "name": "ohos.permission.WRITE_USER_STORAGE"
+ },
+ {
+ "name": "ohos.permission.READ_USER_STORAGE"
+ },
+ {
+ "name": "ohos.permission.READ_MEDIA"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/element/color.json b/AudioDemo/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..d4e835bddf1c1ea9ceb11cd87238bd3021e92515
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,16 @@
+{
+ "color": [
+ {
+ "name": "red",
+ "value": "#FF0000"
+ },
+ {
+ "name": "blue",
+ "value": "#0000FF"
+ },
+ {
+ "name": "white",
+ "value": "#ffffff"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/element/string.json b/AudioDemo/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..bb076ba2d5a9f3a2987a43f259d17da119863aa6
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,12 @@
+{
+ "string":[
+ {
+ "name":"app_name",
+ "value":"HarmonyAudioDemo"
+ },
+ {
+ "name":"mainability_description",
+ "value":"Java_Phone_Empty Feature Ability"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/animation_record_play.xml b/AudioDemo/entry/src/main/resources/base/graphic/animation_record_play.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e90863d7699ce5a13cedaf94419f98e9c72b3f11
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/animation_record_play.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/background_ability_main.xml b/AudioDemo/entry/src/main/resources/base/graphic/background_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..47a2d3e00aea59206e521f2e2c2491c629528df9
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/background_ability_main.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/background_record_progress.xml b/AudioDemo/entry/src/main/resources/base/graphic/background_record_progress.xml
new file mode 100644
index 0000000000000000000000000000000000000000..98942569f9cc93e902efc047a6fe9c3fd9b56c0b
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/background_record_progress.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/button_normal_ability_main.xml b/AudioDemo/entry/src/main/resources/base/graphic/button_normal_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..72106aa48fd77c9124c3cc99126627d562cbeada
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/button_normal_ability_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml b/AudioDemo/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a29a1da66db5c0c9f5e67bfcd580f61267d4b59f
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/button_record_normal.xml b/AudioDemo/entry/src/main/resources/base/graphic/button_record_normal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..82fa87c355a32b377dde3298dbd713c9c7bebbd3
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/button_record_normal.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/button_record_pressed.xml b/AudioDemo/entry/src/main/resources/base/graphic/button_record_pressed.xml
new file mode 100644
index 0000000000000000000000000000000000000000..884334598914ae48bf533db9f931bd677a84a8c3
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/button_record_pressed.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/corner_yellow_bg.xml b/AudioDemo/entry/src/main/resources/base/graphic/corner_yellow_bg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bbecb50641c449f4d12f079d06888d614031415
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/corner_yellow_bg.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/gray_thumb.xml b/AudioDemo/entry/src/main/resources/base/graphic/gray_thumb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d417a8323687bfb6403316072e2ac50b0a0befcd
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/gray_thumb.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/gray_track.xml b/AudioDemo/entry/src/main/resources/base/graphic/gray_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2235f61227ed99cbe9dd13b183d8d3eb257c2ec2
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/gray_track.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/green_thumb.xml b/AudioDemo/entry/src/main/resources/base/graphic/green_thumb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f1d6074ab039aefb1826442ccf765b9963e8f12a
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/green_thumb.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/green_track.xml b/AudioDemo/entry/src/main/resources/base/graphic/green_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4854f4e01f75d959d381e8ccbd739932a8f31473
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/green_track.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/selector_ability_main.xml b/AudioDemo/entry/src/main/resources/base/graphic/selector_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..603ed1fbca321ba08d2f00aa83089b9cfc79ea1f
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/selector_ability_main.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/selector_button_record.xml b/AudioDemo/entry/src/main/resources/base/graphic/selector_button_record.xml
new file mode 100644
index 0000000000000000000000000000000000000000..120009d0731bcb3d372cf62ed24b4d1492076086
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/selector_button_record.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/thumb.xml b/AudioDemo/entry/src/main/resources/base/graphic/thumb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1c42512863fc7196a8f326be27b340bac03784f1
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/thumb.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/graphic/track.xml b/AudioDemo/entry/src/main/resources/base/graphic/track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ecb569ed0ad2ca43aafd7a7157301ee3e8d29829
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/graphic/track.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/layout/ability_main.xml b/AudioDemo/entry/src/main/resources/base/layout/ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fde80782cbce9ad596f34b753e76df0254bd06ac
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/ability_main.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/layout/ability_music_player.xml b/AudioDemo/entry/src/main/resources/base/layout/ability_music_player.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7635847bdb9e081c590996af882931e0866c4e03
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/ability_music_player.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/AudioDemo/entry/src/main/resources/base/layout/media_sound_audio.xml b/AudioDemo/entry/src/main/resources/base/layout/media_sound_audio.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f6554fe28ff3a8cec34910dcfa6796d4f9f2de0c
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/media_sound_audio.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/layout/media_sound_tone.xml b/AudioDemo/entry/src/main/resources/base/layout/media_sound_tone.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e7a2ce2fd4b496196d0a9b34c76126acb6b2825a
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/media_sound_tone.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AudioDemo/entry/src/main/resources/base/layout/media_sound_volume.xml b/AudioDemo/entry/src/main/resources/base/layout/media_sound_volume.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1903c0a885f553542594fb372076c7935b751ddc
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/media_sound_volume.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/layout/player_loading_layout.xml b/AudioDemo/entry/src/main/resources/base/layout/player_loading_layout.xml
new file mode 100644
index 0000000000000000000000000000000000000000..498983f3b231656b23c998c91707e1882e589155
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/player_loading_layout.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
diff --git a/AudioDemo/entry/src/main/resources/base/layout/record_play_button.xml b/AudioDemo/entry/src/main/resources/base/layout/record_play_button.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aaa6a3101a014fffcd10dbf467e5ffdc0e50d9b4
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/record_play_button.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/layout/simple_player_controller_layout.xml b/AudioDemo/entry/src/main/resources/base/layout/simple_player_controller_layout.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fc1eba5c769804abc0e7b9136591a1053b967bfa
--- /dev/null
+++ b/AudioDemo/entry/src/main/resources/base/layout/simple_player_controller_layout.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioDemo/entry/src/main/resources/base/media/bg_music_player.jpg b/AudioDemo/entry/src/main/resources/base/media/bg_music_player.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..518eaacaffa7ab7e57acd179df0286e3607fcd0a
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/bg_music_player.jpg differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_back.png b/AudioDemo/entry/src/main/resources/base/media/ic_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..392306cdb9171897c6ca7fec1216b6fa7099c2d0
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_back.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_backward.png b/AudioDemo/entry/src/main/resources/base/media/ic_backward.png
new file mode 100644
index 0000000000000000000000000000000000000000..2696217ec5156e83b88adf46d87d4c5bfd328075
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_backward.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_forward.png b/AudioDemo/entry/src/main/resources/base/media/ic_forward.png
new file mode 100644
index 0000000000000000000000000000000000000000..b52b99f1c209870d3c4a9b083b767eac2209bec8
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_forward.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_horns.png b/AudioDemo/entry/src/main/resources/base/media/ic_horns.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f7bd807998c984a55e5972240fdcb44cfdc96b9
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_horns.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_loading.png b/AudioDemo/entry/src/main/resources/base/media/ic_loading.png
new file mode 100644
index 0000000000000000000000000000000000000000..8803fa85f47eacd897aff7d72952ef7bbb932a63
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_loading.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_music_play.png b/AudioDemo/entry/src/main/resources/base/media/ic_music_play.png
new file mode 100644
index 0000000000000000000000000000000000000000..818369b1f29c3451ff7616ba3ca12c8fc2c2cfe4
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_music_play.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_music_stop.png b/AudioDemo/entry/src/main/resources/base/media/ic_music_stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..211e4757a0aa24bc9256fca076d7d998b60e10dd
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_music_stop.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_record_play1.png b/AudioDemo/entry/src/main/resources/base/media/ic_record_play1.png
new file mode 100644
index 0000000000000000000000000000000000000000..b31ed7d873c1f8d6ed2a29929365a6cc576ca67b
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_record_play1.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_record_play2.png b/AudioDemo/entry/src/main/resources/base/media/ic_record_play2.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9ce54e44ba0fc5c0280967570f97f9751934319
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_record_play2.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_record_play3.png b/AudioDemo/entry/src/main/resources/base/media/ic_record_play3.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e58bdbc62aa63c649ce735ac957195d147a5015
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_record_play3.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_recorder.png b/AudioDemo/entry/src/main/resources/base/media/ic_recorder.png
new file mode 100644
index 0000000000000000000000000000000000000000..8f247901c719a83fb202ea8ca7890e94cfa2e75d
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_recorder.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/ic_update.png b/AudioDemo/entry/src/main/resources/base/media/ic_update.png
new file mode 100644
index 0000000000000000000000000000000000000000..1b63a318d863b5b236da9c83f616334b702dde82
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/ic_update.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/icon.png b/AudioDemo/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/icon.png differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/test.aac b/AudioDemo/entry/src/main/resources/base/media/test.aac
new file mode 100644
index 0000000000000000000000000000000000000000..22871a8d45b4db3f4ebf8a75ffb91184d940f4d5
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/test.aac differ
diff --git a/AudioDemo/entry/src/main/resources/base/media/test.m4a b/AudioDemo/entry/src/main/resources/base/media/test.m4a
new file mode 100644
index 0000000000000000000000000000000000000000..dafd82086a78dffb98f4221e66b3535ca3764272
Binary files /dev/null and b/AudioDemo/entry/src/main/resources/base/media/test.m4a differ
diff --git a/AudioDemo/entry/src/ohosTest/config.json b/AudioDemo/entry/src/ohosTest/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..20e47eb2717894191bc2b46da933c609cab80366
--- /dev/null
+++ b/AudioDemo/entry/src/ohosTest/config.json
@@ -0,0 +1,38 @@
+{
+ "app": {
+ "bundleName": "com.huawei.harmonyaudiodemo",
+ "vendor": "huawei",
+ "version": {
+ "code": 1,
+ "name": "1.0"
+ },
+ "apiVersion": {
+ "compatible": 4,
+ "target": 4,
+ "releaseType": "Beta1"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.huawei.harmonyaudiodemo",
+ "name": "testModule",
+ "deviceType": ["phone"],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry_test",
+ "moduleType": "feature"
+ },
+ "abilities":[
+ {
+ "name": "decc.testkit.runner.EntryAbility",
+ "description": "Test Entry Ability",
+ "icon": "$media:icon",
+ "label": "TestAbility",
+ "launchType": "standard",
+ "orientation": "landscape",
+ "visible": true,
+ "type": "page"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/AudioDemo/entry/src/ohosTest/java/com/huawei/harmonyaudiodemo/ExampleOhosTest.java b/AudioDemo/entry/src/ohosTest/java/com/huawei/harmonyaudiodemo/ExampleOhosTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7585fdedb9d870fd4cf6d8847ef0886a5483cfb4
--- /dev/null
+++ b/AudioDemo/entry/src/ohosTest/java/com/huawei/harmonyaudiodemo/ExampleOhosTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-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.harmonyaudiodemo;
+
+import static org.junit.Assert.assertEquals;
+
+import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
+
+import org.junit.Test;
+
+/**
+ * ExampleOhosTest
+ *
+ * @since 2020-12-04
+ *
+ */
+public class ExampleOhosTest {
+ /**
+ * testBundleName
+ *
+ */
+ @Test
+ public void testBundleName() {
+ final String actualBundleName = AbilityDelegatorRegistry.getArguments().getTestBundleName();
+ assertEquals("com.huawei.harmonyaudiodemo", actualBundleName);
+ }
+}
diff --git a/AudioDemo/entry/src/test/java/com/huawei/harmonyaudiodemo/ExampleTest.java b/AudioDemo/entry/src/test/java/com/huawei/harmonyaudiodemo/ExampleTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f1e3c8cd64e7f3afb55efd9a5fb29cd36ee88a3
--- /dev/null
+++ b/AudioDemo/entry/src/test/java/com/huawei/harmonyaudiodemo/ExampleTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-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.harmonyaudiodemo;
+
+import org.junit.Test;
+
+/**
+ * ExampleTest
+ *
+ * @since 2020-12-04
+ *
+ */
+public class ExampleTest {
+ /**
+ * onStart
+ *
+ */
+ @Test
+ public void onStart() {
+ }
+}
diff --git a/AudioDemo/gradle/wrapper/gradle-wrapper.jar b/AudioDemo/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9
Binary files /dev/null and b/AudioDemo/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/AudioDemo/gradle/wrapper/gradle-wrapper.properties b/AudioDemo/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6623300bebd011bc5f7991f4f9c389e2f67b14ac
--- /dev/null
+++ b/AudioDemo/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/AudioDemo/settings.gradle b/AudioDemo/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..4773db73233a570c2d0c01a22e75321acfbf7a07
--- /dev/null
+++ b/AudioDemo/settings.gradle
@@ -0,0 +1 @@
+include ':entry'
diff --git a/DistributedMapDemo/LICENSE b/DistributedMapDemo/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..eb44b24a0ff113ed4b008408a3406f792bde2adb
--- /dev/null
+++ b/DistributedMapDemo/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/DistributedMapDemo/README.md b/DistributedMapDemo/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2c4239a087ee7fb685f11650138a2bb721497de8
--- /dev/null
+++ b/DistributedMapDemo/README.md
@@ -0,0 +1,24 @@
+DistributedMapDemo
+
+What is it? The DistributedMapDemo application is to show the simple HarmonyOS Distributed capability. You can simulate navigation through the app. This sample code has been completed for the flow of navigation data between your phone, smart wearable, and tablet. You can work with us from the beginning. This example code is complete and you can learn from the beginning with us.
+
+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
+
+If you can directly access the Internet, just download the HarmonyOS SDK
+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 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.
+
+
+简介 • 本篇Codelab旨在展示简单的HarmonyOS分布式功能。您可以通过应用程序模拟导航,在手机、智能穿戴和平板电脑之间进行导航数据流转。
+
+安装要求 • 安装DevEco Studio • 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书
+
+用户指南 • 下载此项目 • 打开HUAWEI DevEco Studio,单击File> Open选择此DistributedMapDemo • 单击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/DistributedMapDemo/RELEASE-NOTES.md b/DistributedMapDemo/RELEASE-NOTES.md
new file mode 100644
index 0000000000000000000000000000000000000000..ea23a13e3d4407d06cba3aa7155a23e5081b50b4
--- /dev/null
+++ b/DistributedMapDemo/RELEASE-NOTES.md
@@ -0,0 +1,2 @@
+1.0.0
+1.Initial version
\ No newline at end of file
diff --git a/DistributedMapDemo/build.gradle b/DistributedMapDemo/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..cee07328749cf41637db2e71b7fbf43f6bde41e4
--- /dev/null
+++ b/DistributedMapDemo/build.gradle
@@ -0,0 +1,37 @@
+// 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://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.huawei.ohos:hap:2.4.2.7'
+ classpath 'com.huawei.ohos:decctest:1.0.0.7'
+ }
+}
+
+allprojects {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+}
diff --git a/DistributedMapDemo/entry/build.gradle b/DistributedMapDemo/entry/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..266a8abbcb70bb85ffaa039ececa4e23ae4251dc
--- /dev/null
+++ b/DistributedMapDemo/entry/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'com.huawei.ohos.hap'
+ohos {
+ compileSdkVersion 5
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
+ implementation 'com.google.code.gson:gson:2.8.0'
+}
diff --git a/DistributedMapDemo/entry/src/main/config.json b/DistributedMapDemo/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..ff4d1e23cef45f0bcadb22215ce242a9bb066c5a
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/config.json
@@ -0,0 +1,102 @@
+{
+ "app": {
+ "bundleName": "com.huawei.codelab",
+ "vendor": "huawei",
+ "version": {
+ "code": 1,
+ "name": "1.0"
+ },
+ "apiVersion": {
+ "compatible": 4,
+ "target": 5,
+ "releaseType": "Release"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "com.huawei.codelab",
+ "name": ".MyApplication",
+ "deviceType": [
+ "phone",
+ "tablet",
+ "wearable"
+ ],
+ "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": "DistributedMapDemo",
+ "type": "page",
+ "launchType": "standard"
+ },
+ {
+ "name": "com.huawei.codelab.WatchService",
+ "icon": "$media:icon",
+ "description": "$string:watchservice_description",
+ "type": "service"
+ },
+ {
+ "orientation": "portrait",
+ "name": "com.huawei.codelab.WatchAbility",
+ "icon": "$media:icon",
+ "description": "$string:watchmainability_description",
+ "label": "entry",
+ "type": "page",
+ "launchType": "standard"
+ }
+ ],
+ "reqPermissions": [
+ {
+ "reason": "distributed permission request",
+ "name": "ohos.permission.DISTRIBUTED_DATASYNC",
+ "usedScene": {
+ "ability": [
+ "com.huawei.codelab.MainAbility",
+ "com.huawei.codelab.WatchAbility"
+ ],
+ "when": "always"
+ }
+ },
+ {
+ "reason": "get Local Location",
+ "name": "ohos.permission.LOCATION",
+ "usedScene": {
+ "ability": [
+ "com.huawei.codelab.MainAbility",
+ "com.huawei.codelab.WatchAbility"
+ ],
+ "when": "always"
+ }
+ },
+ {
+ "name": "ohos.permission.INTERNET"
+ },
+ {
+ "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
+ },
+ {
+ "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
+ },
+ {
+ "name": "ohos.permission.GET_BUNDLE_INFO"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl b/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl
new file mode 100644
index 0000000000000000000000000000000000000000..e05490a838afef967df2d4db7bfcf15594cec21f
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+// IMapIdlInterface.idl
+
+// Declare any non-default types here with sequenceable or interface statements
+interface com.huawei.codelab.IMapIdlInterface {
+
+ void action([in] String actionType,[in] String actionContent);
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..66a68ab53e4e4bdc0d8d96c9706fd2964643514b
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java
@@ -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.
+ */
+
+package com.huawei.codelab;
+
+import com.huawei.codelab.slice.MainAbilitySlice;
+import com.huawei.codelab.util.LogUtils;
+import com.huawei.codelab.util.PermissionsUtils;
+
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.ability.IAbilityContinuation;
+import ohos.aafwk.content.Intent;
+import ohos.aafwk.content.IntentParams;
+import ohos.security.SystemPermission;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-03-12
+ */
+public class MainAbility extends Ability implements IAbilityContinuation {
+ private static final String TAG = MainAbility.class.getSimpleName();
+
+ private String[] requestPermissions = {SystemPermission.DISTRIBUTED_DATASYNC, SystemPermission.LOCATION};
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(MainAbilitySlice.class.getName());
+ PermissionsUtils.getInstance().requestPermissions(this, requestPermissions);
+ }
+
+ @Override
+ public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
+ PermissionsUtils.getInstance().onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+
+ @Override
+ public boolean onStartContinuation() {
+ LogUtils.info(TAG, "onStartContinuation");
+ return true;
+ }
+
+ @Override
+ public boolean onSaveData(IntentParams intentParams) {
+ LogUtils.info(TAG, "onSaveData");
+ return true;
+ }
+
+ @Override
+ public boolean onRestoreData(IntentParams intentParams) {
+ LogUtils.info(TAG, "onRestoreData");
+ return true;
+ }
+
+ @Override
+ public void onCompleteContinuation(int position) {
+ LogUtils.info(TAG, "onCompleteContinuation");
+ }
+
+ @Override
+ public void onRemoteTerminated() {
+ LogUtils.info(TAG, "onRemoteTerminated");
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd9057697ee2324b9a696b15391cc5478571b537
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab;
+
+import ohos.aafwk.ability.AbilityPackage;
+
+/**
+ * MyApplication
+ *
+ * @since 2021-03-12
+ */
+public class MyApplication extends AbilityPackage {
+ @Override
+ public void onInitialize() {
+ super.onInitialize();
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..9831ac017976f6a8f4278902b5bd915a118a4803
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab;
+
+import com.huawei.codelab.slice.WatchAbilitySlice;
+
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+import ohos.agp.utils.Color;
+import ohos.agp.window.service.WindowManager;
+
+/**
+ * WatchAbility
+ *
+ * @since 2021-03-12
+ */
+public class WatchAbility extends Ability {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(WatchAbilitySlice.class.getName());
+ WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.BLACK.getValue());
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java
new file mode 100644
index 0000000000000000000000000000000000000000..d2232e3f3288ad2176b7e11547cced7237eb0f32
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab;
+
+import com.huawei.codelab.util.LogUtils;
+
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+import ohos.aafwk.content.Operation;
+import ohos.event.commonevent.CommonEventData;
+import ohos.event.commonevent.CommonEventManager;
+import ohos.rpc.IRemoteObject;
+import ohos.rpc.RemoteException;
+
+/**
+ * WatchService
+ *
+ * @since 2021-03-12
+ */
+public class WatchService extends Ability {
+ private static final String TAG = WatchService.class.getSimpleName();
+
+ private WatchRemote watchRemote = new WatchRemote("WatchRemote");
+
+ @Override
+ public void onStart(Intent intent) {
+ LogUtils.info(TAG, "WatchService::onStart");
+ super.onStart(intent);
+ }
+
+ @Override
+ public void onBackground() {
+ super.onBackground();
+ LogUtils.info(TAG, "WatchService::onBackground");
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ LogUtils.info(TAG, "WatchService::onStop");
+ }
+
+ @Override
+ public void onCommand(Intent intent, boolean isRestart, int startId) {
+ }
+
+ @Override
+ public IRemoteObject onConnect(Intent intent) {
+ return watchRemote.asObject();
+ }
+
+ @Override
+ public void onDisconnect(Intent intent) {
+ }
+
+ /**
+ * WatchRemote
+ *
+ * @since 2021-03-12
+ */
+ public class WatchRemote extends MapIdlInterfaceStub {
+ private WatchRemote(String descriptor) {
+ super(descriptor);
+ }
+
+ @Override
+ public void action(String actionType, String actionContent) throws RemoteException {
+ LogUtils.info(TAG, "WatchService::action");
+ sendEvent(actionType, actionContent);
+ }
+ }
+
+ private void sendEvent(String actionType, String actionContent) {
+ LogUtils.info(TAG, "WatchService::sendEvent");
+ try {
+ Intent intent = new Intent();
+ Operation operation = new Intent.OperationBuilder().withAction("com.huawei.map").build();
+ intent.setOperation(operation);
+ intent.setParam("actionType", actionType);
+ intent.setParam("actionContent", actionContent);
+ CommonEventData eventData = new CommonEventData(intent);
+ CommonEventManager.publishCommonEvent(eventData);
+ } catch (RemoteException e) {
+ LogUtils.info(TAG, "publishCommonEvent occur exception.");
+ }
+ }
+}
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0410a333058ae1cc10328844a7f7b915ed31623
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.bean;
+
+import java.util.List;
+
+/**
+ * InputTipsResult
+ *
+ * @since 2021-03-12
+ */
+public class InputTipsResult {
+ private String count;
+
+ private String infocode;
+
+ private List tips;
+
+ private String status;
+
+ private String info;
+
+ public void setCount(String count) {
+ this.count = count;
+ }
+
+ public void setInfocode(String infocode) {
+ this.infocode = infocode;
+ }
+
+ public void setTips(List tips) {
+ this.tips = tips;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void setInfo(String info) {
+ this.info = info;
+ }
+
+ public String getCount() {
+ return count;
+ }
+
+ public String getInfocode() {
+ return infocode;
+ }
+
+ public List getTips() {
+ return tips;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * TipsEntity
+ *
+ * @param type
+ * @since 2021-03-12
+ */
+ public class TipsEntity {
+ private String typecode;
+
+ private E address;
+
+ private E adcode;
+
+ private List> city;
+
+ private E district;
+
+ private String name;
+
+ private String location;
+
+ private E id;
+
+ public void setTypecode(String typecode) {
+ this.typecode = typecode;
+ }
+
+ public void setAddress(E address) {
+ this.address = address;
+ }
+
+ public void setAdcode(E adcode) {
+ this.adcode = adcode;
+ }
+
+ public void setCity(List> city) {
+ this.city = city;
+ }
+
+ public void setDistrict(E district) {
+ this.district = district;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public void setId(E id) {
+ this.id = id;
+ }
+
+ public String getTypecode() {
+ return typecode;
+ }
+
+ public E getAddress() {
+ return address;
+ }
+
+ public E getAdcode() {
+ return adcode;
+ }
+
+ public List> getCity() {
+ return city;
+ }
+
+ public E getDistrict() {
+ return district;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public E getId() {
+ return id;
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d90d82939743f95c3ebbed1ef6fbcd0876a6988
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java
@@ -0,0 +1,304 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.bean;
+
+import java.util.List;
+
+/**
+ * RegionDetailResult
+ *
+ * @since 2021-03-12
+ */
+public class RegionDetailResult {
+ private String infocode;
+
+ private RegeocodeEntity regeocode;
+
+ private String status;
+
+ private String info;
+
+ public void setInfocode(String infocode) {
+ this.infocode = infocode;
+ }
+
+ public void setRegeocode(RegeocodeEntity regeocode) {
+ this.regeocode = regeocode;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void setInfo(String info) {
+ this.info = info;
+ }
+
+ public String getInfocode() {
+ return infocode;
+ }
+
+ public RegeocodeEntity getRegeocode() {
+ return regeocode;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * RegeocodeEntity
+ *
+ * @since 2021-03-12
+ */
+ public class RegeocodeEntity {
+ private String formattedAddress;
+
+ private AddressComponentEntity addressComponent;
+
+ public void setFormattedAddress(String formattedAddress) {
+ this.formattedAddress = formattedAddress;
+ }
+
+ public void setAddressComponent(AddressComponentEntity addressComponent) {
+ this.addressComponent = addressComponent;
+ }
+
+ public String getFormattedAddress() {
+ return formattedAddress;
+ }
+
+ public AddressComponentEntity getAddressComponent() {
+ return addressComponent;
+ }
+
+ /**
+ * AddressComponentEntity
+ *
+ * @since 2021-03-12
+ */
+ public class AddressComponentEntity {
+ private List> businessAreas;
+
+ private String country;
+
+ private String province;
+
+ private String citycode;
+
+ private String city;
+
+ private String adcode;
+
+ private StreetNumberEntity streetNumber;
+
+ private String towncode;
+
+ private String district;
+
+ private BuildingEntity neighborhood;
+
+ private String township;
+
+ private BuildingEntity building;
+
+ public void setBusinessAreas(List> businessAreas) {
+ this.businessAreas = businessAreas;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public void setProvince(String province) {
+ this.province = province;
+ }
+
+ public void setCitycode(String citycode) {
+ this.citycode = citycode;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public void setAdcode(String adcode) {
+ this.adcode = adcode;
+ }
+
+ public void setStreetNumber(StreetNumberEntity streetNumber) {
+ this.streetNumber = streetNumber;
+ }
+
+ public void setTowncode(String towncode) {
+ this.towncode = towncode;
+ }
+
+ public void setDistrict(String district) {
+ this.district = district;
+ }
+
+ public void setNeighborhood(BuildingEntity neighborhood) {
+ this.neighborhood = neighborhood;
+ }
+
+ public void setTownship(String township) {
+ this.township = township;
+ }
+
+ public void setBuilding(BuildingEntity building) {
+ this.building = building;
+ }
+
+ public List> getBusinessAreas() {
+ return businessAreas;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public String getProvince() {
+ return province;
+ }
+
+ public String getCitycode() {
+ return citycode;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public String getAdcode() {
+ return adcode;
+ }
+
+ public StreetNumberEntity getStreetNumber() {
+ return streetNumber;
+ }
+
+ public String getTowncode() {
+ return towncode;
+ }
+
+ public String getDistrict() {
+ return district;
+ }
+
+ public BuildingEntity getNeighborhood() {
+ return neighborhood;
+ }
+
+ public String getTownship() {
+ return township;
+ }
+
+ public BuildingEntity getBuilding() {
+ return building;
+ }
+
+ /**
+ * StreetNumberEntity
+ *
+ * @since 2021-03-12
+ */
+ public class StreetNumberEntity {
+ private String number;
+
+ private String distance;
+
+ private String street;
+
+ private String location;
+
+ private String direction;
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+
+ public void setDistance(String distance) {
+ this.distance = distance;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public void setDirection(String direction) {
+ this.direction = direction;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public String getDistance() {
+ return distance;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public String getDirection() {
+ return direction;
+ }
+ }
+
+ /**
+ * BuildingEntity
+ *
+ * @since 2021-03-12
+ */
+ public class BuildingEntity {
+ private List> name;
+
+ private List> type;
+
+ public void setName(List> name) {
+ this.name = name;
+ }
+
+ public void setType(List> type) {
+ this.type = type;
+ }
+
+ public List> getName() {
+ return name;
+ }
+
+ public List> getType() {
+ return type;
+ }
+ }
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..645c9ec3f93f41c20800c304a422f1b57f3b893c
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.bean;
+
+import java.util.List;
+
+/**
+ * RouteResult
+ *
+ * @since 2021-03-12
+ */
+public class RouteResult {
+ private RouteEntity route;
+
+ private String count;
+
+ private String infocode;
+
+ private String status;
+
+ private String info;
+
+ public void setRoute(RouteEntity route) {
+ this.route = route;
+ }
+
+ public void setCount(String count) {
+ this.count = count;
+ }
+
+ public void setInfocode(String infocode) {
+ this.infocode = infocode;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void setInfo(String info) {
+ this.info = info;
+ }
+
+ public RouteEntity getRoute() {
+ return route;
+ }
+
+ public String getCount() {
+ return count;
+ }
+
+ public String getInfocode() {
+ return infocode;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * RouteEntity
+ *
+ * @since 2021-03-12
+ */
+ public class RouteEntity {
+ private List paths;
+
+ private String origin;
+
+ private String destination;
+
+ private String taxiCost;
+
+ public void setPaths(List paths) {
+ this.paths = paths;
+ }
+
+ public void setOrigin(String origin) {
+ this.origin = origin;
+ }
+
+ public void setDestination(String destination) {
+ this.destination = destination;
+ }
+
+ public void setTaxiCost(String taxiCost) {
+ this.taxiCost = taxiCost;
+ }
+
+ public List getPaths() {
+ return paths;
+ }
+
+ public String getOrigin() {
+ return origin;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public String getTaxiCost() {
+ return taxiCost;
+ }
+
+ /**
+ * PathsEntity
+ *
+ * @since 2021-03-12
+ */
+ public class PathsEntity {
+ private String duration;
+
+ private String distance;
+
+ private String restriction;
+
+ private String tollDistance;
+
+ private String strategy;
+
+ private String trafficLights;
+
+ private List steps;
+
+ private String tolls;
+
+ public void setDuration(String duration) {
+ this.duration = duration;
+ }
+
+ public void setDistance(String distance) {
+ this.distance = distance;
+ }
+
+ public void setRestriction(String restriction) {
+ this.restriction = restriction;
+ }
+
+ public void setTollDistance(String tollDistance) {
+ this.tollDistance = tollDistance;
+ }
+
+ public void setStrategy(String strategy) {
+ this.strategy = strategy;
+ }
+
+ public void setTrafficLights(String trafficLights) {
+ this.trafficLights = trafficLights;
+ }
+
+ public void setSteps(List steps) {
+ this.steps = steps;
+ }
+
+ public void setTolls(String tolls) {
+ this.tolls = tolls;
+ }
+
+ public String getDuration() {
+ return duration;
+ }
+
+ public String getDistance() {
+ return distance;
+ }
+
+ public String getRestriction() {
+ return restriction;
+ }
+
+ public String getTollDistance() {
+ return tollDistance;
+ }
+
+ public String getStrategy() {
+ return strategy;
+ }
+
+ public String getTrafficLights() {
+ return trafficLights;
+ }
+
+ public List getSteps() {
+ return steps;
+ }
+
+ public String getTolls() {
+ return tolls;
+ }
+
+ /**
+ * StepsEntity
+ *
+ * @param type
+ * @since 2021-03-12
+ */
+ public class StepsEntity {
+ private String orientation;
+
+ private String distance;
+
+ private List cities;
+
+ private E tollRoad;
+
+ private String tollDistance;
+
+ private String tolls;
+
+ private String duration;
+
+ private E assistantAction;
+
+ private String road;
+
+ private String instruction;
+
+ private E action;
+
+ private String polyline;
+
+ private List tmcs;
+
+ public void setOrientation(String orientation) {
+ this.orientation = orientation;
+ }
+
+ public void setDistance(String distance) {
+ this.distance = distance;
+ }
+
+ public void setCities(List cities) {
+ this.cities = cities;
+ }
+
+ public void setTollRoad(E tollRoad) {
+ this.tollRoad = tollRoad;
+ }
+
+ public void setTollDistance(String tollDistance) {
+ this.tollDistance = tollDistance;
+ }
+
+ public void setTolls(String tolls) {
+ this.tolls = tolls;
+ }
+
+ public void setDuration(String duration) {
+ this.duration = duration;
+ }
+
+ public void setAssistantAction(E assistantAction) {
+ this.assistantAction = assistantAction;
+ }
+
+ public void setRoad(String road) {
+ this.road = road;
+ }
+
+ public void setInstruction(String instruction) {
+ this.instruction = instruction;
+ }
+
+ public void setAction(E action) {
+ this.action = action;
+ }
+
+ public void setPolyline(String polyline) {
+ this.polyline = polyline;
+ }
+
+ public void setTmcs(List tmcs) {
+ this.tmcs = tmcs;
+ }
+
+ public String getOrientation() {
+ return orientation;
+ }
+
+ public String getDistance() {
+ return distance;
+ }
+
+ public List getCities() {
+ return cities;
+ }
+
+ public E getTollRoad() {
+ return tollRoad;
+ }
+
+ public String getTollDistance() {
+ return tollDistance;
+ }
+
+ public String getTolls() {
+ return tolls;
+ }
+
+ public String getDuration() {
+ return duration;
+ }
+
+ public E getAssistantAction() {
+ return assistantAction;
+ }
+
+ public String getRoad() {
+ return road;
+ }
+
+ public String getInstruction() {
+ return instruction;
+ }
+
+ public E getAction() {
+ return action;
+ }
+
+ public String getPolyline() {
+ return polyline;
+ }
+
+ public List getTmcs() {
+ return tmcs;
+ }
+
+ /**
+ * CitiesEntity
+ *
+ * @since 2021-03-12
+ */
+ public class CitiesEntity {
+ private String citycode;
+
+ private String adcode;
+
+ private String name;
+
+ private List districts;
+
+ public void setCitycode(String citycode) {
+ this.citycode = citycode;
+ }
+
+ public void setAdcode(String adcode) {
+ this.adcode = adcode;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setDistricts(List districts) {
+ this.districts = districts;
+ }
+
+ public String getCitycode() {
+ return citycode;
+ }
+
+ public String getAdcode() {
+ return adcode;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List getDistricts() {
+ return districts;
+ }
+
+ /**
+ * DistrictsEntity
+ *
+ * @since 2021-03-12
+ */
+ public class DistrictsEntity {
+ private String adcode;
+
+ private String name;
+
+ public void setAdcode(String adcode) {
+ this.adcode = adcode;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAdcode() {
+ return adcode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+ }
+
+ /**
+ * TmcsEntity
+ *
+ * @since 2021-03-12
+ */
+ public class TmcsEntity {
+ private String distance;
+
+ private E lcode;
+
+ private String polyline;
+
+ private String status;
+
+ public void setDistance(String distance) {
+ this.distance = distance;
+ }
+
+ public void setLcode(E lcode) {
+ this.lcode = lcode;
+ }
+
+ public void setPolyline(String polyline) {
+ this.polyline = polyline;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getDistance() {
+ return distance;
+ }
+
+ public E getLcode() {
+ return lcode;
+ }
+
+ public String getPolyline() {
+ return polyline;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b345fc81d7c3be157e46f509f97c77d09a4425e
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+/**
+ * 地图导航常量封装
+ *
+ * @since 2021-03-12
+ */
+public class Const {
+ /**
+ * 接口的调用凭证,需要开发者自己申请
+ */
+ public static final String MAP_KAY = "";
+
+ /**
+ * 高德地图导航瓦片url
+ */
+ public static final String TILE_URL =
+ "https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=2&style=8&x=%d&y=%d&z=%d";
+
+ /**
+ * 高德地图输入提示api接口
+ */
+ public static final String INPUT_TIPS_URL =
+ "https://restapi.amap.com/v3/assistant/inputtips?keywords=%s&key=%s&location=%s&city=%s";
+
+ /**
+ * 高德地图路径导航api接口
+ */
+ public static final String ROUTE_URL =
+ "https://restapi.amap.com/v3/direction/driving?extensions=all&strategy=5&origin=%s&destination=%s&key=%s";
+
+ /**
+ * 高德地图逆地理编码api接口
+ */
+ public static final String REGION_DETAIL_URL = "https://restapi.amap.com/v3/geocode/regeo?location=%s&key=%s";
+
+ /**
+ * 导航开始标识
+ */
+ public static final String ROUTE_START = "route_start";
+
+ /**
+ * 导航结束标识
+ */
+ public static final String ROUTE_END = "route_end";
+
+ /**
+ * 当前位置标识
+ */
+ public static final String ROUTE_PEOPLE = "route_people";
+
+ /**
+ * 关闭WatchAbility标识
+ */
+ public static final String STOP_WATCH_ABILITY = "stop_watch_ability";
+
+ /**
+ * 右转标识
+ */
+ public static final String ROUTE_TURN_RIGHT = "右转";
+
+ /**
+ * 左转标识
+ */
+ public static final String ROUTE_TURN_LEFT = "左转";
+
+ /**
+ * 直行标识
+ */
+ public static final String ROUTE_STRAIGHT = "直行";
+
+ /**
+ * 向右前方行驶标识
+ */
+ public static final String ROUTE_RIGHT_STRAIGHT = "向右前方行驶";
+
+ /**
+ * 向左前方行驶标识
+ */
+ public static final String ROUTE_LEFT_STRAIGHT = "向左前方行驶";
+
+ private Const() {
+ }
+}
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3ae8541aa90e6c28bc27ad824486bc2f9c492a9
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.app.Context;
+import ohos.location.Location;
+import ohos.location.Locator;
+import ohos.location.LocatorCallback;
+import ohos.location.RequestParam;
+
+/**
+ * 获取本机位置信息实现类
+ *
+ * @since 2021-03-15
+ */
+public class LocationHelper {
+ private LocCallBack locCallBack;
+
+ private Context context;
+
+ /**
+ * 获取本机位置信息
+ *
+ * @param con Context con
+ * @param callBack LocCallBack callBack
+ */
+ public void getMyLocation(Context con, LocCallBack callBack) {
+ locCallBack = callBack;
+ context = con;
+ Locator locator = new Locator(context);
+ if (locator.isLocationSwitchOn()) {
+ RequestParam requestParam = new RequestParam(RequestParam.SCENE_NAVIGATION);
+ MyLocatorCallback locatorCallback = new MyLocatorCallback();
+ locator.requestOnce(requestParam, locatorCallback);
+ } else {
+ ToastDialog toastDialog = new ToastDialog(context);
+ toastDialog.setAutoClosable(false);
+ toastDialog.setContentText("请前往设置打开位置信息开关");
+ toastDialog.show();
+ }
+ }
+
+ /**
+ * 获取位置信息后的回调接口
+ *
+ * @since 2021-03-15
+ */
+ public interface LocCallBack {
+ /**
+ * locCallBack
+ *
+ * @param loc loc
+ */
+ void locCallBack(Location loc);
+ }
+
+ /**
+ * MyLocatorCallback
+ *
+ * @since 2021-03-12
+ */
+ private class MyLocatorCallback implements LocatorCallback {
+ @Override
+ public void onLocationReport(Location location) {
+ if (locCallBack != null) {
+ context.getUITaskDispatcher().asyncDispatch((Runnable) () -> locCallBack.locCallBack(location));
+ }
+ }
+
+ @Override
+ public void onStatusChanged(int type) {
+ }
+
+ @Override
+ public void onErrorReport(int type) {
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..481f563ac4eba70a7e0db21cc9e08a10ad6163f6
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import com.huawei.codelab.bean.InputTipsResult;
+import com.huawei.codelab.bean.RegionDetailResult;
+import com.huawei.codelab.bean.RouteResult;
+import com.huawei.codelab.util.GsonUtils;
+import com.huawei.codelab.util.HttpUtils;
+import com.huawei.codelab.util.LogUtils;
+import com.huawei.codelab.util.MapUtils;
+
+import ohos.agp.utils.Point;
+import ohos.app.Context;
+
+import java.util.List;
+
+/**
+ * 地图导航逻辑控制类
+ *
+ * @since 2021-03-29
+ */
+public class MapDataHelper {
+ private static final String TAG = MapDataHelper.class.getName();
+
+ private String location;
+
+ private NavMap navMap;
+
+ private Context context;
+
+ private DataCallBack dataCallBack;
+
+ private String localCityCode;
+
+ /**
+ * 构造方法
+ *
+ * @param navMap navMap
+ * @param context context
+ */
+ public MapDataHelper(NavMap navMap, Context context) {
+ this.navMap = navMap;
+ this.context = context;
+ }
+
+ /**
+ * 设置路径起点
+ *
+ * @param startLocation location
+ */
+ public void setLocation(String startLocation) {
+ location = startLocation;
+ }
+
+ public void setDataCallBack(DataCallBack dataCallBack) {
+ this.dataCallBack = dataCallBack;
+ }
+
+ /**
+ * 获取本机位置信息
+ */
+ public void getMyLocation() {
+ new LocationHelper().getMyLocation(context, loc -> {
+ double locLongitude = loc.getLongitude();
+ double locLatitude = loc.getLatitude();
+ location = locLongitude + "," + locLatitude;
+ if (navMap.getMapElements() == null) {
+ setMapCenter(locLongitude, locLatitude);
+ getRegionDetail();
+ }
+ });
+ }
+
+ /**
+ * 调用高德地图逆地理编码api,获取城市编码
+ */
+ private void getRegionDetail() {
+ String url = String.format(Const.REGION_DETAIL_URL, location, Const.MAP_KAY);
+ HttpUtils.getInstance(context).get(url, result -> {
+ RegionDetailResult regionDetailResult = GsonUtils.jsonToBean(result, RegionDetailResult.class);
+ localCityCode = regionDetailResult.getRegeocode().getAddressComponent().getCitycode();
+ });
+ }
+
+ /**
+ * 调用高德地图输入提示api
+ *
+ * @param keyWords input content
+ */
+ public void getInputTips(String keyWords) {
+ String url = String.format(Const.INPUT_TIPS_URL, keyWords, Const.MAP_KAY, location, localCityCode);
+ HttpUtils.getInstance(context).get(url, result -> {
+ InputTipsResult inputTipsResult = GsonUtils.jsonToBean(result, InputTipsResult.class);
+ if (inputTipsResult == null) {
+ return;
+ }
+ dataCallBack.setInputTipsView(inputTipsResult.getTips());
+ LogUtils.info(TAG, "localCityCode:" + localCityCode);
+ });
+ }
+
+ /**
+ * 调用高德地图路径规划api
+ *
+ * @param endLocation 终点路径
+ */
+ public void getRouteResult(String endLocation) {
+ String url = String.format(Const.ROUTE_URL, location, endLocation, Const.MAP_KAY);
+ HttpUtils.getInstance(context).get(url, result -> dataCallBack.setRouteView(result));
+ }
+
+ /**
+ * 解析高德地图路径规划api返回的结果,获取导航路径元素集合,并将此集合添加到NavMap对象
+ *
+ * @param result 高德地图路径规划api返回的结果
+ */
+ public void parseRoute(String result) {
+ navMap.getMapElements().clear();
+ RouteResult routeResult = GsonUtils.jsonToBean(result, RouteResult.class);
+ List paths = routeResult.getRoute().getPaths();
+ RouteResult.RouteEntity.PathsEntity pathsEntity = paths.get(0);
+ List steps = pathsEntity.getSteps();
+ for (int i = 0; i < steps.size(); i++) {
+ RouteResult.RouteEntity.PathsEntity.StepsEntity stepsEntity = steps.get(i);
+ Object action = stepsEntity.getAction();
+ String instruction = stepsEntity.getInstruction();
+ String polyLine = stepsEntity.getPolyline();
+ String[] points = polyLine.split(";");
+ for (int j = 0; j < points.length; j++) {
+ String[] pointCoordinates = points[j].split(",");
+ double[] coordinates = MapUtils.lonLat2Mercator(Double.parseDouble(pointCoordinates[0]),
+ Double.parseDouble(pointCoordinates[1]));
+
+ if (i == 0 && j == 0) {
+ // 添加定位图标元素
+ addElementToMap(coordinates, Const.ROUTE_PEOPLE, "", true);
+
+ // 添加起点位置元素
+ addElementToMap(coordinates, Const.ROUTE_START, "", true);
+ }
+
+ if (j == 0) {
+ // 添加每一个step第一个元素,用于显示导航时提示信息
+ addElementToMap(coordinates, action.toString(), action.toString(), false);
+ } else {
+ addElementToMap(coordinates, action.toString(), instruction, false);
+ }
+
+ // 添加终点位置元素
+ if (i == steps.size() - 1 && j == points.length - 1) {
+ addElementToMap(coordinates, Const.ROUTE_END, "到达终点", true);
+ }
+ }
+ }
+ }
+
+ /**
+ * 设置地图中心点坐标
+ *
+ * @param lon Longitude
+ * @param lat latitude
+ */
+ public void setMapCenter(double lon, double lat) {
+ double[] mercators = MapUtils.lonLat2Mercator(lon, lat);
+ Point centerPoint = new Point((float) mercators[0], (float) mercators[1]);
+ navMap.setCenterPoint(centerPoint);
+ MapElement peopleEle = new MapElement(centerPoint.getPointX(), centerPoint.getPointY(), true);
+ peopleEle.setActionType(Const.ROUTE_PEOPLE);
+ navMap.addElement(peopleEle);
+ }
+
+ private void addElementToMap(double[] coordinates, String actionType, String content, boolean isImage) {
+ MapElement mapElementEnd = new MapElement((float) coordinates[0], (float) coordinates[1], isImage);
+ mapElementEnd.setActionType(actionType);
+ mapElementEnd.setActionContent(content);
+ navMap.addElement(mapElementEnd);
+ }
+
+ /**
+ * MapInterface
+ *
+ * @since 2021-03-29
+ */
+ public interface DataCallBack {
+ /**
+ * 设置输入提示视图
+ *
+ * @param tips tips
+ */
+ void setInputTipsView(List tips);
+
+ /**
+ * 设置导航路径视图
+ *
+ * @param route route
+ */
+ void setRouteView(String route);
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f75c67feee9c726f7c9954d6e4fa7ad7737ab3e
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import ohos.agp.utils.Point;
+
+/**
+ * MapElement地图元素类,用于封装导航路径上的点和图标元素
+ *
+ * @since 2021-02-01
+ */
+public class MapElement {
+ // 元素的墨卡托影坐标
+ private Point mercatorPoint = new Point(0, 0);
+
+ // 元素在屏幕上的坐标(原始)
+ private Point originPoint = new Point(0, 0);
+
+ // 元素在屏幕上的坐标(拖动后)
+ private Point nowPoint = new Point(0, 0);
+
+ private String actionType;
+
+ private String actionContent;
+
+ private boolean isImage = false;
+
+ /**
+ * MapElement
+ *
+ * @param mercatorX 墨卡托影X轴坐标
+ * @param mercatorY 墨卡托影y轴坐标
+ * @since 2021-03-12
+ */
+ public MapElement(float mercatorX, float mercatorY) {
+ mercatorPoint = new Point(mercatorX, mercatorY);
+ }
+
+ /**
+ * MapElement
+ *
+ * @param mercatorX 墨卡托影X轴坐标
+ * @param mercatorY 墨卡托影y轴坐标
+ * @param isImage 元素是否为图片
+ * @since 2021-03-12
+ */
+ public MapElement(float mercatorX, float mercatorY, boolean isImage) {
+ mercatorPoint = new Point(mercatorX, mercatorY);
+ this.isImage = isImage;
+ }
+
+ public boolean isImage() {
+ return isImage;
+ }
+
+ public String getActionContent() {
+ return actionContent;
+ }
+
+ public void setActionContent(String actionContent) {
+ this.actionContent = actionContent;
+ }
+
+ public String getActionType() {
+ return actionType;
+ }
+
+ public void setActionType(String actionType) {
+ this.actionType = actionType;
+ }
+
+ /**
+ * 获取元素当前x轴坐标
+ *
+ * @return float类型
+ */
+ public float getNowPointX() {
+ return nowPoint.getPointX();
+ }
+
+ /**
+ * 设置元素当前x轴坐标
+ *
+ * @param pointX 当前x轴坐标
+ */
+ public void setNowPointX(float pointX) {
+ nowPoint = new Point(pointX, nowPoint.getPointY());
+ }
+
+ /**
+ * 获取元素当前y轴坐标
+ *
+ * @return float类型
+ */
+ public float getNowPointY() {
+ return nowPoint.getPointY();
+ }
+
+ /**
+ * 设置元素当前y轴坐标
+ *
+ * @param pointY 元素当前y轴坐标
+ */
+ public void setNowPointY(float pointY) {
+ nowPoint = new Point(nowPoint.getPointX(), pointY);
+ }
+
+ /**
+ * 获取元素x轴坐标
+ *
+ * @return float类型
+ */
+ public float getOriginX() {
+ return originPoint.getPointX();
+ }
+
+ /**
+ * 设置元素x轴坐标
+ *
+ * @param pointX x-axis
+ */
+ public void setOriginX(float pointX) {
+ originPoint = new Point(pointX, originPoint.getPointY());
+ }
+
+ /**
+ * 获取元素y轴坐标
+ *
+ * @return float类型
+ */
+ public float getOriginY() {
+ return originPoint.getPointY();
+ }
+
+ /**
+ * 设置元素y轴坐标
+ *
+ * @param pointY 元素y轴坐标
+ */
+ public void setOriginY(float pointY) {
+ originPoint = new Point(originPoint.getPointX(), pointY);
+ }
+
+ public Point getMercatorPoint() {
+ return mercatorPoint;
+ }
+
+ public void setMercatorPoint(Point mercatorPoint) {
+ this.mercatorPoint = mercatorPoint;
+ }
+
+ public Point getOriginPoint() {
+ return originPoint;
+ }
+
+ public void setOriginPoint(Point originPoint) {
+ this.originPoint = originPoint;
+ }
+
+ public Point getNowPoint() {
+ return nowPoint;
+ }
+
+ public void setNowPoint(Point nowPoint) {
+ this.nowPoint = nowPoint;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..33ecfffb0644ff94df4b1bfa585b03e10739dafd
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import com.huawei.codelab.IMapIdlInterface;
+import com.huawei.codelab.MapIdlInterfaceStub;
+import com.huawei.codelab.WatchAbility;
+import com.huawei.codelab.WatchService;
+import com.huawei.codelab.bean.InputTipsResult;
+import com.huawei.codelab.util.LogUtils;
+
+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.distributedschedule.interwork.DeviceManager;
+import ohos.eventhandler.EventHandler;
+import ohos.eventhandler.EventRunner;
+import ohos.eventhandler.InnerEvent;
+import ohos.rpc.IRemoteObject;
+import ohos.rpc.RemoteException;
+
+import java.util.List;
+
+/**
+ * 地图控制类
+ *
+ * @since 2021-03-31
+ */
+public class MapManager {
+ private static final String TAG = MapManager.class.getSimpleName();
+
+ private static final int STEP_DELAY_TIME = 800;
+
+ private IMapIdlInterface proxy;
+
+ private MapEventHandler mapEventHandler;
+
+ private int stepPoint = 0;
+
+ private MapElement nextElement;
+
+ private NavMap navMap;
+
+ private AbilitySlice slice;
+
+ private NavListener navListener;
+
+ /**
+ * IAbilityConnection
+ *
+ * @since 2021-03-12
+ */
+ private IAbilityConnection conn = new IAbilityConnection() {
+ @Override
+ public void onAbilityConnectDone(ElementName element, IRemoteObject remote, int resultCode) {
+ LogUtils.info(TAG, "onAbilityConnectDone......");
+ proxy = MapIdlInterfaceStub.asInterface(remote);
+ }
+
+ @Override
+ public void onAbilityDisconnectDone(ElementName element, int resultCode) {
+ LogUtils.info(TAG, "onAbilityDisconnectDone......");
+ proxy = null;
+ }
+ };
+
+ /**
+ * 用于实现路径上点的移动
+ *
+ * @since 2021-03-12
+ */
+ private Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ MapElement peopleElement = navMap.getMapElements().get(0);
+ nextElement = navMap.getMapElements().get(stepPoint + 1);
+ peopleElement.setMercatorPoint(nextElement.getMercatorPoint());
+ peopleElement.setNowPoint(nextElement.getNowPoint());
+ peopleElement.setOriginPoint(nextElement.getOriginPoint());
+ mapEventHandler.sendEvent(1, EventHandler.Priority.IMMEDIATE);
+ mapEventHandler.postTask(task, STEP_DELAY_TIME, EventHandler.Priority.IMMEDIATE);
+ stepPoint++;
+ navMap.setStepPoint(stepPoint);
+ LogUtils.info(TAG, "run......" + stepPoint);
+ if (stepPoint >= navMap.getMapElements().size() - 1) {
+ mapEventHandler.removeTask(task);
+ }
+ }
+ };
+
+ /**
+ * 构造方法
+ *
+ * @param navMap navMap
+ * @param slice slice
+ */
+ public MapManager(NavMap navMap, AbilitySlice slice) {
+ this.navMap = navMap;
+ this.slice = slice;
+ mapEventHandler = new MapEventHandler(EventRunner.current());
+ }
+
+ /**
+ * 移除tips中location为空的元素
+ *
+ * @param tips tips
+ */
+ public static void clearEmptyLocation(List tips) {
+ for (int i = 0; i < tips.size(); i++) {
+ InputTipsResult.TipsEntity tipsEntity = tips.get(i);
+ if ((tipsEntity.getLocation()).isEmpty()) {
+ tips.remove(tipsEntity);
+ }
+ }
+ }
+
+ public int getStepPoint() {
+ return stepPoint;
+ }
+
+ public void setStepPoint(int stepPoint) {
+ this.stepPoint = stepPoint;
+ }
+
+ public void setNavListener(NavListener navListener) {
+ this.navListener = navListener;
+ }
+
+ /**
+ * 连接手表
+ */
+ public void connectWatch() {
+ List devices = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);
+ for (DeviceInfo deviceInfo : devices) {
+ if (DeviceInfo.DeviceType.SMART_WATCH.equals(deviceInfo.getDeviceType())) {
+ connectWatchService(deviceInfo.getDeviceId());
+ startWatchAbility(deviceInfo.getDeviceId());
+ }
+ }
+ }
+
+ /**
+ * 连接WatchService
+ *
+ * @param deviceId 智能表deviceId
+ */
+ private void connectWatchService(String deviceId) {
+ Intent intent = new Intent();
+ Operation operation = new Intent.OperationBuilder().withDeviceId(deviceId)
+ .withBundleName(slice.getBundleName())
+ .withAbilityName(WatchService.class.getName())
+ .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
+ .build();
+ intent.setOperation(operation);
+ slice.connectAbility(intent, conn);
+ }
+
+ /**
+ * 启动WatchAbility
+ *
+ * @param deviceId 智能表deviceId
+ */
+ private void startWatchAbility(String deviceId) {
+ Intent intent = new Intent();
+ Operation operation = new Intent.OperationBuilder().withDeviceId(deviceId)
+ .withBundleName(slice.getBundleName())
+ .withAbilityName(WatchAbility.class.getName())
+ .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
+ .build();
+ intent.setOperation(operation);
+ slice.startAbility(intent);
+ }
+
+ /**
+ * 向WatchService发送数据
+ *
+ * @param actionType actionType
+ * @param actionContent actionContent
+ */
+ private void requestRemote(String actionType, String actionContent) {
+ LogUtils.info(TAG, "requestRemote");
+ try {
+ if (proxy != null) {
+ proxy.action(actionType, actionContent);
+ }
+ } catch (RemoteException e) {
+ LogUtils.info(TAG, "RemoteException:RemoteException");
+ }
+ }
+
+ /**
+ * 开始导航
+ */
+ public void startNav() {
+ if (!mapEventHandler.hasInnerEvent(task)) {
+ mapEventHandler.postTask(task, STEP_DELAY_TIME, EventHandler.Priority.IMMEDIATE);
+ connectWatch();
+ }
+ }
+
+ /**
+ * 结束导航
+ */
+ public void endNav() {
+ requestRemote(Const.STOP_WATCH_ABILITY, "");
+ mapEventHandler.removeTask(task);
+ stepPoint = 0;
+ navMap.setStepPoint(0);
+ navMap.getMapElements().clear();
+ navMap.invalidate();
+ }
+
+ /**
+ * 迁移
+ */
+ public void translate() {
+ slice.continueAbility();
+ requestRemote(Const.STOP_WATCH_ABILITY, "");
+ }
+
+ /**
+ * 迁移完成后的回调
+ */
+ public void translateComplete() {
+ navMap.getMapElements().clear();
+ navMap.invalidate();
+ mapEventHandler.removeTask(task);
+ }
+
+ /**
+ * 导航行动轨迹监听
+ *
+ * @since 2021-03-29
+ */
+ public interface NavListener {
+ /**
+ * 监听回调
+ *
+ * @param mapElement MapElement
+ */
+ void onNavListener(MapElement mapElement);
+ }
+
+ /**
+ * MapEventHandler
+ *
+ * @since 2021-03-12
+ */
+ private class MapEventHandler extends EventHandler {
+ private MapEventHandler(EventRunner runner) {
+ super(runner);
+ }
+
+ @Override
+ public void processEvent(InnerEvent event) {
+ super.processEvent(event);
+ if (event.eventId != 1) {
+ return;
+ }
+ LogUtils.info(TAG, "processEvent invalidate");
+ if (nextElement.getActionType() != null && !nextElement.getActionType().isEmpty()) {
+ navListener.onNavListener(nextElement);
+ }
+ if (proxy != null) {
+ requestRemote(nextElement.getActionType() == null ? "" : nextElement.getActionType(),
+ nextElement.getActionContent() == null ? "" : nextElement.getActionContent());
+ }
+ navMap.invalidate();
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java
new file mode 100644
index 0000000000000000000000000000000000000000..53dff9c46ef46f2d9840788fa79411420b56ce57
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import ohos.agp.render.PixelMapHolder;
+import ohos.agp.utils.Point;
+import ohos.media.image.PixelMap;
+
+/**
+ * Tile
+ *
+ * @since 2021-03-12
+ */
+public class MapTile extends PixelMapHolder {
+ private Point originPoint = new Point(0, 0);
+
+ private Point nowPoint = new Point(0, 0);
+
+ private int row;
+
+ private int col;
+
+ /**
+ * MapElement
+ *
+ * @param pixelMap pixelMap
+ * @param pointX pointX
+ * @param pointY pointY
+ * @since 2021-03-12
+ */
+ public MapTile(PixelMap pixelMap, float pointX, float pointY) {
+ super(pixelMap);
+ originPoint = new Point(pointX, pointY);
+ nowPoint = new Point(pointX, pointY);
+ }
+
+ /**
+ * 获取元素当前x轴坐标
+ *
+ * @return 类型为float
+ */
+ public float getNowPointX() {
+ return nowPoint.getPointX();
+ }
+
+ /**
+ * 设置元素当前x轴坐标
+ *
+ * @param pointX pointX
+ */
+ public void setNowPointX(float pointX) {
+ nowPoint = new Point(pointX, nowPoint.getPointY());
+ }
+
+ /**
+ * 获取元素当前y轴坐标
+ *
+ * @return 类型为float
+ */
+ public float getNowPointY() {
+ return nowPoint.getPointY();
+ }
+
+ /**
+ * 设置元素当前y轴坐标
+ *
+ * @param pointY pointY
+ */
+ public void setNowPointY(float pointY) {
+ nowPoint = new Point(nowPoint.getPointX(), pointY);
+ }
+
+ /**
+ * 获取元素x轴坐标
+ *
+ * @return 类型为float
+ */
+ public float getOriginX() {
+ return originPoint.getPointX();
+ }
+
+ /**
+ * 设置元素x轴坐标
+ *
+ * @param pointX pointX
+ */
+ public void setOriginX(float pointX) {
+ originPoint = new Point(pointX, originPoint.getPointY());
+ }
+
+ /**
+ * 获取元素y轴坐标
+ *
+ * @return 类型为float
+ */
+ public float getOriginY() {
+ return originPoint.getPointY();
+ }
+
+ /**
+ * 设置元素y轴坐标
+ *
+ * @param pointY 类型为float
+ */
+ public void setOriginY(float pointY) {
+ originPoint = new Point(originPoint.getPointX(), pointY);
+ }
+
+ public int getRow() {
+ return row;
+ }
+
+ public void setRow(int row) {
+ this.row = row;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+ public void setCol(int col) {
+ this.col = col;
+ }
+
+ /**
+ * isInBoundary
+ *
+ * @param rowMin rowMin
+ * @param rowMax rowMax
+ * @param colMin colMin
+ * @param colMax colMax
+ * @return isInBoundary
+ */
+ public boolean isInBoundary(int rowMin, int rowMax, int colMin, int colMax) {
+ if (row < rowMin || row > rowMax || col < colMin || col > colMax) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..52f0b5e77c186013efc46025d36fc55e6b4ab5ce
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java
@@ -0,0 +1,385 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.map;
+
+import com.huawei.codelab.util.ImageUtils;
+import com.huawei.codelab.util.ScreenUtils;
+
+import ohos.agp.components.AttrSet;
+import ohos.agp.components.Component;
+import ohos.agp.render.Canvas;
+import ohos.agp.render.Paint;
+import ohos.agp.render.Path;
+import ohos.agp.render.PixelMapHolder;
+import ohos.agp.utils.Color;
+import ohos.agp.utils.Point;
+import ohos.app.Context;
+import ohos.app.dispatcher.task.TaskPriority;
+import ohos.media.image.PixelMap;
+import ohos.multimodalinput.event.MmiPoint;
+import ohos.multimodalinput.event.TouchEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * NavMap
+ *
+ * @since 2021-03-12
+ */
+public class NavMap extends Component implements Component.DrawTask, Component.TouchEventListener {
+ private static final int TILE_LENGTH = 512;
+
+ private static final int ROUTE_WIDTH = 20;
+
+ private static final int ROUTE_COLOR_R = 61;
+
+ private static final int ROUTE_COLOR_G = 89;
+
+ private static final int ROUTE_COLOR_B = 171;
+
+ private static final int COMPONENT_HALF = 2;
+
+ private static final double COMPONENT_HALF_F = 2;
+
+ private static final int LEFT_MARGIN = 40;
+
+ private static final int RIGHT_MARGIN = 80;
+
+ // 墨卡托总投影半轴长度
+ private static final double OVER_LENGTH = 20037508.3427892;
+
+ // 高德地图的缩放级别, 取值范围3~18
+ private static final int ZOOM = 15;
+
+ private double tileRealLength;
+
+ private Point centerPoint;
+
+ private int rowMin;
+
+ private int rowMax;
+
+ private int colMin;
+
+ private int colMax;
+
+ private float touchedDownX;
+
+ private float touchedDownY;
+
+ private double mapComponentWidth;
+
+ private double mapComponentHeight;
+
+ private List mapTiles;
+
+ private List elements;
+
+ private Paint paint;
+
+ private Paint linePaint;
+
+ private Paint grayPaint;
+
+ private Path path = new Path();
+
+ private Path grayPath = new Path();
+
+ private int stepPoint;
+
+ /**
+ * 构造方法
+ *
+ * @param context Context
+ * @param attrSet AttrSet
+ */
+
+ public NavMap(Context context, AttrSet attrSet) {
+ super(context, attrSet);
+ initPaint();
+ }
+
+ private void initPaint() {
+ paint = new Paint();
+ paint.setColor(new Color(Color.rgb(ROUTE_COLOR_R, ROUTE_COLOR_G, ROUTE_COLOR_B)));
+ paint.setStrokeWidth(ROUTE_WIDTH);
+ paint.setStyle(Paint.Style.STROKE_STYLE);
+ paint.setAntiAlias(true);
+
+ grayPaint = new Paint();
+ grayPaint.setColor(Color.GRAY);
+ grayPaint.setStrokeWidth(ROUTE_WIDTH);
+ grayPaint.setStyle(Paint.Style.STROKE_STYLE);
+ grayPaint.setAntiAlias(true);
+
+ linePaint = new Paint();
+ }
+
+ /**
+ * 获取地图元素集合
+ *
+ * @return 类型为List
+ */
+ public List getMapElements() {
+ return elements;
+ }
+
+ /**
+ * 设置中心点坐标
+ *
+ * @param centerPoint centerPoint
+ */
+ public void setCenterPoint(Point centerPoint) {
+ this.centerPoint = centerPoint;
+ initMapCanvas(true);
+ }
+
+ public void setStepPoint(int stepPoint) {
+ this.stepPoint = stepPoint;
+ }
+
+ /**
+ * 往地图中添加地图元素
+ *
+ * @param mapElement 地图元素
+ */
+ public void addElement(MapElement mapElement) {
+ if (elements == null) {
+ elements = new ArrayList<>(0);
+ }
+ double componentX =
+ (mapElement.getMercatorPoint().getPointX() - centerPoint.getPointX()) / tileRealLength * TILE_LENGTH
+ + mapComponentWidth / COMPONENT_HALF;
+ double componentY =
+ (centerPoint.getPointY() - mapElement.getMercatorPoint().getPointY()) / tileRealLength * TILE_LENGTH
+ + mapComponentHeight / COMPONENT_HALF;
+ mapElement.setNowPoint(new Point((float) componentX, (float) componentY));
+ mapElement.setOriginPoint(new Point((float) componentX, (float) componentY));
+ elements.add(mapElement);
+ invalidate();
+ }
+
+ /**
+ * 初始化地图
+ *
+ * @param isRefresh 是否为刷新
+ */
+ public void initMapCanvas(boolean isRefresh) {
+ // 在某个缩放级别下,瓦片的行数(列数)
+ int rowCount = (int) Math.pow(COMPONENT_HALF, ZOOM);
+ tileRealLength = OVER_LENGTH * COMPONENT_HALF / rowCount;
+ mapComponentWidth = ScreenUtils.getScreenWidth(getContext());
+ mapComponentHeight = ScreenUtils.getScreenHeight(getContext());
+
+ double minX = centerPoint.getPointX() - mapComponentWidth / COMPONENT_HALF_F * tileRealLength / TILE_LENGTH;
+ colMin = (int) Math.floor((minX + OVER_LENGTH) / tileRealLength);
+ double maxX = centerPoint.getPointX() + mapComponentWidth / COMPONENT_HALF_F * tileRealLength / TILE_LENGTH;
+ colMax = Math.min((int) Math.floor((maxX + OVER_LENGTH) / tileRealLength), rowCount - 1);
+ double maxY = centerPoint.getPointY() + mapComponentHeight / COMPONENT_HALF_F * tileRealLength / TILE_LENGTH;
+ rowMin = Math.min(rowCount - 1 - (int) Math.floor((maxY + OVER_LENGTH) / tileRealLength), rowCount - 1);
+ double minY = centerPoint.getPointY() - mapComponentHeight / COMPONENT_HALF_F * tileRealLength / TILE_LENGTH;
+ rowMax = rowCount - 1 - (int) Math.floor((minY + OVER_LENGTH) / tileRealLength);
+
+ addDrawTask(this);
+ setTouchEventListener(this);
+
+ initTiles(isRefresh);
+ initElement(isRefresh);
+ }
+
+ /**
+ * 初始化地图瓦片集合
+ *
+ * @param isRefresh 是否为刷新
+ */
+ private void initTiles(boolean isRefresh) {
+ if (mapTiles == null || isRefresh) {
+ mapTiles = new CopyOnWriteArrayList<>();
+ }
+ mapTiles.removeIf(mapTile -> !mapTile.isInBoundary(rowMin, rowMax, colMin, colMax));
+
+ getContext().getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(this::setTiles);
+ }
+
+ private void setTiles() {
+ for (int row = rowMin; row <= rowMax; row++) {
+ for (int col = colMin; col <= colMax; col++) {
+ String urlString = String.format(Const.TILE_URL, col, row, ZOOM);
+
+ if (hasThisTile(row, col)) {
+ continue;
+ }
+
+ PixelMap pixelMap = ImageUtils.getMapPixelMap(urlString);
+ if (pixelMap == null) {
+ continue;
+ }
+
+ double tileX = col * tileRealLength - OVER_LENGTH;
+ double tileY = OVER_LENGTH - row * tileRealLength;
+ double componentX = (tileX - centerPoint.getPointX()) / tileRealLength * TILE_LENGTH
+ + mapComponentWidth / COMPONENT_HALF;
+ double componentY = (centerPoint.getPointY() - tileY) / tileRealLength * TILE_LENGTH
+ + mapComponentHeight / COMPONENT_HALF;
+ MapTile mapTile = new MapTile(pixelMap, (float) componentX, (float) componentY);
+ mapTile.setCol(col);
+ mapTile.setRow(row);
+ mapTiles.add(mapTile);
+ getContext().getUITaskDispatcher().asyncDispatch(this::invalidate);
+ }
+ }
+ }
+
+ private boolean hasThisTile(int row, int col) {
+ for (MapTile mapTile : mapTiles) {
+ if (mapTile.getRow() == row && mapTile.getCol() == col) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 初始化地图元素集合
+ *
+ * @param isRefresh refresh
+ */
+ private void initElement(boolean isRefresh) {
+ if (elements == null || isRefresh) {
+ elements = new ArrayList<>(0);
+ }
+ }
+
+ /**
+ * onDraw
+ *
+ * @param component component
+ * @param canvas canvas
+ */
+ @Override
+ public void onDraw(Component component, Canvas canvas) {
+ path.reset();
+ grayPath.reset();
+ drawTiles(canvas);
+ drawRoutePath(canvas);
+ drawImageElement(canvas);
+ }
+
+ private void drawTiles(Canvas canvas) {
+ for (MapTile mapTile : mapTiles) {
+ canvas.drawPixelMapHolder(mapTile, mapTile.getNowPointX(), mapTile.getNowPointY(), linePaint);
+ }
+ }
+
+ private void drawRoutePath(Canvas canvas) {
+ for (int i = 1; i < elements.size(); i++) {
+ MapElement mapElement = elements.get(i);
+ Point point = mapElement.getNowPoint();
+ float pointX = point.getPointX();
+ float pointY = point.getPointY();
+ if (i == 1 || i == elements.size() - 1) {
+ path.moveTo(pointX, pointY);
+ } else {
+ path.lineTo(pointX, pointY);
+ }
+
+ if (i <= stepPoint) {
+ if (i == 1 || i == elements.size() - 1) {
+ grayPath.moveTo(pointX, pointY);
+ } else {
+ grayPath.lineTo(pointX, pointY);
+ }
+ }
+ }
+
+ // 绘制导航路径(未走过的路径)
+ canvas.drawPath(path, paint);
+
+ // 绘制导航路径(已走过的路径)
+ canvas.drawPath(grayPath, grayPaint);
+ }
+
+ private void drawImageElement(Canvas canvas) {
+ for (MapElement element : elements) {
+ if (element.isImage()) {
+ PixelMapHolder pmh = new PixelMapHolder(ImageUtils.getPixelMap(getContext(), element.getActionType()));
+ canvas.drawPixelMapHolder(pmh, element.getNowPointX() - LEFT_MARGIN,
+ element.getNowPointY() - RIGHT_MARGIN, new Paint());
+ }
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
+ MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
+
+ // down
+ if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
+ touchedDownX = point.getX() - component.getContentPositionX();
+ touchedDownY = point.getY() - component.getContentPositionY();
+ return true;
+ }
+
+ // move
+ if (touchEvent.getAction() == TouchEvent.POINT_MOVE) {
+ for (MapTile mapTile : mapTiles) {
+ mapTile.setNowPointX(
+ (point.getX() - component.getContentPositionX()) - touchedDownX + mapTile.getOriginX());
+ mapTile.setNowPointY(
+ (point.getY() - component.getContentPositionY()) - touchedDownY + mapTile.getOriginY());
+ }
+ for (MapElement element : elements) {
+ element.setNowPointX(
+ (point.getX() - component.getContentPositionX()) - touchedDownX + element.getOriginX());
+ element.setNowPointY(
+ (point.getY() - component.getContentPositionY()) - touchedDownY + element.getOriginY());
+ }
+ component.invalidate();
+ }
+
+ // up
+ if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
+ float newCenterPointX = (float) (centerPoint.getPointX()
+ - (point.getX() - component.getContentPositionX() - touchedDownX) / TILE_LENGTH * tileRealLength);
+ float newCenterPointY = (float) (centerPoint.getPointY()
+ + (point.getY() - component.getContentPositionY() - touchedDownY) / TILE_LENGTH * tileRealLength);
+ centerPoint = new Point(newCenterPointX, newCenterPointY);
+
+ for (MapTile mapTile : mapTiles) {
+ mapTile.setNowPointX(
+ (point.getX() - component.getContentPositionX()) - touchedDownX + mapTile.getOriginX());
+ mapTile.setNowPointY(
+ (point.getY() - component.getContentPositionY()) - touchedDownY + mapTile.getOriginY());
+ mapTile.setOriginX(mapTile.getNowPointX());
+ mapTile.setOriginY(mapTile.getNowPointY());
+ }
+
+ for (MapElement element : elements) {
+ element.setNowPointX(
+ (point.getX() - component.getContentPositionX()) - touchedDownX + element.getOriginX());
+ element.setNowPointY(
+ (point.getY() - component.getContentPositionY()) - touchedDownY + element.getOriginY());
+ element.setOriginX(element.getNowPointX());
+ element.setOriginY(element.getNowPointY());
+ }
+ initMapCanvas(false);
+ }
+ return false;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec2c4099767cbfe93967053a2c8aaf7f3dc7d454
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.provider;
+
+import com.huawei.codelab.ResourceTable;
+import com.huawei.codelab.bean.InputTipsResult;
+
+import ohos.agp.components.BaseItemProvider;
+import ohos.agp.components.Component;
+import ohos.agp.components.ComponentContainer;
+import ohos.agp.components.LayoutScatter;
+import ohos.agp.components.Text;
+import ohos.app.Context;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * InputTipsProvider
+ *
+ * @since 2021-03-12
+ */
+public class InputTipsProvider extends BaseItemProvider {
+ private List list;
+
+ private Context context;
+
+ /**
+ * InputTipsProvider
+ *
+ * @param context Context context
+ * @param list list
+ * @since 2021-03-12
+ */
+ public InputTipsProvider(Context context, List list) {
+ this.list = list;
+ this.context = context;
+ }
+
+ @Override
+ public int getCount() {
+ return list == null ? 0 : list.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return Optional.of(list.get(position));
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public Component getComponent(int position, Component componentP, ComponentContainer componentContainer) {
+ ViewHolder viewHolder = null;
+ Component component = componentP;
+ if (component == null) {
+ component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_input_tips, null, false);
+ viewHolder = new ViewHolder();
+ if (component.findComponentById(ResourceTable.Id_tips_name) instanceof Text) {
+ viewHolder.tipsName = (Text) component.findComponentById(ResourceTable.Id_tips_name);
+ }
+ if (component.findComponentById(ResourceTable.Id_tips_detail) instanceof Text) {
+ viewHolder.tipsDetail = (Text) component.findComponentById(ResourceTable.Id_tips_detail);
+ }
+ component.setTag(viewHolder);
+ } else {
+ if (component.getTag() instanceof ViewHolder) {
+ viewHolder = (ViewHolder) component.getTag();
+ }
+ }
+ if (viewHolder != null) {
+ viewHolder.tipsName.setText(list.get(position).getName());
+ if (list.get(position).getAddress() instanceof String) {
+ viewHolder.tipsDetail.setText((String) list.get(position).getAddress());
+ } else {
+ viewHolder.tipsDetail.setText(list.get(position).getName());
+ }
+ }
+ return component;
+ }
+
+ /**
+ * ViewHolder
+ *
+ * @since 2021-03-12
+ */
+ private static class ViewHolder {
+ private Text tipsName;
+
+ private Text tipsDetail;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad634d3a5986069ba1c96a0fa610d995f065bcf7
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java
@@ -0,0 +1,378 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.slice;
+
+import com.huawei.codelab.ResourceTable;
+import com.huawei.codelab.bean.InputTipsResult;
+import com.huawei.codelab.map.MapDataHelper;
+import com.huawei.codelab.map.MapElement;
+import com.huawei.codelab.map.MapManager;
+import com.huawei.codelab.map.NavMap;
+import com.huawei.codelab.provider.InputTipsProvider;
+import com.huawei.codelab.util.GsonUtils;
+import com.huawei.codelab.util.ImageUtils;
+import com.huawei.codelab.util.LogUtils;
+import com.huawei.codelab.util.PermissionsUtils;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.ability.IAbilityContinuation;
+import ohos.aafwk.content.Intent;
+import ohos.aafwk.content.IntentParams;
+import ohos.agp.components.Button;
+import ohos.agp.components.Component;
+import ohos.agp.components.DependentLayout;
+import ohos.agp.components.DirectionalLayout;
+import ohos.agp.components.Image;
+import ohos.agp.components.ListContainer;
+import ohos.agp.components.Text;
+import ohos.agp.components.TextField;
+import ohos.agp.utils.Point;
+import ohos.bundle.IBundleManager;
+import ohos.security.SystemPermission;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MainAbilitySlice
+ *
+ * @since 2021-03-12
+ */
+public class MainAbilitySlice extends AbilitySlice
+ implements Component.ClickedListener, IAbilityContinuation, MapDataHelper.DataCallBack {
+ private static final String TAG = MainAbilitySlice.class.getSimpleName();
+
+ private static final String ELEMENT_STRING = "elementsString";
+
+ private static final int INPUT_START = 1;
+
+ private static final int INPUT_END = 2;
+
+ private int inputType;
+
+ private DependentLayout routeTipsLayout;
+
+ private NavMap navMap;
+
+ private List elements;
+
+ private TextField startTextField;
+
+ private TextField endTextField;
+
+ private ListContainer listContainer;
+
+ private DependentLayout inputTipsLayout;
+
+ private DirectionalLayout navBottom;
+
+ private Button btnStartNav;
+
+ private Button btnEndNav;
+
+ private String endLocation;
+
+ private Button navTranslate;
+
+ private DirectionalLayout selectPointLayout;
+
+ private boolean isSetInputText = false;
+
+ private List tips = new ArrayList<>(0);
+
+ private InputTipsProvider inputTipsProvider;
+
+ private Text routeContent;
+
+ private MapDataHelper mapDataHelper;
+
+ private MapManager mapManager;
+
+ private Image routeImage;
+
+ private int stepPoint = 0;
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_ability_main);
+ findComponentById();
+ initView();
+ initInputTipsProvider();
+ setListener();
+ }
+
+ private void findComponentById() {
+ if (findComponentById(ResourceTable.Id_map) instanceof NavMap) {
+ navMap = (NavMap) findComponentById(ResourceTable.Id_map);
+ }
+
+ if (findComponentById(ResourceTable.Id_start_point_field) instanceof TextField) {
+ startTextField = (TextField) findComponentById(ResourceTable.Id_start_point_field);
+ }
+
+ if (findComponentById(ResourceTable.Id_end_point_field) instanceof TextField) {
+ endTextField = (TextField) findComponentById(ResourceTable.Id_end_point_field);
+ }
+
+ if (findComponentById(ResourceTable.Id_route_content) instanceof Text) {
+ routeContent = (Text) findComponentById(ResourceTable.Id_route_content);
+ }
+
+ if (findComponentById(ResourceTable.Id_route_tips) instanceof DependentLayout) {
+ routeTipsLayout = (DependentLayout) findComponentById(ResourceTable.Id_route_tips);
+ }
+
+ if (findComponentById(ResourceTable.Id_route_img) instanceof Image) {
+ routeImage = (Image) findComponentById(ResourceTable.Id_route_img);
+ }
+
+ if (findComponentById(ResourceTable.Id_list_input_tips) instanceof ListContainer) {
+ listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_input_tips);
+ }
+
+ if (findComponentById(ResourceTable.Id_layout_input_tips) instanceof DependentLayout) {
+ inputTipsLayout = (DependentLayout) findComponentById(ResourceTable.Id_layout_input_tips);
+ }
+
+ if (findComponentById(ResourceTable.Id_select_point) instanceof DirectionalLayout) {
+ selectPointLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_select_point);
+ }
+
+ if (findComponentById(ResourceTable.Id_nav_bottom) instanceof DirectionalLayout) {
+ navBottom = (DirectionalLayout) findComponentById(ResourceTable.Id_nav_bottom);
+ }
+
+ if (findComponentById(ResourceTable.Id_start_nav) instanceof Button) {
+ btnStartNav = (Button) findComponentById(ResourceTable.Id_start_nav);
+ }
+
+ if (findComponentById(ResourceTable.Id_end_nav) instanceof Button) {
+ btnEndNav = (Button) findComponentById(ResourceTable.Id_end_nav);
+ }
+
+ if (findComponentById(ResourceTable.Id_nav_translate) instanceof Button) {
+ navTranslate = (Button) findComponentById(ResourceTable.Id_nav_translate);
+ }
+ }
+
+ private void setListener() {
+ btnStartNav.setClickedListener(this);
+ btnEndNav.setClickedListener(this);
+ navTranslate.setClickedListener(this);
+
+ endTextField.setClickedListener(component -> inputTipsLayout.setVisibility(Component.VISIBLE));
+ startTextField.setClickedListener(component -> inputTipsLayout.setVisibility(Component.VISIBLE));
+
+ mapDataHelper.setDataCallBack(this);
+
+ mapManager.setNavListener(mapElement -> {
+ routeContent.setText(mapElement.getActionContent());
+ routeImage.setPixelMap(ImageUtils.getImageId(mapElement.getActionType()));
+ });
+
+ PermissionsUtils.getInstance().setRequestListener(permission -> {
+ if (permission.equals(SystemPermission.LOCATION)) {
+ mapDataHelper.getMyLocation();
+ }
+ });
+
+ startTextField.addTextObserver((text, start, before, count) -> {
+ if (!text.trim().isEmpty() && !isSetInputText) {
+ mapDataHelper.getInputTips(text);
+ }
+ });
+
+ endTextField.addTextObserver((text, start, before, count) -> {
+ if (!text.trim().isEmpty() && !isSetInputText) {
+ mapDataHelper.getInputTips(text);
+ }
+ });
+
+ startTextField.setFocusChangedListener((component, hasFocus) -> {
+ if (hasFocus) {
+ inputType = INPUT_START;
+ }
+ });
+
+ endTextField.setFocusChangedListener((component, hasFocus) -> {
+ if (hasFocus) {
+ inputType = INPUT_END;
+ }
+ });
+ }
+
+ private void initView() {
+ mapDataHelper = new MapDataHelper(navMap, this);
+ mapManager = new MapManager(navMap, this);
+
+ // 解决ListContainer和NavMap的Touch事件冲突
+ listContainer.setTouchEventListener((component, touchEvent) -> true);
+
+ if (verifySelfPermission(SystemPermission.LOCATION) == IBundleManager.PERMISSION_GRANTED) {
+ mapDataHelper.getMyLocation();
+ }
+
+ if (elements != null) {
+ routeTipsLayout.setVisibility(Component.VISIBLE);
+ navBottom.setVisibility(Component.VISIBLE);
+ navTranslate.setVisibility(Component.VISIBLE);
+ btnEndNav.setVisibility(Component.VISIBLE);
+ btnStartNav.setVisibility(Component.HIDE);
+ selectPointLayout.setVisibility(Component.HIDE);
+
+ navMap.setStepPoint(stepPoint);
+ mapManager.setStepPoint(stepPoint);
+ Point mercatorPoint = elements.get(0).getMercatorPoint();
+ navMap.setCenterPoint(new Point(mercatorPoint.getPointX(), mercatorPoint.getPointY()));
+
+ // 将元素集合添加到navMap对象,并重新计算坐标
+ for (MapElement mapElement : elements) {
+ navMap.addElement(mapElement);
+ }
+
+ mapManager.startNav();
+ }
+ }
+
+ private void initInputTipsProvider() {
+ if (inputTipsProvider == null) {
+ inputTipsProvider = new InputTipsProvider(this, tips);
+ listContainer.setItemProvider(inputTipsProvider);
+ listContainer.setItemClickedListener((container, component, position, id) -> {
+ inputTipsLayout.setVisibility(Component.HIDE);
+ if (inputType == INPUT_START) {
+ isSetInputText = true;
+ startTextField.setText(tips.get(position).getName());
+ isSetInputText = false;
+ String location = tips.get(position).getLocation();
+ String[] coordinates = location.split(",");
+ mapDataHelper.setMapCenter(Double.parseDouble(coordinates[0]), Double.parseDouble(coordinates[1]));
+ mapDataHelper.setLocation(location);
+ } else {
+ endLocation = tips.get(position).getLocation();
+ isSetInputText = true;
+ endTextField.setText(tips.get(position).getName());
+ isSetInputText = false;
+ }
+ if (!startTextField.getText().trim().isEmpty() && !endTextField.getText().trim().isEmpty()) {
+ mapDataHelper.getRouteResult(endLocation);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onClick(Component component) {
+ switch (component.getId()) {
+ // 迁移
+ case ResourceTable.Id_nav_translate:
+ mapManager.translate();
+ setTranslateView();
+ break;
+
+ // 开始导航
+ case ResourceTable.Id_start_nav:
+ mapManager.startNav();
+ setStartNavView();
+ break;
+
+ // 结束导航
+ case ResourceTable.Id_end_nav:
+ mapManager.endNav();
+ setEndNavView();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void setTranslateView() {
+ navTranslate.setVisibility(Component.HIDE);
+ }
+
+ private void setStartNavView() {
+ btnStartNav.setVisibility(Component.HIDE);
+ selectPointLayout.setVisibility(Component.HIDE);
+ btnEndNav.setVisibility(Component.VISIBLE);
+ navTranslate.setVisibility(Component.VISIBLE);
+ routeTipsLayout.setVisibility(Component.VISIBLE);
+ }
+
+ private void setEndNavView() {
+ selectPointLayout.setVisibility(Component.VISIBLE);
+ routeTipsLayout.setVisibility(Component.HIDE);
+ btnEndNav.setVisibility(Component.HIDE);
+ btnStartNav.setVisibility(Component.VISIBLE);
+ routeTipsLayout.setVisibility(Component.HIDE);
+ navBottom.setVisibility(Component.HIDE);
+ }
+
+ @Override
+ public void setInputTipsView(List inputTips) {
+ tips.clear();
+ tips.addAll(inputTips);
+ MapManager.clearEmptyLocation(tips);
+ inputTipsProvider.notifyDataChanged();
+ }
+
+ @Override
+ public void setRouteView(String route) {
+ navMap.getMapElements().clear();
+ navBottom.setVisibility(Component.VISIBLE);
+ navMap.setStepPoint(0);
+ mapDataHelper.parseRoute(route);
+ }
+
+ @Override
+ public boolean onStartContinuation() {
+ LogUtils.info(TAG, "onStartContinuation");
+ return true;
+ }
+
+ @Override
+ public void onRemoteTerminated() {
+ LogUtils.info(TAG, "onRemoteTerminated");
+ }
+
+ @Override
+ public boolean onSaveData(IntentParams saveData) {
+ String elementsString = GsonUtils.objectToString(navMap.getMapElements());
+ saveData.setParam(ELEMENT_STRING, elementsString);
+ saveData.setParam("stepPoint", mapManager.getStepPoint());
+ LogUtils.info(TAG, "onSaveData" + navMap.getMapElements().size());
+ return true;
+ }
+
+ @Override
+ public boolean onRestoreData(IntentParams restoreData) {
+ if (restoreData.getParam(ELEMENT_STRING) instanceof String) {
+ String elementsString = (String) restoreData.getParam(ELEMENT_STRING);
+ elements = GsonUtils.jsonToList(elementsString, MapElement.class);
+ }
+ stepPoint = (int) restoreData.getParam("stepPoint");
+ LogUtils.info(TAG, "onRestoreData::elements::" + elements.size());
+ return true;
+ }
+
+ @Override
+ public void onCompleteContinuation(int result) {
+ mapManager.translateComplete();
+ routeTipsLayout.setVisibility(Component.HIDE);
+ LogUtils.info(TAG, "onCompleteContinuation");
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..602317af419dbb7df90a31e6ae162280f27f5dd6
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.slice;
+
+import com.huawei.codelab.ResourceTable;
+import com.huawei.codelab.map.Const;
+import com.huawei.codelab.util.ImageUtils;
+import com.huawei.codelab.util.LogUtils;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.agp.components.Image;
+import ohos.agp.components.Text;
+import ohos.event.commonevent.CommonEventData;
+import ohos.event.commonevent.CommonEventManager;
+import ohos.event.commonevent.CommonEventSubscribeInfo;
+import ohos.event.commonevent.CommonEventSubscriber;
+import ohos.event.commonevent.CommonEventSupport;
+import ohos.event.commonevent.MatchingSkills;
+import ohos.rpc.RemoteException;
+
+/**
+ * WatchAbilitySlice
+ *
+ * @since 2021-03-12
+ */
+public class WatchAbilitySlice extends AbilitySlice {
+ private static final String TAG = MainAbilitySlice.class.getSimpleName();
+
+ private MyCommonEventSubscriber subscriber;
+
+ private Text contentComponent;
+
+ private Image actionImg;
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_ability_watch_main);
+ subscribe();
+ findComponentById();
+ }
+
+ private void findComponentById() {
+ if (findComponentById(ResourceTable.Id_action_content) instanceof Text) {
+ contentComponent = (Text) findComponentById(ResourceTable.Id_action_content);
+ }
+ if (findComponentById(ResourceTable.Id_action_img) instanceof Image) {
+ actionImg = (Image) findComponentById(ResourceTable.Id_action_img);
+ }
+ }
+
+ private void subscribe() {
+ String event = "com.huawei.map";
+ MatchingSkills matchingSkills = new MatchingSkills();
+ matchingSkills.addEvent(event);
+ matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_SCREEN_ON);
+ CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
+ subscriber = new MyCommonEventSubscriber(subscribeInfo);
+ try {
+ CommonEventManager.subscribeCommonEvent(subscriber);
+ } catch (RemoteException e) {
+ LogUtils.error(TAG, "subscribeCommonEvent occur exception.");
+ }
+ }
+
+ private void unSubscribe() {
+ try {
+ CommonEventManager.unsubscribeCommonEvent(subscriber);
+ } catch (RemoteException e) {
+ LogUtils.error(TAG, "unSubscribe Exception");
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ unSubscribe();
+ }
+
+ /**
+ * MyCommonEventSubscriber
+ * 接收从WatchService发送的数据
+ *
+ * @since 2020-12-03
+ */
+ private class MyCommonEventSubscriber extends CommonEventSubscriber {
+ MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
+ super(info);
+ }
+
+ @Override
+ public void onReceiveEvent(CommonEventData commonEventData) {
+ Intent intent = commonEventData.getIntent();
+ String actionType = intent.getStringParam("actionType");
+ String actionContent = intent.getStringParam("actionContent");
+ if (actionType != null) {
+ if (actionType.equals(Const.STOP_WATCH_ABILITY)) {
+ terminateAbility();
+ } else {
+ actionImg.setPixelMap(ImageUtils.getImageId(actionType));
+ contentComponent.setText(actionContent);
+ }
+ }
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..22d887d7360ef240511ffd946ec45b7d4b1e00c0
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ *
+ *
+ * Gson is released under the Apache 2.0 license.
+ *
+ * Copyright 2008 Google Inc.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * GsonUtil
+ *
+ * @param type
+ * @since 2021-03-12
+ */
+public class GsonUtils {
+ private static final String TAG = GsonUtils.class.getSimpleName();
+
+ private static Gson gson = null;
+
+ static {
+ gson = new GsonBuilder().disableHtmlEscaping().registerTypeAdapterFactory(new MyTypeAdapterFactory()).create();
+ }
+
+ private GsonUtils() {
+ }
+
+ /**
+ * 对象转json字符串
+ *
+ * @param data type e
+ * @param type
+ * @return string
+ */
+ public static String objectToString(E data) {
+ String jsonString = null;
+ if (gson != null) {
+ jsonString = gson.toJson(data);
+ }
+ return jsonString;
+ }
+
+ /**
+ * json字符串转对象
+ *
+ * @param jsonString string
+ * @param cls cls
+ * @param T
+ * @return bean
+ */
+ public static T jsonToBean(String jsonString, Class cls) {
+ T bean = null;
+ try {
+ if (gson != null) {
+ bean = gson.fromJson(jsonString, cls);
+ }
+ return bean;
+ } catch (JsonSyntaxException exception) {
+ LogUtils.info(TAG, "jsonToBean exception:" + exception.getMessage());
+ }
+ return bean;
+ }
+
+ /**
+ * json字符串转对象集合
+ *
+ * @param json json string
+ * @param cls cls
+ * @param t
+ * @return list
+ */
+ public static List jsonToList(String json, Class cls) {
+ List lists = new ArrayList(0);
+ JsonArray array = new JsonParser().parse(json).getAsJsonArray();
+ for (final JsonElement elem : array) {
+ lists.add(gson.fromJson(elem, cls));
+ }
+ return lists;
+ }
+
+ /**
+ * Gson容错处理:定义的数据类型为string,但是有时候api返回数据为“[]”,导致解决异常
+ *
+ * @param type
+ * @since 2021-03-12
+ */
+ public static class MyTypeAdapterFactory implements TypeAdapterFactory {
+ @Override
+ public TypeAdapter create(Gson gs, TypeToken type) {
+ TypeAdapter stringNullAdapter = null;
+ Class rawType = (Class) type.getRawType();
+ if (rawType == String.class) {
+ stringNullAdapter = (TypeAdapter) new StringNullAdapter();
+ }
+ return stringNullAdapter;
+ }
+ }
+
+ /**
+ * StringNullAdapter
+ *
+ * @since 2021-03-12
+ */
+ public static class StringNullAdapter extends TypeAdapter {
+ @Override
+ public String read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+ reader.skipValue();
+ return "";
+ }
+ return reader.nextString();
+ }
+
+ @Override
+ public void write(JsonWriter writer, String value) throws IOException {
+ writer.value(value);
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0051055f9fd7094e0b070f32b79958d449c6923
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+import com.huawei.codelab.map.Const;
+
+import ohos.agp.utils.LayoutAlignment;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.app.Context;
+import ohos.app.dispatcher.TaskDispatcher;
+import ohos.app.dispatcher.task.TaskPriority;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 网络请求管理类
+ *
+ * @since 2021-03-12
+ */
+public class HttpUtils {
+ private static final String TAG = HttpUtils.class.getName();
+
+ private static final int TIME_OUT = 5 * 1000;
+
+ private static HttpUtils instance;
+
+ private Context context;
+
+ private TaskDispatcher globalTaskDispatcher;
+
+ /**
+ * 构造方法
+ *
+ * @param context context
+ */
+ private HttpUtils(Context context) {
+ this.context = context;
+ globalTaskDispatcher = context.getGlobalTaskDispatcher(TaskPriority.DEFAULT);
+ }
+
+ /**
+ * 获取NetworkManager单例对象
+ *
+ * @param context context
+ * @return NetworkManager
+ */
+ public static synchronized HttpUtils getInstance(Context context) {
+ if (instance == null) {
+ instance = new HttpUtils(context.getApplicationContext());
+ }
+ return instance;
+ }
+
+ /**
+ * get
+ *
+ * @param url url
+ * @param callback callback
+ */
+ public void get(String url, ResponseCallback callback) {
+ if (Const.MAP_KAY.isEmpty()) {
+ showError("MAP_KAY cannot be empty");
+ } else {
+ globalTaskDispatcher.asyncDispatch(() -> {
+ try {
+ doGet(url, callback);
+ } catch (IOException e) {
+ showError(e.getMessage());
+ }
+ });
+ }
+ }
+
+ /**
+ * get请求
+ *
+ * @param address request address
+ * @param callback response callback
+ * @throws IOException
+ */
+ private void doGet(String address, ResponseCallback callback) throws IOException {
+ InputStream inputStream = null;
+ InputStreamReader inputStreamReader = null;
+ BufferedReader bufferedReader = null;
+ try {
+ URL url = new URL(address);
+ URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(TIME_OUT);
+ inputStream = connection.getInputStream();
+ inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
+ bufferedReader = new BufferedReader(inputStreamReader);
+ String line;
+ StringBuilder stringBuilder = new StringBuilder(0);
+ while ((line = bufferedReader.readLine()) != null) {
+ stringBuilder.append(line);
+ }
+ String result = stringBuilder.toString();
+ LogUtils.info(TAG, "result:" + result);
+ context.getUITaskDispatcher().syncDispatch(() -> callback.onSuccess(result));
+ } catch (IOException e) {
+ showError(e.getMessage());
+ LogUtils.error(TAG, "doGet IOException:" + e.getMessage());
+ } finally {
+ if (bufferedReader != null) {
+ bufferedReader.close();
+ }
+ if (inputStreamReader != null) {
+ inputStreamReader.close();
+ }
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+ }
+
+ private void showError(String content) {
+ context.getUITaskDispatcher().asyncDispatch(new Runnable() {
+ @Override
+ public void run() {
+ ToastDialog toastDialog = new ToastDialog(context);
+ toastDialog.setAutoClosable(false);
+ toastDialog.setContentText(content);
+ toastDialog.setAlignment(LayoutAlignment.CENTER);
+ toastDialog.show();
+ }
+ });
+ }
+
+ /**
+ * 网络请求成功回调接口
+ *
+ * @since 2021-03-12
+ */
+ public interface ResponseCallback {
+ /**
+ * onSuccess
+ *
+ * @param result result
+ */
+ void onSuccess(String result);
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6b78c3abfd261babc65b4fe3b6b0ec2350712d5
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+import com.huawei.codelab.ResourceTable;
+import com.huawei.codelab.map.Const;
+
+import ohos.app.Context;
+import ohos.global.resource.NotExistException;
+import ohos.media.image.ImageSource;
+import ohos.media.image.PixelMap;
+import ohos.media.image.common.Size;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * MapHelper
+ *
+ * @since 2021-02-01
+ */
+public class ImageUtils {
+ private static final String TAG = ImageUtils.class.getName();
+
+ private static final int TILE_LENGTH = 513;
+
+ private static final int TIME_OUT = 5 * 1000;
+
+ private static final int IMAGE_WIDTH_HEIGHT = 80;
+
+ private ImageUtils() {
+ }
+
+ /**
+ * 获取图像id
+ *
+ * @param actionType actionType
+ * @return imageId
+ */
+ public static int getImageId(String actionType) {
+ int imageId = 0;
+ switch (actionType) {
+ case Const.ROUTE_STRAIGHT:
+ imageId = ResourceTable.Media_nav_straight;
+ break;
+ case Const.ROUTE_END:
+ imageId = ResourceTable.Media_route_end;
+ break;
+ case Const.ROUTE_START:
+ imageId = ResourceTable.Media_route_start;
+ break;
+ case Const.ROUTE_TURN_LEFT:
+ imageId = ResourceTable.Media_nav_turn_left;
+ break;
+ case Const.ROUTE_TURN_RIGHT:
+ imageId = ResourceTable.Media_nav_turn_right;
+ break;
+ case Const.ROUTE_LEFT_STRAIGHT:
+ imageId = ResourceTable.Media_nav_turn_little_left;
+ break;
+ case Const.ROUTE_RIGHT_STRAIGHT:
+ imageId = ResourceTable.Media_nav_turn_little_right;
+ break;
+ case Const.ROUTE_PEOPLE:
+ imageId = ResourceTable.Media_loc;
+ break;
+ default:
+ break;
+ }
+ return imageId;
+ }
+
+ /**
+ * getPixelMap
+ *
+ * @param context context
+ * @param actionType actionType
+ * @return PixelMap
+ */
+ public static PixelMap getPixelMap(Context context, String actionType) {
+ InputStream drawableInputStream = null;
+ PixelMap pixelMap = null;
+ try {
+ drawableInputStream = context.getResourceManager().getResource(ImageUtils.getImageId(actionType));
+ ImageSource imageSource = ImageSource.create(drawableInputStream, new ImageSource.SourceOptions());
+ ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
+ options.desiredSize = new Size(IMAGE_WIDTH_HEIGHT, IMAGE_WIDTH_HEIGHT);
+ pixelMap = imageSource.createPixelmap(options);
+ return pixelMap;
+ } catch (IOException | NotExistException exception) {
+ LogUtils.info(TAG, "getPixelMap:" + exception.getMessage());
+ } finally {
+ if (drawableInputStream != null) {
+ try {
+ drawableInputStream.close();
+ } catch (IOException e) {
+ LogUtils.info(TAG, "getPixelMap:" + e.getMessage());
+ }
+ }
+ }
+ return pixelMap;
+ }
+
+ /**
+ * 从网络获取地图瓦片数据
+ *
+ * @param urlString urlString
+ * @return PixelMap
+ */
+ public static PixelMap getMapPixelMap(String urlString) {
+ InputStream is = null;
+ PixelMap pixelMap = null;
+ try {
+ URL url = new URL(urlString);
+ URLConnection con = url.openConnection();
+ con.setConnectTimeout(TIME_OUT);
+ is = con.getInputStream();
+ ImageSource source = ImageSource.create(is, new ImageSource.SourceOptions());
+ ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
+ options.desiredSize = new Size(TILE_LENGTH, TILE_LENGTH);
+ pixelMap = source.createPixelmap(options);
+ return pixelMap;
+ } catch (IOException exception) {
+ LogUtils.info(TAG, "getImagePixelMap:" + exception.getMessage());
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ LogUtils.info(TAG, "getImagePixelMap:" + e.getMessage());
+ }
+ }
+ }
+ return pixelMap;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..56cbbd498e01e3a8d105590459e0d04ca2eca31a
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+
+/**
+ * LogUtils
+ *
+ * @since 2021-03-12
+ */
+public class LogUtils {
+ private static final String TAG_LOG = "LogUtil";
+
+ private static final HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, LogUtils.TAG_LOG);
+
+ private static final String LOG_FORMAT = "%{public}s: %{public}s";
+
+ private LogUtils() {
+ }
+
+ /**
+ * 打印info日志
+ *
+ * @param tag log tag
+ * @param msg log message
+ */
+ public static void info(String tag, String msg) {
+ HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg);
+ }
+
+ /**
+ * 打印error日志
+ *
+ * @param tag log tag
+ * @param msg log message
+ */
+ public static void error(String tag, String msg) {
+ HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg);
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..a79ba29de84fb93c4ed2c996c1c85fe3aead04b4
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+/**
+ * 地图工具类
+ *
+ * @since 2021-04-01
+ */
+public class MapUtils {
+ private static final double OVER_LENGTH = 20037508.3427892;
+
+ private static final int PARAM_NUM = 2;
+
+ private static final int NUM_90 = 90;
+
+ private static final int NUM_180 = 180;
+
+ private static final int NUM_360 = 360;
+
+ private MapUtils() {
+ }
+
+ /**
+ * Latitude and longitude Mercator to Mercator
+ *
+ * @param lon longitude
+ * @param lat Latitude
+ * @return Mercator
+ */
+ public static double[] lonLat2Mercator(double lon, double lat) {
+ double[] mercators = new double[PARAM_NUM];
+ double mercatorX = lon * OVER_LENGTH / NUM_180;
+ double mercatorY = Math.log(Math.tan((NUM_90 + lat) * Math.PI / NUM_360)) / (Math.PI / NUM_180);
+ mercatorY = mercatorY * OVER_LENGTH / NUM_180;
+ mercators[0] = mercatorX;
+ mercators[1] = mercatorY;
+ return mercators;
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..37376ecef71015b4f620fed6f83081544d1bb7aa
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+import ohos.app.Context;
+import ohos.bundle.IBundleManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * PermissionsUtils
+ *
+ * @since 2021-03-12
+ */
+public class PermissionsUtils {
+ private static final String TAG = PermissionsUtils.class.getName();
+
+ private static final int PERMISSION_REQUEST_CODE = 1;
+
+ private static PermissionsUtils permissionsUtils;
+
+ private RequestListener requestListener;
+
+ private PermissionsUtils() {
+ }
+
+ /**
+ * 获取PermissionsUtils单例
+ *
+ * @return PermissionsUtils
+ */
+ public static synchronized PermissionsUtils getInstance() {
+ if (permissionsUtils == null) {
+ permissionsUtils = new PermissionsUtils();
+ }
+ return permissionsUtils;
+ }
+
+ /**
+ * requestPermissions
+ *
+ * @param context context
+ * @param permissions 需要申请的权限集合
+ */
+ public void requestPermissions(Context context, String[] permissions) {
+ List applyPermissions = new ArrayList<>(0);
+ for (String element : permissions) {
+ if (context.verifySelfPermission(element) != IBundleManager.PERMISSION_GRANTED) {
+ if (context.canRequestPermission(element)) {
+ applyPermissions.add(element);
+ }
+ }
+ }
+
+ if (!applyPermissions.isEmpty()) {
+ context.requestPermissionsFromUser(applyPermissions.toArray(new String[0]), PERMISSION_REQUEST_CODE);
+ }
+ }
+
+ public void setRequestListener(RequestListener requestListener) {
+ this.requestListener = requestListener;
+ }
+
+ /**
+ * 在MainAbility中的onRequestPermissionsFromUserResult方法会调用此方法
+ *
+ * @param requestCode requestCode
+ * @param permissions permissions
+ * @param grantResults grantResults
+ */
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if (requestCode != PERMISSION_REQUEST_CODE) {
+ return;
+ }
+ for (int i = 0; i < grantResults.length; i++) {
+ if (grantResults[i] == IBundleManager.PERMISSION_GRANTED) {
+ requestListener.permissionGranted(permissions[i]);
+ } else {
+ LogUtils.info(TAG, "user deny permission:" + permissions[i]);
+ }
+ }
+ }
+
+ /**
+ * 权限申请结果回调
+ *
+ * @since 2021-03-12
+ */
+ public interface RequestListener {
+ /**
+ * permissionGranted
+ *
+ * @param permission 类型为string
+ */
+ void permissionGranted(String permission);
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c7fb462da3f9f609b6b7d1c32fb2d81698f000c
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package com.huawei.codelab.util;
+
+import ohos.agp.utils.Point;
+import ohos.agp.window.service.Display;
+import ohos.agp.window.service.DisplayManager;
+import ohos.app.Context;
+
+import java.util.Optional;
+
+/**
+ * ScreenUtils
+ *
+ * @since 2021-03-12
+ */
+public class ScreenUtils {
+ private ScreenUtils() {
+ }
+
+ /**
+ * 获取屏幕高度
+ *
+ * @param context context
+ * @return 类型为int
+ */
+ public static int getScreenHeight(Context context) {
+ DisplayManager displayManager = DisplayManager.getInstance();
+ Optional optDisplay = displayManager.getDefaultDisplay(context);
+ Point point = new Point(0, 0);
+ if (!optDisplay.isPresent()) {
+ return (int) point.position[1];
+ } else {
+ Display display = optDisplay.get();
+ display.getSize(point);
+ return (int) point.position[1];
+ }
+ }
+
+ /**
+ * 获取屏幕宽度
+ *
+ * @param context context
+ * @return 类型为int
+ */
+ public static int getScreenWidth(Context context) {
+ DisplayManager displayManager = DisplayManager.getInstance();
+ Optional optDisplay = displayManager.getDefaultDisplay(context);
+ Point point = new Point(0, 0);
+ if (!optDisplay.isPresent()) {
+ return (int) point.position[0];
+ } else {
+ Display display = optDisplay.get();
+ display.getSize(point);
+ return (int) point.position[0];
+ }
+ }
+}
diff --git a/DistributedMapDemo/entry/src/main/resources/base/element/string.json b/DistributedMapDemo/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..b22c94dead8081154457544aece9ec62ad180ebf
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,28 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "DistributedMapDemo"
+ },
+ {
+ "name": "mainability_description",
+ "value": "Java_Phone_Empty Feature Ability"
+ },
+ {
+ "name": "watchservice_description",
+ "value": "hap sample empty service"
+ },
+ {
+ "name": "watchmainability_description",
+ "value": "Java_Phone_Empty Feature Ability"
+ },
+ {
+ "name": "carmainability_description",
+ "value": "Java_Phone_Empty Feature Ability"
+ },
+ {
+ "name": "reason_description",
+ "value": "need request location permission"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card.xml b/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10b1db709c0adba978a3122de6344690a7a9d16e
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card_gray.xml b/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card_gray.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1876763dffbb46788d3630200b6bb7fd8aee4b56
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/graphic/background_card_gray.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/graphic/button_bg.xml b/DistributedMapDemo/entry/src/main/resources/base/graphic/button_bg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fc76bf46a611296dd98893e268510d0940932946
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/graphic/button_bg.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/layout/ability_main.xml b/DistributedMapDemo/entry/src/main/resources/base/layout/ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..78479b169b866959c7f77bfe15718fecf6a23015
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/layout/ability_main.xml
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/layout/ability_watch_main.xml b/DistributedMapDemo/entry/src/main/resources/base/layout/ability_watch_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1c728b475f57044b2b803f303d0fe1dad879008
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/layout/ability_watch_main.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/layout/item_input_tips.xml b/DistributedMapDemo/entry/src/main/resources/base/layout/item_input_tips.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8dc50d881ab8f5f30a595e5594ae3b047d01c3cf
--- /dev/null
+++ b/DistributedMapDemo/entry/src/main/resources/base/layout/item_input_tips.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/icon.png b/DistributedMapDemo/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/icon.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/loc.png b/DistributedMapDemo/entry/src/main/resources/base/media/loc.png
new file mode 100644
index 0000000000000000000000000000000000000000..74ead4cdf5c1971d8880b4d2759e37f18adc476c
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/loc.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/nav_straight.png b/DistributedMapDemo/entry/src/main/resources/base/media/nav_straight.png
new file mode 100644
index 0000000000000000000000000000000000000000..3aa37c27bf0f700b8077162b6007f555ea0cff48
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/nav_straight.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_left.png b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_left.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9a2740e0e41c166e1086fc5d83f4f6feedeb699
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_left.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_left.png b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_left.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b1f8bdd9668cafa05bd15d210957b0161d037ca
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_left.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_right.png b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..a86b74605cc914b6844237f9d8814717cae9c50b
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_little_right.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_right.png b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_right.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e896a829b2165bf0f0f638b78040a6fab0e4c12
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/nav_turn_right.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/route_end.png b/DistributedMapDemo/entry/src/main/resources/base/media/route_end.png
new file mode 100644
index 0000000000000000000000000000000000000000..1522c6825fe4ea80016bb88e111c5890c5dbbd92
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/route_end.png differ
diff --git a/DistributedMapDemo/entry/src/main/resources/base/media/route_start.png b/DistributedMapDemo/entry/src/main/resources/base/media/route_start.png
new file mode 100644
index 0000000000000000000000000000000000000000..9bf16b9750174019b511a313ecc6e3a62f16a5d1
Binary files /dev/null and b/DistributedMapDemo/entry/src/main/resources/base/media/route_start.png differ
diff --git a/DistributedMapDemo/gradle/wrapper/gradle-wrapper.jar b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9
Binary files /dev/null and b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..6623300bebd011bc5f7991f4f9c389e2f67b14ac
--- /dev/null
+++ b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/DistributedMapDemo/settings.gradle b/DistributedMapDemo/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..4773db73233a570c2d0c01a22e75321acfbf7a07
--- /dev/null
+++ b/DistributedMapDemo/settings.gradle
@@ -0,0 +1 @@
+include ':entry'
diff --git a/README.md b/README.md
index 8374a204a9ecc2ac46899a4cc6eda5b4392d104b..804673f9f69bb73572a77fc290028a59b397f314 100644
--- a/README.md
+++ b/README.md
@@ -23,3 +23,7 @@ JSPlaygroundDemo:利用HarmonyOS“一次开发、多端部署”特性,开
RemoteInputDemo:展示了通过手机输入文字到电视的跨设备输入能力,链接:https://gitee.com/openharmony/codelabs/tree/master/RemoteInputDemo-master
DistributionGamePad:分布式游戏手柄,可以通过手机端跨设备控制电视上的飞机游戏,链接:https://gitee.com/openharmony/codelabs/tree/master/DistributionGamePad-master
+
+AudioDemo:音频播放相关管理应用包括音频播放、声音采集和音频相关管理(快进、快退、暂停、播放、音量控制)等功能,链接:https://gitee.com/openharmony/codelabs/tree/master/AudioDemo
+
+DistributedMapDemo:展示简单的HarmonyOS分布式功能,可以通过应用程序模拟导航,在手机、智能穿戴和平板电脑之间进行导航数据流转,链接:https://gitee.com/openharmony/codelabs/tree/master/DistributedMapDemo