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

电子说

1.3w人已加入

描述

背景

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

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

说明

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

效果

鸿蒙

准备

  1. 请参照

熟读HarmonyOS Web组件指导

鸿蒙

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) })

  }
}

审核编辑 黄宇

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分