diff --git a/VideoProcessBaseWeb/entry/src/main/ets/pages/Index.ets b/VideoProcessBaseWeb/entry/src/main/ets/pages/Index.ets index 8e776219502349470706f0b61849fe420a0bacc7..01ebfb4269ae428f2f75853f12e57c0f1e44de9b 100644 --- a/VideoProcessBaseWeb/entry/src/main/ets/pages/Index.ets +++ b/VideoProcessBaseWeb/entry/src/main/ets/pages/Index.ets @@ -16,13 +16,16 @@ import { webview } from '@kit.ArkWeb'; import { common } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; import { AlertDialog, ComponentContent, promptAction, window } from '@kit.ArkUI'; import { Constants } from '../common/Constants'; import { WebDownloadManager } from '../utils/WebDownloadManager'; import { downloadControlBuilder } from '../view/DownloadControlView'; import { customPopupMenuBuilder, getOffset } from '../view/CustomPopupMenu'; + const uiContext: UIContext | undefined = AppStorage.get('uiContext'); let context = uiContext!.getHostContext() + // [Start index] // [Start is_full] // [Start bind_pop] @@ -93,14 +96,21 @@ struct Index { }) }); private openDownloadDialog = () => { - this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options); + this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options).catch((error: BusinessError) => { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + }); }; private closeDownloadDialog = () => { - this.ctx.getPromptAction().closeCustomDialog(this.contentNode); + this.ctx.getPromptAction().closeCustomDialog(this.contentNode).catch((error: BusinessError) => { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + }); }; private changeIsShow = () => { this.isShow = !this.isShow; }; + // [Start index] aboutToAppear(): void { window.getLastWindow(this.context).then((windowClass) => this.windowClass = windowClass); @@ -110,6 +120,7 @@ struct Index { hilog.info(0x000, Constants.TAG, 'language: ' + this.language); // [EndExclude index] } + /** * Changes the preferred orientation of the window. * @@ -119,6 +130,7 @@ struct Index { changeOrientation(orientation: window.Orientation) { this.windowClass?.setPreferredOrientation(orientation); } + // [End index] // [Start on_back_press] onBackPress(): boolean | void { @@ -128,6 +140,7 @@ struct Index { } return false; } + // [End on_back_press] // [Start index] // [EndExclude is_full] @@ -143,11 +156,11 @@ struct Index { src: $rawfile(/zh/.test(this.language) ? 'index_cn.html' : 'index_en.html'), controller: this.webController }) - // [StartExclude is_full] - // [StartExclude raw_file] - // [StartExclude bind_pop] - // [StartExclude is_show1] - // [StartExclude component] + // [StartExclude is_full] + // [StartExclude raw_file] + // [StartExclude bind_pop] + // [StartExclude is_show1] + // [StartExclude component] .zoomAccess(false) .width('100%') .height('100%') @@ -155,8 +168,8 @@ struct Index { this.webWidth = newArea.width as number; this.webHeight = newArea.height as number; }) - // [EndExclude is_show1] - // [EndExclude component] + // [EndExclude is_show1] + // [EndExclude component] .onContextMenuShow((event) => { if (!event) { return false; @@ -172,10 +185,10 @@ struct Index { this.isShow = true; return true; }) - // [EndExclude bind_pop] - // [Start bind_pop] - // [StartExclude is_show1] - // [StartExclude component] + // [EndExclude bind_pop] + // [Start bind_pop] + // [StartExclude is_show1] + // [StartExclude component] .bindPopup(this.isShow, { builder: customPopupMenuBuilder( this.linkUrl, @@ -195,15 +208,15 @@ struct Index { } } }) - // [End bind_pop] - // [StartExclude bind_pop] - // [EndExclude is_full] + // [End bind_pop] + // [StartExclude bind_pop] + // [EndExclude is_full] .onFullScreenEnter((event) => { this.handler = event.handler; this.changeOrientation(window.Orientation.LANDSCAPE); this.isFullScreen = true; }) - // [EndExclude raw_file] + // [EndExclude raw_file] .onFullScreenExit(() => { this.changeOrientation(window.Orientation.PORTRAIT); this.isFullScreen = false; diff --git a/VideoProcessBaseWeb/entry/src/main/ets/utils/CustomFunction.ets b/VideoProcessBaseWeb/entry/src/main/ets/utils/CustomFunction.ets index 95260527cf42c06b2257cce4fa2e25b378886927..6a3dcf2309cf217c3b9b46c31ce435c5b1e0ece8 100644 --- a/VideoProcessBaseWeb/entry/src/main/ets/utils/CustomFunction.ets +++ b/VideoProcessBaseWeb/entry/src/main/ets/utils/CustomFunction.ets @@ -14,7 +14,6 @@ */ import { common, Want } from '@kit.AbilityKit'; -import { promptAction } from '@kit.ArkUI'; import { pasteboard } from '@kit.BasicServicesKit'; import { fileIo as fs, picker } from '@kit.CoreFileKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; @@ -64,27 +63,32 @@ export async function saveVideoToGallery( documentSaveOptions.newFileNames = ['video.mp4']; let documentPicker = new picker.DocumentViewPicker(context); documentPicker.save(documentSaveOptions).then(async (uris: Array) => { - if (uris.length === 0) { - context1.showToast({ message: $r('app.string.user_cancelled_authorization') }) - return; - } - openDownloadDialog(); // open dialog - const path = await webDownloadManager.start(Constants.INDEX_WEB_CONTROLLER, context.filesDir, uri); - closeDownloadDialog(); // close dialog - webDownloadManager.clearProgress(); - context1.showToast({ message: $r('app.string.download_success') }) - const targetFile = fs.openSync(uris[0], fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); - const sourceFile = fs.openSync(path, fs.OpenMode.READ_ONLY); - let buf = new ArrayBuffer(1024); - while (true) { - const len = fs.readSync(sourceFile.fd, buf); - if (0 === len) { - break; + try { + if (uris.length === 0) { + context1.showToast({ message: $r('app.string.user_cancelled_authorization') }) + return; + } + openDownloadDialog(); // open dialog + const path = await webDownloadManager.start(Constants.INDEX_WEB_CONTROLLER, context.filesDir, uri); + closeDownloadDialog(); // close dialog + webDownloadManager.clearProgress(); + context1.showToast({ message: $r('app.string.download_success') }) + const targetFile = fs.openSync(uris[0], fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + const sourceFile = fs.openSync(path, fs.OpenMode.READ_ONLY); + let buf = new ArrayBuffer(1024); + while (true) { + const len = fs.readSync(sourceFile.fd, buf); + if (0 === len) { + break; + } + fs.writeSync(targetFile.fd, buf); } - fs.writeSync(targetFile.fd, buf); + fs.closeSync(sourceFile); + fs.closeSync(targetFile); + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); } - fs.closeSync(sourceFile); - fs.closeSync(targetFile); }).finally(() => { webDownloadManager.deleteFile(); }) diff --git a/VideoProcessBaseWeb/entry/src/main/ets/utils/WebDownloadManager.ets b/VideoProcessBaseWeb/entry/src/main/ets/utils/WebDownloadManager.ets index 13390fa04508d6ec96f6e82dc9056a1424cc25e4..c9cf737edb53bd3a20756f38daff0cc4766c8f9e 100644 --- a/VideoProcessBaseWeb/entry/src/main/ets/utils/WebDownloadManager.ets +++ b/VideoProcessBaseWeb/entry/src/main/ets/utils/WebDownloadManager.ets @@ -16,6 +16,7 @@ import { webview } from '@kit.ArkWeb'; import { fileIo } from '@kit.CoreFileKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; import { Constants } from '../common/Constants'; interface ControllerManager { @@ -50,6 +51,7 @@ implements ControllerManager { // [EndExclude manage] // Define the download delegate instance. private delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate(); + // [StartExclude manage] private constructor() { super() @@ -61,6 +63,7 @@ implements ControllerManager { } return WebDownloadManager.instance; } + // [EndExclude manage] public start(controllerName: string, path: string, url: string): Promise { return new Promise((resolve, reject) => { @@ -98,28 +101,44 @@ implements ControllerManager { resolve(this.sourcePath); }) // [End finish1] - // [EndExclude manage] - // Associate the download delegate with the webview controller. - controller?.setDownloadDelegate(this.delegate); - // [StartExclude manage] - // [Start url2] - controller?.startDownload(url); - // [End url2] - // [EndExclude manage] + try { + // [EndExclude manage] + // Associate the download delegate with the webview controller. + controller?.setDownloadDelegate(this.delegate); + // [StartExclude manage] + // [Start url2] + controller?.startDownload(url); + // [End url2] + // [EndExclude manage] + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } }); } + // [StartExclude manage] public pause() { const state = this.currentTask.getState(); if (state === webview.WebDownloadState.IN_PROGRESS) { - this.currentTask.pause(); + try { + this.currentTask.pause(); + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } } } public unpause() { const state = this.currentTask.getState(); if (state === webview.WebDownloadState.PAUSED) { - this.currentTask.resume(); + try { + this.currentTask.resume(); + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } } } // [Start resume] @@ -128,7 +147,12 @@ implements ControllerManager { const state = this.currentTask.getState(); if (state === webview.WebDownloadState.CANCELED) { webview.WebDownloadManager.setDownloadDelegate(this.delegate); - webview.WebDownloadManager.resumeDownload(webview.WebDownloadItem.deserialize(this.failedData)); + try { + webview.WebDownloadManager.resumeDownload(webview.WebDownloadItem.deserialize(this.failedData)); + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } } } // [End resume] @@ -149,8 +173,16 @@ implements ControllerManager { } public deleteFile() { - if (fileIo.accessSync(this.sourcePath)) { - fileIo.unlink(this.sourcePath); + try { + if (fileIo.accessSync(this.sourcePath)) { + fileIo.unlink(this.sourcePath).catch((error: BusinessError) => { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + }); + } + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); } } diff --git a/WebApplicationJump/AppScope/app.json5 b/WebApplicationJump/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..20a4d63d8235dea45c7df1a11b1bc9aba03af32c --- /dev/null +++ b/WebApplicationJump/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.huawei.webapplicationjump", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/WebApplicationJump/AppScope/resources/base/element/string.json b/WebApplicationJump/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..aa43a4efa63bf16ee5e5d467b39c7ce527388329 --- /dev/null +++ b/WebApplicationJump/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "WebApplicationJump" + } + ] +} diff --git a/WebApplicationJump/AppScope/resources/base/media/app_icon.png b/WebApplicationJump/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/WebApplicationJump/AppScope/resources/base/media/app_icon.png differ diff --git a/WebApplicationJump/LICENSE b/WebApplicationJump/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..338e5b0bc22082e0ffcc7121c2ed3897a3ddccb0 --- /dev/null +++ b/WebApplicationJump/LICENSE @@ -0,0 +1,78 @@ + Copyright (c) 2024 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/WebApplicationJump/README.md b/WebApplicationJump/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6038564dab575908b6300f8e48a5edd2c0890fd0 --- /dev/null +++ b/WebApplicationJump/README.md @@ -0,0 +1,53 @@ +# 基于应用拉起相关能力实现Web跳转功能 + +## 介绍 + +本示例基于应用拉起相关能力,实现了Web页面与ArkTS页面的相互拉起、从Web页面拉起各类应用、以及拉起应用市场详情页等场景。 + +## 效果预览 +手机运行效果图如下: + +![](./screenshots/device/phone.png) + + +## 工程目录结构 + +``` +├──entry/src/main/ets // 代码区 +│ ├──common +│ | ├──Logger.ets // 日志工具类 +│ | └──Constants.ets // 常量 +│ ├──entryability +│ | └──EntryAbility.ets +│ ├──entrybackupability +│ | └──EntryBackupAbility.ets +│ └──pages +│ ├──Index.ets // 入口界面 +│ └──OriginPage.ets // 原生页面 +└──entry/src/main/resources // 应用资源目录 +``` + +## 具体实现 + +从Web页面拉起原生页面需要在Web组件的onLoadIntercept拦截器拦截页面加载,并使用Navigation提供的组件路由能力跳转到原生的页面。 + +从Web页面拉起另外的Web页面,只需要在前端侧使用a标签配置href属性,即可实现从Web页面跳转到其他的Web页面。 + +从Web页面拉起三方应用,首先同样需要在Web组件的onLoadIntercept中进行拦截,然后执行自定义的拉起逻辑,在拉起之前,需要首先对三方应用进行配置,配置三方应用的module.json5文件中的exported属性为true,同时需要在skills属性中配置entities与actions。最后在拉起方应用内使用隐式拉起的方式,配置Want类型的配置参数,其中action配置为之前在被拉起方中的actions,同时配置entities属性也为被拉起方中的entities,最后使用startAbility进行拉起。即可在不指定bundleName的情况下拉起应用。在本项目中,您需要先安装配套的dependence目录下的PulledUpApplication应用,避免拉起三方应用时拉起失败,也可以在下载本项目后自行配置拉起参数,从而拉起其他的三方应用。 + +从Web页面拉起系统应用,同样的要在onLoadIntercept中进行拦截,然后可以使用配置Want参数为对应系统应用的配置,然后使用startAbility进行拉起,也可以使用具体场景中系统提供的Picker与API接口。 + +从Web页面跳转到市场详情页,开发者需要首先在onLoadIntercept中进行拦截,然后使用Store Kit中的应用市场推荐功能,该功能提供了loadProduct接口可以加载应用市场详情页。 + +从Web页面拉起其他设备的该应用,首先需要在onLoadIntercept中进行拦截,然后使用getAvailableDeviceListSync获取到可信设备列表,最后通过设置want参数中的deviceId进行应用拉起,注意该场景需要开发者多端设备登录同一华为账号、连接同一Wi-Fi、打开蓝牙连接。 + +## 相关权限 + +* DISTRIBUTED_DATASYNC:允许不同设备间的数据交换。 + +## 约束与限制 + +1. 本示例仅支持标准系统上运行,支持设备:华为手机。 +2. HarmonyOS系统:HarmonyOS 5.0.5 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.0.5 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.0.5 Release SDK及以上。 \ No newline at end of file diff --git a/WebApplicationJump/README_EN.md b/WebApplicationJump/README_EN.md new file mode 100644 index 0000000000000000000000000000000000000000..3a23c67503d264d717216bc09470de9de7aab60a --- /dev/null +++ b/WebApplicationJump/README_EN.md @@ -0,0 +1,53 @@ +# Jumping Between Webs and Applications + +## Overview + +Based on the application startup capabilities, this sample implements scenarios such as jumping between the web page and ArkTS page, jumping to applications and details page in AppGallery from the web page. + +## Preview +The following figure shows the running effect on a mobile phone. + +![](./screenshots/device/phone_EN.png) + + +## Project Directory + +``` +├──entry/src/main/ets // Code area +│ ├──common +│ │ ├──Logger.ets // Logger +│ | └──Constants.ets // Constants +│ ├──entryability +│ | └──EntryAbility.ets +│ ├──entrybackupability +│ | └──EntryBackupAbility.ets +│ └──pages +│ ├──Index.ets // Entry page +│ └──OriginPage.ets // Origin page +└──entry/src/main/resources // App resource directory +``` + +## How to Implement + +To start a native page from a web page, you need to intercept page loading using the interceptor **onLoadIntercept** of the **Web** component and use the routing capability of the **Navigation** component. + +To start another web page from a web page, you only need to configure the **a** tag with the **href** property on the frontend. + +To start a third-party application from the web page, you need to intercept the page loading using **onLoadIntercept** of the **Web** component and then execute the custom startup logic. Before starting the third-party application, you need to set the **exported** property of the **module.json5** file of the third-party application to **true**. In addition, you need to configure **entities** and **actions** in the **skills** property. Use the implicit startup mode in the application and configure the parameters of the **Want** type. The **action** and **entities** parameters specify the actions and entities of the application to be started respectively. Then, use **startAbility** to start the application. In this way, the application can be started without specifying the bundle name. To start the third-party application successfully, you need to install **PulledUpApplication** in the **dependence** directory. You can also download this project and set the startup parameters to start a third-party application. + +To start a system application from the web page, you need to intercept the page loading using **onLoadIntercept**. Then, you can set the parameters of **Want** to the configuration of the corresponding system application, and use **startAbility** to start the system application. In addition, the system application can also be started using the **Picker** and APIs provided by the system in a specific scenario. + +To jump from a web page to the details page in AppGallery, you need to intercept the page loading using **onLoadIntercept** and then use the AppGallery recommendation function of Store Kit. This function provides the **loadProduct** API to load the details page on AppGallery. + +To start an application on another device from the web page, you need to intercept the page loading using **onLoadIntercept**, use **getAvailableDeviceListSync** to obtain the list of trusted devices, and set the **deviceId** parameter of **want**. In this case, note that you need to log in to the same HUAWEI ID on multiple devices, connect to the same Wi-Fi network, and enable Bluetooth. + +## Required Permissions + +* **DISTRIBUTED_DATASYNC**, which allows data to be exchanged between devices. + +## Constraints + +1. The sample app is supported only on Huawei phones running the standard system. +2. The HarmonyOS version must be HarmonyOS 5.0.5 Release or later. +3. The DevEco Studio version must be DevEco Studio 5.0.5 Release or later. +4. The HarmonyOS SDK version must be HarmonyOS 5.0.5 Release SDK or later. diff --git a/WebApplicationJump/build-profile.json5 b/WebApplicationJump/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b2ca56e35558b0dc7ca91989b68a1ea65b49a7a2 --- /dev/null +++ b/WebApplicationJump/build-profile.json5 @@ -0,0 +1,36 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.5(17)", + "targetSdkVersion": "5.0.5(17)", + "runtimeOS": "HarmonyOS", + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/AppScope/app.json5 b/WebApplicationJump/dependence/PulledUpApplication/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b5d0c7543d4b2b0d74797b5e0d7fe84e3e471e95 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.huawei.pulledupapplication", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/element/string.json b/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..76ffdf7b4d21b8022e4cd1caec724ea24c5d875f --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "PulledUpApplication" + } + ] +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/media/app_icon.png b/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/WebApplicationJump/dependence/PulledUpApplication/AppScope/resources/base/media/app_icon.png differ diff --git a/WebApplicationJump/dependence/PulledUpApplication/build-profile.json5 b/WebApplicationJump/dependence/PulledUpApplication/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c033ce4278fb0641d84107c3c134047ac487368e --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/build-profile.json5 @@ -0,0 +1,35 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS", + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/build-profile.json5 b/WebApplicationJump/dependence/PulledUpApplication/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b695582d3680556f4cce2ec518f65720a9413ca3 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/hvigorfile.ts b/WebApplicationJump/dependence/PulledUpApplication/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/obfuscation-rules.txt b/WebApplicationJump/dependence/PulledUpApplication/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..69c4d6a8a5531548e4886fa766090c5c157a87d9 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/obfuscation-rules.txt @@ -0,0 +1,18 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/oh-package.json5 b/WebApplicationJump/dependence/PulledUpApplication/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entryability/EntryAbility.ets b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..8335b7692d4cac1f8b5d78ce7bc1c45a453d563e --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,41 @@ +import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..dc55c03d3eea7ce53d5346c732a39ce9bf5267e1 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,12 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/pages/Index.ets b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..9393e00f3990f2da833746e03f7fc066e15766bc --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,20 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + RelativeContainer() { + Text(this.message) + .id('HelloWorld') + .fontSize(50) + .fontWeight(FontWeight.Bold) + .alignRules({ + center: { anchor: '__container__', align: VerticalAlign.Center }, + middle: { anchor: '__container__', align: HorizontalAlign.Center } + }) + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/module.json5 b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..aa0ca22fb3a9aa6b1c18db03ef8f3bc14dbf18fa --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/module.json5 @@ -0,0 +1,76 @@ +// [Start deep_link_json] +{ + "module": { + // [StartExclude deep_link_json] + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + // [EndExclude deep_link_json] + "abilities": [ + { + // [StartExclude deep_link_json] + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + // [EndExclude deep_link_json] + "skills": [ + // [StartExclude deep_link_json] + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + }, + // [EndExclude deep_link_json] + { + "entities": [ + "entity.system.browsable" + ], + "actions": [ + "ohos.want.action.viewData" + ], + "uris": [ + { + "scheme": "appScheme", + "host": "www.test.com", + "port": "80", + "path": "path1" + } + ] + } + ] + } + ], + // [StartExclude deep_link_json] + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ], + // [EndExclude deep_link_json] + } +} +// [End deep_link_json] \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/color.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/string.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..0b6525cdfce587c049be40ffb167336c16f8a205 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "被拉起应用" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/background.png b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/background.png differ diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/foreground.png b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/foreground.png differ diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/layered_image.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/startIcon.png b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/media/startIcon.png differ diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/backup_config.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/main_pages.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/en_US/element/string.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..bbb394e5aa0a4bc76734195a10e168f3f33644b8 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "PulledUpApplication" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/zh_CN/element/string.json b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..609042cb24470e48b5e81554f6862f4715708655 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "被拉起应用" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/dependence/PulledUpApplication/hvigor/hvigor-config.json5 b/WebApplicationJump/dependence/PulledUpApplication/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..06b2783670a348f95533b352c1ceda909a842bbc --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/hvigorfile.ts b/WebApplicationJump/dependence/PulledUpApplication/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/WebApplicationJump/dependence/PulledUpApplication/oh-package.json5 b/WebApplicationJump/dependence/PulledUpApplication/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8bf916d4a165e0466c65bc49f58ab2e3c27e8931 --- /dev/null +++ b/WebApplicationJump/dependence/PulledUpApplication/oh-package.json5 @@ -0,0 +1,8 @@ +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + } +} diff --git a/WebApplicationJump/entry/build-profile.json5 b/WebApplicationJump/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..b695582d3680556f4cce2ec518f65720a9413ca3 --- /dev/null +++ b/WebApplicationJump/entry/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/hvigorfile.ts b/WebApplicationJump/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3 --- /dev/null +++ b/WebApplicationJump/entry/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/WebApplicationJump/entry/obfuscation-rules.txt b/WebApplicationJump/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1dfa0bd175984dc49e641436aa67b1de1b8abeb --- /dev/null +++ b/WebApplicationJump/entry/obfuscation-rules.txt @@ -0,0 +1,22 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/WebApplicationJump/entry/oh-package.json5 b/WebApplicationJump/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a --- /dev/null +++ b/WebApplicationJump/entry/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/WebApplicationJump/entry/src/main/ets/common/Constants.ets b/WebApplicationJump/entry/src/main/ets/common/Constants.ets new file mode 100644 index 0000000000000000000000000000000000000000..dfe64f568cae7f9e83cf3ae0522e18a34dc68b6f --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/common/Constants.ets @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Constants { + /** + * Original page router name. + */ + static readonly ORIGIN_PAGE: string = 'OriginPage'; + + /** + * Full Screen Size. + */ + static readonly FULL_SCREEN: string = '100%'; + + /** + * Web page router name. + */ + static readonly WEB_PAGE: string = 'WebPage'; + + /** + * Original page router chinese name. + */ + static readonly ORIGIN_PAGE_CHINESE: string = '原生页面'; + + /** + * Web page router chinese name. + */ + static readonly WEB_PAGE_CHINESE: string = 'Web页面'; + /** + * Original web page link. + */ + static readonly ORIGIN_WEB_PAGE_LINK: string = 'resource://rawfile/index.html'; + + /** + * Original web page link. + */ + static readonly WEB_PAGE_ADDRESS: string = 'resource://rawfile/index1.html'; + + static readonly SYSTEM_LANGUAGE_KEY: string = 'systemLanguage'; + static readonly CHINESE_LANGUAGE: string = 'zh-Hans-CN'; + static readonly ENGLISH_LANGUAGE: string = 'en-Latn-CN'; +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/common/Logger.ets b/WebApplicationJump/entry/src/main/ets/common/Logger.ets new file mode 100644 index 0000000000000000000000000000000000000000..a31d0a012cdd1dde65d794c5f120e138b8f3549f --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/common/Logger.ets @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +export class Logger { + private static domain: number = 0x0000; + private static prefix: string = 'WebPullOtherApplication'; + private static format: string = '%{public}s, %{public}s'; + + static debug(...args: string[]): void { + hilog.debug(Logger.domain, Logger.prefix, Logger.format, args); + } + + static info(...args: string[]): void { + hilog.info(Logger.domain, Logger.prefix, Logger.format, args); + } + + static warn(...args: string[]): void { + hilog.warn(Logger.domain, Logger.prefix, Logger.format, args); + } + + static error(...args: string[]): void { + hilog.error(Logger.domain, Logger.prefix, Logger.format, args); + } +} diff --git a/WebApplicationJump/entry/src/main/ets/entryability/EntryAbility.ets b/WebApplicationJump/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4d51dbd0d15479604343a3b2d09369b8438c901f --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + abilityAccessCtrl, + AbilityConstant, + bundleManager, + Configuration, + Permissions, + UIAbility, + Want +} from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; +import { Constants } from '../common/Constants'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.checkPermissions(); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + AppStorage.setOrCreate(Constants.SYSTEM_LANGUAGE_KEY, this.context.config.language); + console.log(`language is ${this.context.config.language}`) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } + + onConfigurationUpdate(newConfig: Configuration): void { + if (AppStorage.get(Constants.SYSTEM_LANGUAGE_KEY) !== newConfig.language) { + AppStorage.setOrCreate(Constants.SYSTEM_LANGUAGE_KEY, newConfig.language) + + } + } + + + async checkPermissions(): Promise { + const permissions: Array = ["ohos.permission.DISTRIBUTED_DATASYNC"]; + const accessManager = abilityAccessCtrl.createAtManager(); + try { + const bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; + const bundleInfo = await bundleManager.getBundleInfoForSelf(bundleFlags); + const grantStatus = await accessManager.checkAccessToken(bundleInfo.appInfo.accessTokenId, permissions[0]); + + if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) { + accessManager.requestPermissionsFromUser(this.context, permissions) + } + } catch (err) { + // ... + } + } +} diff --git a/WebApplicationJump/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/WebApplicationJump/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..6b744d7eaa66e51e79fc4e0896e251292ee767c5 --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/Index.ets b/WebApplicationJump/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..fd1dd1e214969f37331ef96a914385ede01db02a --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { webview } from '@kit.ArkWeb'; +import { common, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { distributedDeviceManager } from '@kit.DistributedServiceKit'; +import { OriginPage } from './OriginPage'; +import { Constants } from '../common/Constants'; +import { Logger } from '../common/Logger'; + +const regex = /^resource:\/\//; + +@Entry +@Component +struct Index { + @Provide navPathStack: NavPathStack = new NavPathStack(); + @StorageProp(Constants.SYSTEM_LANGUAGE_KEY) la: string = '' + private controller: WebviewController = new webview.WebviewController(); + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + private functionsMap: Map void> = new Map(); + private bundleName: string = ''; + + aboutToAppear(): void { + this.bundleName = this.context.abilityInfo.bundleName; + this.initFunctionsMap(); + } + + getRemoteDeviceId() { + let networkIdRet: string | undefined = undefined; + let dmInstance: distributedDeviceManager.DeviceManager = + distributedDeviceManager.createDeviceManager(this.bundleName); + if (typeof dmInstance === 'object' && dmInstance !== null) { + try { + let list = dmInstance.getAvailableDeviceListSync(); + if (typeof (list) === 'undefined' || typeof (list.length) === 'undefined') { + Logger.info('EntryAbility onButtonClick getRemoteDeviceId err: list is null') + return networkIdRet; + } + networkIdRet = list[0].networkId; + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } + } else { + Logger.error('EntryAbility onButtonClick getRemoteDeviceId err: dmClass is null'); + } + return networkIdRet; + } + + onBackPress(): boolean | void { + try { + if (this.controller.accessBackward()) { + this.controller.backward(); + return true; + } + } catch (error) { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + } + } + + @Builder + PageMap(name: string) { + if (name === Constants.ORIGIN_PAGE) { + OriginPage() + } + } + + initFunctionsMap() { + this.functionsMap.set('arkts://pages/toOriginPage', + () => this.navPathStack.pushPath({ name: Constants.ORIGIN_PAGE })); + this.functionsMap.set('third-party://pages/toThirdPage', () => { + this.context.openLink('appScheme://www.test.com:80/path1').then(() => { + Logger.info('Succeeded in starting FuncAbility'); + }).catch((err: BusinessError) => { + Logger.error(`Failed to start FuncAbility. Code is ${err.code}, message is ${err.message}`); + }); + }); + this.functionsMap.set('network://pages/toSystemApp', () => { + const want: Want = { + bundleName: 'com.huawei.hmos.settings', + abilityName: 'com.huawei.hmos.settings.MainAbility', + uri: 'wifi_entry', + }; + this.context.startAbility(want).then(() => { + Logger.info(`Successfully to startAbility. `); + }).catch((err: BusinessError) => { + Logger.error(`Failed to startAbility. Code: ${err.code}, message: ${err.message}`); + }); + }); + this.functionsMap.set('appgallery://pages/toMarketDetailPage', () => { + this.context.openLink('https://appgallery.huawei.com/app/detail?id=com.huawei.hmsapp.appgallery') + .catch((error: BusinessError) => { + hilog.error(0x0000, 'testTag', 'Execution failed, code = %{public}d, message = %{public}s', + error.code, error.message); + }); + }); + this.functionsMap.set('cross-device://pages/crossDevice', () => { + try { + let remoteDeviceId = this.getRemoteDeviceId(); + if (!remoteDeviceId) { + this.getUIContext().getPromptAction().showToast({ + message: $r('app.string.not_found_toast'), + duration: 2000 + }) + return; + } + const want: Want = { + deviceId: remoteDeviceId, + bundleName: this.bundleName, + abilityName: 'EntryAbility', + moduleName: 'entry', + } + this.context.startAbility(want); + } catch (err) { + this.getUIContext().getPromptAction().showToast({ + message: $r('app.string.not_found_toast'), + duration: 2000 + }) + Logger.error(`err: ${err.code} ${err.message}`); + } + }) + } + + build() { + Navigation(this.navPathStack) { + Column() { + Web({ + src: $rawfile(this.la == Constants.ENGLISH_LANGUAGE ? 'index_en.html' : 'index_cn.html'), + controller: this.controller + }) + .zoomAccess(false) + .onLoadIntercept((event) => { + const url: string = event.data.getRequestUrl(); + const callFunc = this.functionsMap.get(url) as () => void; + callFunc && callFunc(); + return !regex.test(url); + }) + } + } + .hideTitleBar(true) + .navDestination(this.PageMap) + .mode(NavigationMode.Stack) + } +} diff --git a/WebApplicationJump/entry/src/main/ets/pages/Navigation.ets b/WebApplicationJump/entry/src/main/ets/pages/Navigation.ets new file mode 100644 index 0000000000000000000000000000000000000000..32a8226e7297dc232c1e83d09a4113accf43a4ea --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Navigation.ets @@ -0,0 +1,28 @@ +@Builder +export function Page01() { + Navigation1() +} + +@Component +export struct Navigation1 { + @Consume('navPathStack') navPathStack: NavPathStack; + + build() { + // [Start navigation] + NavDestination() { + Column() { + Button($r('app.string.back_to_web_page')) + .width('100%') + .height(40) + .onClick(() => { + this.navPathStack.pushPath({ name: 'WebPage' }); + }) + } + + // ... + } + .title('ArkTS页面') + + // [End navigation] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/Navigation1.ets b/WebApplicationJump/entry/src/main/ets/pages/Navigation1.ets new file mode 100644 index 0000000000000000000000000000000000000000..0295db9ea074f6327cfb9e40c78c023b4c5b0752 --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Navigation1.ets @@ -0,0 +1,35 @@ +import { webview } from "@kit.ArkWeb"; + +@Builder +export function Page02() { + Navigation2() +} + +@Component +export struct Navigation2 { + @Consume('navPathStack') navPathStack: NavPathStack; + private controller: WebviewController = new webview.WebviewController; + + build() { + // [Start navigation1] + NavDestination() { + Column() { + Web({ + src: $rawfile('index.html'), + controller: this.controller + }) + .zoomAccess(false) + .onLoadIntercept((event) => { + const url: string = event.data.getRequestUrl(); + if (url === 'arkts://pages/toOriginPage') { + this.navPathStack.pop(); + } + // [StartExclude navigation1] + return false; + // [EndExclude navigation1] + }) + } + } + // [End navigation1] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/Navigation2.ets b/WebApplicationJump/entry/src/main/ets/pages/Navigation2.ets new file mode 100644 index 0000000000000000000000000000000000000000..439f8daf71f24847ddb0cd95f2d3c256854bf9ec --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Navigation2.ets @@ -0,0 +1,57 @@ +import { bundleManager, common, OpenLinkOptions } from "@kit.AbilityKit"; +import { BusinessError } from "@kit.BasicServicesKit"; +import { webview } from "@kit.ArkWeb"; + +@Builder +export function Page03() { + Navigation3() +} + +// [Start link1] +const link: string = "appScheme://www.test.com:80/path1"; +// [End link1] +@Component +export struct Navigation3 { + @Consume('navPathStack') navPathStack: NavPathStack; + private controller: WebviewController = new webview.WebviewController; + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + + build() { + // [Start link3] + Navigation(this.navPathStack) { + Column() { + Web({ + src: $rawfile('index.html'), + controller: this.controller + }) + .zoomAccess(false) + .onLoadIntercept((event) => { + const url: string = event.data.getRequestUrl(); + if (url === 'third-party://pages/toThirdApp') { + const link: string = "appScheme://www.test.com:80/path1"; + // [Start link2] + if (!bundleManager.canOpenLink(link)) { + return true; + } + // [End link2] + // Configuration parameter. + const openLinkOptions: OpenLinkOptions = { + appLinkingOnly: false, + parameters: { + name: 'test' + } + }; + // Open the application using the openLink interface. + this.context.openLink(link, openLinkOptions).then(() => { + console.info('open link success.'); + }).catch((err: BusinessError) => { + console.error(`open link failed. Code is ${err.code}, message is ${err.message}`); + }) + } + return url !== 'resource://rawfile/index2.html'; + }) + } + } + // [End link3] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/Navigation3.ets b/WebApplicationJump/entry/src/main/ets/pages/Navigation3.ets new file mode 100644 index 0000000000000000000000000000000000000000..4d0f09da0aff72a87a6f89ada20dbba6fd1adb7d --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Navigation3.ets @@ -0,0 +1,62 @@ +import { hilog } from "@kit.PerformanceAnalysisKit"; +import { common } from "@kit.AbilityKit"; +import { webview } from "@kit.ArkWeb"; + +@Builder +export function Page04() { + Navigation4() +} + +@Component +export struct Navigation4 { + @Consume('navPathStack') navPathStack: NavPathStack; + private controller: WebviewController = new webview.WebviewController; + private context = this.getUIContext().getHostContext() as common.UIAbilityContext; + + build() { + // [Start path_stack1] + Navigation(this.navPathStack) { + Column() { + Web({ + src: $rawfile('index.html'), + controller: this.controller + }) + .zoomAccess(false) + .onLoadIntercept((event) => { + const url: string = event.data.getRequestUrl(); + if (url === 'arkts://pullSpeciallyApp') { + const wantParam: Record = { + 'sceneType': 1, + 'destinationLatitude': 32.060844, + 'destinationLongitude': 118.78315, + 'destinationName': 'xx市xx路xx号', + 'destinationPoiIds': { + 1: '111111111111', + 2: '222222222222' + } as Record, + 'originName': 'xx市xx公园', + 'originLatitude': 31.060844, + 'originLongitude': 120.78315, + 'originPoiIds': { + 1: '333333333333', + 2: '444444444444' + } as Record, + 'vehicleType': 0 + }; + const abilityStartCallback: common.AbilityStartCallback = { + onError: (code: number, name: string, message: string) => { + hilog.error(0x0000, 'Sample', '%{public}s', 'onError code ' + code + 'name: ' + name + 'message: ' + message); + }, + onResult: (result:ESObject) => { + hilog.error(0x0000, 'Sample', '%{public}s', 'onResult result: ' + JSON.stringify(result)); + } + }; + this.context.startAbilityByType('navigation', wantParam, abilityStartCallback); + } + return url !== 'resource://rawfile/index.html'; + }) + } + } + // [End path_stack1] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/Navigation4.ets b/WebApplicationJump/entry/src/main/ets/pages/Navigation4.ets new file mode 100644 index 0000000000000000000000000000000000000000..739a5b42539cda961e6ba4d8bed0aa460cf83961 --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/Navigation4.ets @@ -0,0 +1,58 @@ +import { photoAccessHelper } from "@kit.MediaLibraryKit"; +import { BusinessError } from "@kit.BasicServicesKit"; +import { webview } from "@kit.ArkWeb"; +import { Constants } from "../common/Constants"; +import { OriginPage } from "./OriginPage"; + +@Builder +export function Page05() { + Navigation5() +} + +@Component +export struct Navigation5 { + @Consume('navPathStack') navPathStack: NavPathStack; + private controller: WebviewController = new webview.WebviewController; + + @Builder + PageMap(name: string) { + if (name === Constants.ORIGIN_PAGE) { + OriginPage() + } + } + + build() { + // [Start path_stack2] + Navigation(this.navPathStack) { + Column() { + Web({ + src: $rawfile('index.html'), + controller: this.controller + }) + .zoomAccess(false) + .onLoadIntercept((event) => { + const url: string = event.data.getRequestUrl(); + if (url === 'photo://pages/selectPhoto') { + const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); + photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // Filter and select the media file type as IMAGE + photoSelectOptions.maxSelectNumber = 5; // Select the maximum number of media files + let uris: Array = []; + const photoViewPicker = new photoAccessHelper.PhotoViewPicker(); + photoViewPicker.select(photoSelectOptions) + .then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => { + uris = photoSelectResult.photoUris; + console.info('photoViewPicker.select to file succeed and uris are:' + uris); + }) + .catch((err: BusinessError) => { + console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`); + }) + } + return url !== 'resource://rawfile/index3.html'; + }) + } + } + .hideTitleBar(true) + .navDestination(this.PageMap) + // [End path_stack2] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/ets/pages/OriginPage.ets b/WebApplicationJump/entry/src/main/ets/pages/OriginPage.ets new file mode 100644 index 0000000000000000000000000000000000000000..187c4e4eadb84eac55a944ab300aa60799791867 --- /dev/null +++ b/WebApplicationJump/entry/src/main/ets/pages/OriginPage.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Constants } from '../common/Constants'; + +@Component +export struct OriginPage { + @Consume('navPathStack') navPathStack: NavPathStack; + @StorageProp(Constants.SYSTEM_LANGUAGE_KEY) la: string = ''; + + build() { + // [Start nav_dest] + NavDestination() { + Column() { + Button('return to the web page') + .width('100%') + .height(40) + .onClick(() => { + this.navPathStack.pop(); + }) + } + // [StartExclude nav_dest] + .width(Constants.FULL_SCREEN) + .height(Constants.FULL_SCREEN) + .justifyContent(FlexAlign.End) + .padding({ + left: $r('app.float.space_24'), + right: $r('app.float.space_24'), + bottom: $r('app.float.space_bottom') + }) + } + // [EndExclude nav_dest] + .title(this.la = 'en-Latn-CN' ? 'OriginPage' : 'NativePage') + // [End nav_dest] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/module.json5 b/WebApplicationJump/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e464848cd376bb91ba16fdf92bac3fc89a71ac41 --- /dev/null +++ b/WebApplicationJump/entry/src/main/module.json5 @@ -0,0 +1,67 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.DISTRIBUTED_DATASYNC", + "reason": "$string:distributed_permission", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "inuse" + } + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ], + // [Start query_schemes] + "querySchemes": [ + "app1Scheme" + ], + // [End query_schemes] + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/element/color.json b/WebApplicationJump/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/element/float.json b/WebApplicationJump/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..1a8e423d0df0a64f6ec6338fd0b0f1fe75f7898e --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/element/float.json @@ -0,0 +1,16 @@ +{ + "float": [ + { + "name": "space_24", + "value": "24vp" + }, + { + "name": "space_bottom", + "value": "16vp" + }, + { + "name": "button_height", + "value": "40vp" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/element/string.json b/WebApplicationJump/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7340b85ede8c3388f1c3eb343bacaaf8c67c761b --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/element/string.json @@ -0,0 +1,32 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "WebPullUp" + }, + { + "name": "back_to_web_page", + "value": "return to the web page" + }, + { + "name": "distributed_permission", + "value": "Used to pull up applications on other devices." + }, + { + "name": "original_page", + "value": "ArkTS Page" + }, + { + "name": "not_found_toast", + "value": "No peripherals found, please check and try again!" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/media/background.png b/WebApplicationJump/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/WebApplicationJump/entry/src/main/resources/base/media/background.png differ diff --git a/WebApplicationJump/entry/src/main/resources/base/media/foreground.png b/WebApplicationJump/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/WebApplicationJump/entry/src/main/resources/base/media/foreground.png differ diff --git a/WebApplicationJump/entry/src/main/resources/base/media/layered_image.json b/WebApplicationJump/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/media/startIcon.png b/WebApplicationJump/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/WebApplicationJump/entry/src/main/resources/base/media/startIcon.png differ diff --git a/WebApplicationJump/entry/src/main/resources/base/profile/backup_config.json b/WebApplicationJump/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/base/profile/main_pages.json b/WebApplicationJump/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/WebApplicationJump/entry/src/main/resources/base/profile/route_map.json b/WebApplicationJump/entry/src/main/resources/base/profile/route_map.json new file mode 100644 index 0000000000000000000000000000000000000000..f7ef686c0f76874d588105795cfab4a7bda8bc12 --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/base/profile/route_map.json @@ -0,0 +1,29 @@ +{ + "routerMap": [ + { + "name": "Page01", + "pageSourceFile": "src/main/ets/pages/Navigation.ets", + "buildFunction": "Page01" + }, + { + "name": "Page02", + "pageSourceFile": "src/main/ets/pages/Navigation1.ets", + "buildFunction": "Page02" + }, + { + "name": "Page03", + "pageSourceFile": "src/main/ets/pages/Navigation2.ets", + "buildFunction": "Page03" + }, + { + "name": "Page04", + "pageSourceFile": "src/main/ets/pages/Navigation3.ets", + "buildFunction": "Page04" + }, + { + "name": "Page05", + "pageSourceFile": "src/main/ets/pages/Navigation4.ets", + "buildFunction": "Page05" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/en_US/element/string.json b/WebApplicationJump/entry/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..7340b85ede8c3388f1c3eb343bacaaf8c67c761b --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/en_US/element/string.json @@ -0,0 +1,32 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "WebPullUp" + }, + { + "name": "back_to_web_page", + "value": "return to the web page" + }, + { + "name": "distributed_permission", + "value": "Used to pull up applications on other devices." + }, + { + "name": "original_page", + "value": "ArkTS Page" + }, + { + "name": "not_found_toast", + "value": "No peripherals found, please check and try again!" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/css/styles.css b/WebApplicationJump/entry/src/main/resources/rawfile/css/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..f6c2fe165095ac0f1f70cb4bc2a22b13c8ef0e4b --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/css/styles.css @@ -0,0 +1,61 @@ +* { + margin: 0; + padding: 0; +} + +.web_page_demo { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; +} + +.title { + width: calc(100% - 48px); + color: rgba(23, 9, 9, 0.9); + font-family: 鸿蒙黑体; + font-size: 30px; + font-weight: 700; + line-height: 40px; + letter-spacing: 0px; + text-align: left; + margin-top: 64px; +} + +ul { + width: calc(100% - 48px); + display: flex; + flex-direction: column; + margin-bottom: 16px; + list-style: none; +} + +ul li { + width: 100%; + height: 40px; + border-radius: 20px; + background: rgb(10, 89, 247); + margin-bottom: 12px; + text-align: center; +} + +.function_item { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + color: rgb(255, 255, 255); + text-decoration: none; + font-family: "鸿蒙黑体"; + font-size: 16px; + font-weight: 500; + line-height: 22px; + letter-spacing: 0px; +} + +ul li:last-child { + margin-bottom: 0px; +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/css/styles1.css b/WebApplicationJump/entry/src/main/resources/rawfile/css/styles1.css new file mode 100644 index 0000000000000000000000000000000000000000..ee4e621b3f8148812dfd2b937bb45d137f09d5cc --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/css/styles1.css @@ -0,0 +1,81 @@ +* { + margin: 0; + padding: 0; +} + +.web_page_demo { + width: 100%; + height: 100vh; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; +} + +.header { + width: calc(100% - 32px); + height: 56px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; +} + +.header .back { + width: 40px; + height: 40px; + border-radius: 20px; + background: rgba(0, 0, 0, 0.05); + margin-right: 8px; + display: flex; + justify-content: center; + align-items: center; +} + +.header .back img { + width: 24px; + height: 24px; +} + +.header span { + height: 26px; + color: rgba(0, 0, 0, 0.9); + font-family: 鸿蒙黑体; + font-size: 20px; + font-weight: 700; + line-height: 26px; + letter-spacing: 0px; + text-align: left; +} + +.title { + color: rgba(0, 0, 0, 0.9); + font-family: "鸿蒙黑体"; + font-size: 24px; + font-weight: 700; + line-height: 22px; + letter-spacing: 0px; + text-align: center; + margin-top: 72px; +} + +a { + margin-top: auto; + width: calc(100% - 48px); + height: 40px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + border-radius: 20px; + background: rgb(10, 89, 247); + text-decoration: none; + color: rgb(255, 255, 255); + font-family: "鸿蒙黑体"; + font-size: 16px; + font-weight: 500; + line-height: 22px; + letter-spacing: 0px; + text-align: center; + margin-bottom: 16px; +} \ No newline at end of file diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/index.html b/WebApplicationJump/entry/src/main/resources/rawfile/index.html new file mode 100644 index 0000000000000000000000000000000000000000..fe0368ff0b6852c3ed608f565d2c7085221a5aa1 --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/index.html @@ -0,0 +1,10 @@ + + + + + + Document + + + + diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/index1_cn.html b/WebApplicationJump/entry/src/main/resources/rawfile/index1_cn.html new file mode 100644 index 0000000000000000000000000000000000000000..b2bef50c772c2fa241dffd3b936e36cc8fd1b2e3 --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/index1_cn.html @@ -0,0 +1,30 @@ + + + + + + Document + + + + +
+
+
+ +
+ + Web 页面 +
+
Hello Web
+ 跳转回Web页面 +
+ + + diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/index1_en.html b/WebApplicationJump/entry/src/main/resources/rawfile/index1_en.html new file mode 100644 index 0000000000000000000000000000000000000000..211cdee9d6cd59726f134dd8235f2ae162b5d44e --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/index1_en.html @@ -0,0 +1,29 @@ + + + + + + Document + + + +
+
+
+ +
+ + Web Page +
+
Hello Web
+ Navigate back to the Web page +
+ + + diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/index_cn.html b/WebApplicationJump/entry/src/main/resources/rawfile/index_cn.html new file mode 100644 index 0000000000000000000000000000000000000000..f72d09ccef82ea00ccebbfd66ef1d435fe7ca4bc --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/index_cn.html @@ -0,0 +1,36 @@ + + + + + + Document + + + + + + + + diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/index_en.html b/WebApplicationJump/entry/src/main/resources/rawfile/index_en.html new file mode 100644 index 0000000000000000000000000000000000000000..cd0bccff2b53e2eae681f6df91c4907c52463f1c --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/rawfile/index_en.html @@ -0,0 +1,38 @@ + + + + + + Document + + + + +
+
web and application jump and pull up
+ +
+ + + diff --git a/WebApplicationJump/entry/src/main/resources/rawfile/statics/ic_back.png b/WebApplicationJump/entry/src/main/resources/rawfile/statics/ic_back.png new file mode 100644 index 0000000000000000000000000000000000000000..4cfaff3395298b86ce6faa8121ff53f9f1dc35fa Binary files /dev/null and b/WebApplicationJump/entry/src/main/resources/rawfile/statics/ic_back.png differ diff --git a/WebApplicationJump/entry/src/main/resources/zh_CN/element/string.json b/WebApplicationJump/entry/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..592138a78d93df8bcf0be9f64de718c0eb90143f --- /dev/null +++ b/WebApplicationJump/entry/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,32 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "模块描述" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "Web应用拉起" + }, + { + "name": "back_to_web_page", + "value": "跳转回Web页面" + }, + { + "name": "distributed_permission", + "value": "用于拉起其他设备上的应用" + }, + { + "name": "original_page", + "value": "原生页面" + }, + { + "name": "not_found_toast", + "value": "未发现周边设备,请检查后重试!" + } + ] +} \ No newline at end of file diff --git a/WebApplicationJump/hvigor/hvigor-config.json5 b/WebApplicationJump/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..06b2783670a348f95533b352c1ceda909a842bbc --- /dev/null +++ b/WebApplicationJump/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/WebApplicationJump/hvigorfile.ts b/WebApplicationJump/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775 --- /dev/null +++ b/WebApplicationJump/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/WebApplicationJump/oh-package.json5 b/WebApplicationJump/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..8bf916d4a165e0466c65bc49f58ab2e3c27e8931 --- /dev/null +++ b/WebApplicationJump/oh-package.json5 @@ -0,0 +1,8 @@ +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + } +} diff --git a/WebApplicationJump/screenshots/device/phone.png b/WebApplicationJump/screenshots/device/phone.png new file mode 100644 index 0000000000000000000000000000000000000000..ccc84f936bcf78437fa0be7f064007c6f8239bbf Binary files /dev/null and b/WebApplicationJump/screenshots/device/phone.png differ diff --git a/WebApplicationJump/screenshots/device/phone_EN.png b/WebApplicationJump/screenshots/device/phone_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..c96185e96ba3f4795e6f6d0af8d7b97b865fb03b Binary files /dev/null and b/WebApplicationJump/screenshots/device/phone_EN.png differ