0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-03-28 21:47 次阅读

背景

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

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

说明

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

效果

Screenshot_20231130120249783.png

准备

  1. 请参照

熟读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?: CustomDialogController
  private 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.buttonColorFocusColor
  private webviewController: web_webview.WebviewController = new web_webview.WebviewController();
  private context = getContext(this) as common.UIAbilityContext;
  dialogController: CustomDialogController | null = null

  aboutToAppear() {
    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.newProgress

            if (progress.newProgress >= 0 && progress.newProgress < 100) {
              this.showProgress = true
            } else if (progress.newProgress == 100) {
              this.showProgress = false
            }

            if (this.webviewController.accessForward()) {
              this.forward = true
              this.currentButtonColor = this.buttonColorFocusColor
            } else {
              this.forward = false
              this.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).host
            try {
              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).host
            try {
              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) })

  }
}

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Web
    Web
    +关注

    关注

    2

    文章

    1238

    浏览量

    68460
  • 鸿蒙
    +关注

    关注

    55

    文章

    1629

    浏览量

    42120
  • HarmonyOS
    +关注

    关注

    79

    文章

    1839

    浏览量

    29261
  • 鸿蒙OS
    +关注

    关注

    0

    文章

    140

    浏览量

    4279
收藏 人收藏

    评论

    相关推荐

    鸿蒙开发基础-Web组件之cookie操作

    }) ... } ... 本文章主要是对鸿蒙开发当中ArkTS语言的基础应用实战,Web组件里的cookie操作。更多的鸿蒙应用开发
    发表于 01-14 21:31

    鸿蒙原生应用/元服务实战-Web隐私声明

    这个位置的隐私申明是需要在WEB网页下完成的,ArkTS鸿蒙原生应用与元服务开发者,不一定熟悉这块,一些公司也不一定有自己的服务器和域名、网站网页
    发表于 01-24 15:05

    鸿蒙OS应用程序开发

    这份学习文档主要是带领大家在鸿蒙OS上学习开发一个应用程序,主要知识点如下:1、U-Boot引导文件烧写方式;2、内核镜像烧写方式;3、镜像运行。
    发表于 09-11 14:39

    鸿蒙OS适用的全场景到底什么意思?

    鸿蒙系统(HarmonyOS),第一款基于微内核的全场景分布式OS,是华为自主研发的操作系统。华为在开发者大会HDC.2019上正式发布了鸿蒙系统,该系统将率先部署在智慧屏、车载终端、
    发表于 09-25 09:25

    鸿蒙os系统是什么意思 鸿蒙os系统有什么作用

    大家都很熟悉华为,那么华为近年新研发出来的鸿蒙os系统是什么意思?下面与大家分享华为鸿蒙os系统是什么意思的教程。鸿蒙
    发表于 12-17 11:34

    Nodemcu web网页显示简介

    Nodemcu-0.96oled-dht11-web网页显示简介1.软件部分Arduino IDE2.硬件部分NodeMCUOLEDDHT113.知识点Web开发Arduino IDE
    发表于 11-01 07:34

    鸿蒙 OS 应用开发初体验

    的操作系统平台和开发框架。HarmonyOS 的目标是实现跨设备的无缝协同和高性能。 DevEco Studio 对标 Android Studio,开发鸿蒙 OS 应用的 IDE。
    发表于 11-02 19:38

    鸿蒙OS2.0手机开发者Beta版登场

    12 月 16 日,华为宣布正式推出鸿蒙 OS 的手机开发者 Beta 版,并正式面向个人/企业开发者公测鸿蒙 2.0,
    的头像 发表于 12-16 14:39 1916次阅读

    华为发布鸿蒙OS Beta版

    昨天华为发布鸿蒙OS Beta版了?鸿蒙系统一直在按照既有步伐前进,现在华为发布鸿蒙OS Beta版,而且一些生态
    的头像 发表于 12-17 08:41 2590次阅读

    华为鸿蒙OS 2.0开发者公测版本大批量向已申请开发者推送

    4 月 27 日,华为鸿蒙 OS 2.0 开发者公测版本大批量向已申请的开发者推送,随后网上出现大量鸿蒙
    的头像 发表于 05-12 09:26 2849次阅读

    鸿蒙OS千呼万唤始出来

    从2019年在华为开发者大会上公布鸿蒙OS开始,围绕着鸿蒙OS的话题始终没有停止过,而华为也坚持不懈地为
    的头像 发表于 06-01 15:56 2335次阅读

    鸿蒙os怎么升级

    6月2日,华为正式发布了鸿蒙armonyOS 2系统,那么鸿蒙os如何升级?现将鸿蒙os升级方式告知如下。
    的头像 发表于 06-08 16:26 2486次阅读

    鸿蒙os和安卓的区别,鸿蒙与安卓比有什么优势

    华为鸿蒙系统已经发布,鸿蒙系统和安卓都是在Linux基础上开发出来的,所以很多小伙伴都想知道鸿蒙os和安卓系统之间的区别是什么?华为
    的头像 发表于 06-17 09:58 1.3w次阅读

    通过Web网页控制开发板LED灯

    接下来将介绍如何通过Web网页来控制开发板上的LED灯,本文只是在网页上实现功能,并无交互功能,与开发板的交互功能实现将在《
    的头像 发表于 04-25 15:05 1231次阅读
    通过<b class='flag-5'>Web</b><b class='flag-5'>网页</b>控制<b class='flag-5'>开发</b>板LED灯

    鸿蒙OS元服务开发说明:【WebGL网页图形库开发接口】

    WebGL主要帮助开发者在前端开发中完成图形图像的相关处理,比如绘制彩色图形等。目前该功能仅支持使用兼容JS的类Web开发范式开发
    的头像 发表于 04-02 17:02 205次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b>元服务<b class='flag-5'>开发</b>说明:【WebGL<b class='flag-5'>网页</b>图形库<b class='flag-5'>开发</b>接口】