鸿蒙OS开发实例:【Web网页】

news/2024/4/28 17:12:26/文章来源:https://blog.csdn.net/m0_70748845/article/details/137124895

 背景

HarmonyOS平台通过Web控件可支持网页加载展示,Web在中是作为专项参考的。

本篇文章将从Android和iOS平台研发角度出发来实践学习API功能

说明

  1. 整个示例是以HarmonyOS开发文档网址作为加载目标
  2. 页面布局增加了三个按钮“后退”,“前进”, “刷新”

效果

Screenshot_20231130120249783.png

准备

  1. 请参照
鸿蒙OS开发更多内容↓点击HarmonyOS与OpenHarmony技术
鸿蒙技术文档开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。或+mau123789学习,是v喔

熟读HarmonyOS Web组件指导

搜狗高速浏览器截图20240326151547.png

2.创建一个Demo工程,选择Stage模型。

实践总结

  1. UA可以设置,但无法通过API拿到自己设置的UA值
  2. 文件可以下载,但用户没有控制权
  3. 用户无法控制定位权限申请
  4. Web控件当前需要将UA设置为Android或者iOS特征的UA,大部分主流网站没有适配鸿蒙Web
  5. 鸿蒙UA特征不明显 Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.88 Mobile Safari/537.36

开始

页面容器设置为沉浸式

import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';export default class EntryAbility extends UIAbility {onWindowStageCreate(windowStage: window.WindowStage) {// 1.获取应用主窗口。let windowClass: window.Window = null;windowStage.getMainWindow((err, data) => {if (err.code) {console.error('Failed to obtain the main window. Cause: ' + JSON.stringify(err));return;}windowClass = data;console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));// 2.实现沉浸式效果:设置导航栏、状态栏显示。windowClass.setWindowSystemBarEnable(['status','navigation'], (err) => {if (err.code) {console.error('Failed to set the system bar to be visible. Cause:' + JSON.stringify(err));return;}console.info('Succeeded in setting the system bar to be visible.');});})//获取当前应用内最后显示的窗口,使用callback异步回调window.getLastWindow(this.context).then((result: window.Window) => {result.setWindowSystemBarEnable(['status', 'navigation'])result.setWindowLayoutFullScreen(true);})windowStage.loadContent('pages/Index', (err, data) => {if (err.code) {hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');return;}hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');});}}

创建WebView组件

文件路径

根目录/ets/entry/src/main/pages/WebView.ts

注册页面 main_pages.json

{"src": ["pages/Index","pages/WebView"]
}

功能实现

Cookie管理指导

网页调试

功能介绍
  1. 支持多窗口
  2. 多窗口返回关闭
  3. 加载进度提示
  4. 警告框,确认框,提示框
  5. 权限申请
  6. 输出调试日志
  7. 非http或https协议拦截
import web_webview from '@ohos.web.webview';
import router from '@ohos.router';
import common from '@ohos.app.ability.common';
import Url from '@ohos.url'web_webview.once("webInited", () => {console.log("setCookie")web_webview.WebCookieManager.setCookie("https://developer.harmonyos.com/", "author=harvey")
})//在同一page页有两个web组件。在WebComponent新开窗口时,会跳转到NewWebViewComp。
@CustomDialog
struct NewWebViewComp {private controller?: CustomDialogControllerprivate webviewController: web_webview.WebviewController = new web_webview.WebviewController()build() {Column() {Web({ src: "", controller: this.webviewController }).javaScriptAccess(true).multiWindowAccess(false).domStorageAccess(true).onWindowExit(() => {console.info("NewWebViewComp onWindowExit")if (this.controller) {this.controller.close()}})}}
}@Entry
@Component
struct Index {//www.useragentinfo.com// @State webURL: string = 'https://m.bilibili.com/'    //'https://developer.harmonyos.com/'// @State webURL: string = 'https://www.baidu.com'@State webURL: string = 'https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/start-overview-0000001478061421-V3?catalogVersion=V3'@State back: boolean = true@State forward: boolean = false@State showProgress: boolean = false@State currentProgress: number = 0@State buttonColorFocusColor: number = Color.Black@State buttonColorDisableColor: number = Color.Gray@State currentButtonColor: number = this.buttonColorFocusColorprivate webviewController: web_webview.WebviewController = new web_webview.WebviewController();private context = getContext(this) as common.UIAbilityContext;dialogController: CustomDialogController | null = nullaboutToAppear() {web_webview.WebviewController.setWebDebuggingAccess(true)let params = router.getParams()if (params) {this.webURL = params['targetUrl'];}}build() {Column() {Stack() {Web({ src: this.webURL, controller: this.webviewController }).width('100%').height('100%').userAgent('Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 HarveyHarmonyOS/1.0.0').multiWindowAccess(true).javaScriptAccess(true).geolocationAccess(true).imageAccess(true).onlineImageAccess(true).domStorageAccess(true).fileAccess(true).mediaPlayGestureAccess(true).mixedMode(MixedMode.Compatible).onTitleReceive((info) => {console.log('标题栏: ' + info.title)}).onProgressChange((progress) => {console.log('当前加载进度 ' + progress.newProgress)this.currentProgress = progress.newProgressif (progress.newProgress >= 0 && progress.newProgress < 100) {this.showProgress = true} else if (progress.newProgress == 100) {this.showProgress = false}if (this.webviewController.accessForward()) {this.forward = truethis.currentButtonColor = this.buttonColorFocusColor} else {this.forward = falsethis.currentButtonColor = this.buttonColorDisableColor}console.log('userAgent: ' + this.webviewController.getUserAgent())}).onErrorReceive((error) => {console.log(error.request.getRequestUrl())console.log(JSON.stringify(error.error))}).onHttpErrorReceive((error) => {console.log(JSON.stringify(error.response))}).onSslErrorEventReceive((info) => {}).onRenderExited(() => {console.log('onRenderExited')}).onUrlLoadIntercept((info) => {if(!info.data.toString().toLowerCase().startsWith("https://") || !info.data.toString().toLowerCase().startsWith("https://")){console.log('拦截信息: ' + JSON.stringify(info))return true;}console.log('信息: ' + JSON.stringify(info))//false : 不拦截   true: 拦截return false}).onDownloadStart( (event) => {AlertDialog.show({title: event.url,message: event.url,primaryButton: {value: 'cancel',action: () => {}}})}).onAlert((event) => {AlertDialog.show({title: event.url,message: event.message,confirm: {value: 'onAlert',action: () => {event.result.handleConfirm()}},cancel: () => {event.result.handleCancel()}})return true}).onConfirm((event) => {AlertDialog.show({title: event.url,message: event.message,confirm: {value: 'onConfirm',action: () => {event.result.handleConfirm()}},cancel: () => {event.result.handleCancel()}})return true;}).onPrompt((event) => {AlertDialog.show({title: event.url,message: event.message,primaryButton: {value: 'cancel',action: () => {event.result.handleCancel()}},secondaryButton: {value: 'ok',action: () => {event.result.handleConfirm()}},cancel: () => {event.result.handleCancel()}})return true;}).onConsole((msg) => {console.error('网页日志:' + JSON.stringify(msg.message.getMessage()))return true}).onWindowNew((event) => {console.log('新开window')if (!event.isAlert) {router.pushUrl({ url: 'custompages/WebView', params: {"targetUrl": event.targetUrl} }).then(() => {console.info('Succeeded in jumping to the second page.')}).catch((error) => {console.log(error)})} else {if (this.dialogController) {this.dialogController.close()}let popController: web_webview.WebviewController = new web_webview.WebviewController()this.dialogController = new CustomDialogController({builder: NewWebViewComp({ webviewController: popController })})this.dialogController.open()//将新窗口对应WebviewController返回给Web内核。//如果不需要打开新窗口请调用event.handler.setWebController接口设置成null。//若不调用event.handler.setWebController接口,会造成render进程阻塞。event.handler.setWebController(popController)}}).onWindowExit(() => {console.log('已推出window')}).onGeolocationHide(() => {console.log('geo隐藏')}).onGeolocationShow((info) => {info.geolocation.invoke(info.origin, false, false)console.log(info.origin + ' 有定位需求')}).onPageBegin((info) => {console.error(info.url)let host = Url.URL.parseURL(info.url).hosttry {let cookie = web_webview.WebCookieManager.getCookie(host)console.log('Bcookie: ' + cookie)} catch (e) {console.error(e)}}).onPageEnd((info) => {let host = Url.URL.parseURL(info.url).hosttry {let cookie = web_webview.WebCookieManager.getCookie(host)console.log('Bcookie: ' + cookie)} catch (e) {console.error(e + ' ' + info.url)}}).onBeforeUnload((info) => {return false}).onRefreshAccessedHistory((info) => {}).onResourceLoad(() => {}).onFullScreenEnter((info) => {}).onFullScreenExit(() => {}).onPermissionRequest((event) => {AlertDialog.show({title: 'title',message: event.request.getAccessibleResource()[0],primaryButton: {value: 'deny',action: () => {event.request.deny()}},secondaryButton: {value: 'onConfirm',action: () => {event.request.grant(event.request.getAccessibleResource())}},cancel: () => {event.request.deny()}})}).onInterceptKeyEvent((info) => {console.log(info.keyCode + ' ' + info.keyText)return false}).onPageVisible((info) => {console.log(info.url)})if (this.showProgress) {Progress({ value: this.currentProgress, total: 100, type: ProgressType.Linear }).width('100%').height(45)}}.height('93%').alignContent(Alignment.TopStart)Row() {Text('后退').fontSize(18).enabled(this.back).onClick(() => {if (this.webviewController.accessBackward()) {this.webviewController.backward()} else {if ("1" === router.getLength()) {this.context.terminateSelf()} else {router.back()}}}).width('30%').height('100%').textAlign(TextAlign.Center)Text('前进').fontSize(18).fontColor(this.currentButtonColor).onClick(() => {if (this.webviewController.accessForward()) {this.webviewController.forward()}}).width('30%').height('100%').textAlign(TextAlign.Center)Text('刷新').fontSize(18).fontColor(Color.Black).onClick(() => {this.webviewController.refresh()}).width('30%').height('100%').textAlign(TextAlign.Center)}.width('100%').height('5%').backgroundColor(Color.White).justifyContent(FlexAlign.SpaceBetween)}.width('100%').height('100%').padding({ top: px2vp(111) })}
}

鸿蒙知识持续更新中,关注我点赞不迷路喔!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1026857.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建vite项目

文章目录 Vite 是一个基于 Webpack 的开发服务器&#xff0c;用于开发 Vue 3 和 Vite 应用程序 一、创建一个vite项目二、集成Vue Router1.安装 vue-routernext插件2.在 src 目录下创建一个名为 router 的文件夹&#xff0c;并在其中创建一个名为 index.js 的文件。在这个文件中…

【刷题】滑动窗口精通 — Leetcode 30. 串联所有单词的子串 | Leetcode 76. 最小覆盖子串

送给大家一句话&#xff1a; 充满着欢乐与斗争精神的人们&#xff0c;永远带着欢乐&#xff0c;欢迎雷霆与阳光。 —— 赫胥黎 滑动窗口精通 前言Leetcode 30. 串联所有单词的子串题目描述算法思路 Leetcode 76. 最小覆盖子串题目描述算法思路 Thanks♪(&#xff65;ω&#xf…

45.跳跃游戏||

// 定义一个名为Solution的类 class Solution {// 定义一个public方法jump&#xff0c;输入参数为一个整数数组nums&#xff0c;返回值类型为整数public int jump(int[] nums) {// 初始化跳跃次数结果变量为0int result 0;// 初始化当前覆盖的最远距离下标为0int end 0;// 初…

【随笔】Git -- 基本概念和使用方式(五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

安卓利用CameraX 拍照获这张照片的exif信息

一、首先导入相关权限 <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE" /><uses-featureandroid:name"android.hardware.camera"android:required"true" /><uses-permission android:name"andro…

2014年认证杯SPSSPRO杯数学建模B题(第一阶段)位图的处理算法全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现&#xff1a; 图形&#xff08;或图像&#xff09;在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形&#xff0c;位图则使用像素来描述图像。一般来说&#…

Leetcode LRU---哈希➕双链表

题目链接 讲解视频 Tips&#xff1a; 代码&#xff1a; import java.util.*; // 修改导入语句&#xff0c;正确引入 java.util 包class Node{//双链表int key,value;Node pre,next;public Node(int k,int v){this.key k;this.value v;this.pre null;this.next null;}…

OpenHarmony实战开发-从0到1实现购物应用页面

概述 OpenHarmony ArkUI框架提供了丰富的动画组件和接口&#xff0c;开发者可以根据实际场景和开发需求&#xff0c;选用丰富的动画组件和接口来实现不同的动画效果。 本Codelab中&#xff0c;我们会构建一个简易的购物应用。应用包含两级页面&#xff0c;分别是主页&#xf…

【Nebula笔记】基础操作

目录 一、预备~ 二、基础操作 (一) 图空间 1. 创建图空间 2. 清空图空间 3. 其他 4. FAQ 执行DROP SPACE语句删除图空间后&#xff0c;为什么磁盘的大小没变化&#xff1f; (二) 点类型 1. 创建Tag 2. 删除Tag 3. 更新Tag 4. 其他 (三) 边类型 1. 创建Edge type…

ubuntu系统下如何使用vscode编译和调试#小白入门#

编程环境&#xff1a;ubuntu系统为18.04.1&#xff0c;vscode版本为1.66.2 一、VSCode切换中文显示&#xff1a; 1、vscode安装完成后启动,在左侧externsions中搜索“简体中文”插件&#xff0c;并完成安装&#xff1a; 2、选择右下角齿轮形状的"Manage"&#xff…

自然指数函数e^x与欧拉数e (下)

自然指数函数e^x与欧拉数e Part I: 如何找到欧拉数e 上一篇文章停在了“应该存在一个b&#xff0c;使得指数函数b^x在x0处的导数为1。且该指数函数在任意一处的导数都等于当前位置的函数值”。根据前面所知道的&#xff0c;可以用数学公式列出以下一些已知条件&#xff1a; &am…

Go语言学习Day5:函数(下)

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、本质、数据类型与延迟函数①函数的本质②函数的数据类型③defer延迟函数 2、匿名、回调函数与闭…

Go——map操作及原理

一.map介绍和使用 map是一种无序的基于key-value的数据结构&#xff0c;Go语言的map是引用类型&#xff0c;必须初始化才可以使用。 1. 定义 Go语言中&#xff0c;map类型语法如下&#xff1a; map[KeyType]ValueType KeyType表示键类型ValueType表示值类型 map类型的变量默认…

班级综合测评管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 目录 1. …

docker 的网络管理

docker应用自带了三种类型的网络&#xff0c;然后我们自己也能自定义网络 roottest-virtual-machine:~# docker network ls NETWORK ID NAME DRIVER SCOPE 4c3e28760cff bridge bridge local afd1493dc119 host host local 5f200e2eaf22 n…

AOP切入点表达式基本格式

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 官方地址 https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html AOP切入点表达式基本格式如下&#xff1a; execution(modifiers-patte…

Vscode创建php项目

1.安装中文插件&#xff08;可安装可不安装&#xff09; 2.安装主题&#xff08;可安装可不安装&#xff09; 3.安装和php相关的插件 4.打开文件夹 5.路由操作 查看项目中的route路由 浏览器中访问think 隐藏index.php入口文件 访问ThinkPHP5.1开发手册&#xff0c;复制apa…

React-1-jsx基础-事件绑定-样式处理

一.JSX基础-概念和本质 1.1 什么是JSX JSX是JavaScript和XML&#xff08;HTML&#xff09;的缩写&#xff0c;表示在JS代码中编写HTML模版结构,它是React中编写UI模版的方式 优势&#xff1a; 1. HTML的声明式模版写法 2. JS的可编程能力 JSX的本质&#xff1a; JSX并不是标…

[openGL] qt5版本+mingw编译Assimp库+调用

目录 一 版本 二 编译问题 三 CMAKE准备 四 开始编译 4.1 准备Assimp源码 4.2 编译工具准备 4.3 生成Assimp库 4.4 使用Assimp 4.4.1 准备 4.4.2 加载模型 4.4.3 模型效果 一 版本 Assimp官网上已经停止更新截至在3.3.1版本,但是这个版本编译是最稳定的,较新的版本…

WORDPRESS从WORD复制粘贴公式

整合教程&#xff1a;WordPress插件包整合教程 WordPaster支持自动上传本地图片文件&#xff0c;自动上传Word文档中的图片 步骤与效果&#xff1a; 1.打开word文档&#xff0c;复制word文档内容 2.在网页中打开编辑器页面&#xff0c;点击“粘贴本地文件,Word文档”按钮上传…