背景
HarmonyOS平台通过Web控件可支持网页加载展示,Web在中是作为专项参考的。
本篇文章将从Android和iOS平台研发角度出发来实践学习API功能
说明
- 整个示例是以HarmonyOS开发文档网址作为加载目标
- 页面布局增加了三个按钮“后退”,“前进”, “刷新”
效果
准备
- 请参照
鸿蒙OS开发 | 更多内容↓点击 | HarmonyOS与OpenHarmony技术 |
---|---|---|
鸿蒙技术文档 | 开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。 | 或+mau123789学习,是v喔 |
熟读HarmonyOS Web组件指导
2.创建一个Demo工程,选择Stage模型。
实践总结
- UA可以设置,但无法通过API拿到自己设置的UA值
- 文件可以下载,但用户没有控制权
- 用户无法控制定位权限申请
- Web控件当前需要将UA设置为Android或者iOS特征的UA,大部分主流网站没有适配鸿蒙Web
- 鸿蒙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管理指导
网页调试
功能介绍
- 支持多窗口
- 多窗口返回关闭
- 加载进度提示
- 警告框,确认框,提示框
- 权限申请
- 输出调试日志
- 非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) })}
}