Skip to content

0x016-鸿蒙应用开发笔记4-webview

加载网络地址

js
import { webview } from '@kit.ArkWeb' 

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController() 
  build() {
    Column() {
      Web({ src: 'https://m.baidu.com', controller: this.controller }) 
    }
  }
}
import { webview } from '@kit.ArkWeb' 

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController() 
  build() {
    Column() {
      Web({ src: 'https://m.baidu.com', controller: this.controller }) 
    }
  }
}

加载本地地址

js
import { webview } from '@kit.ArkWeb'  
  
@Entry  
@Component  
struct Index {  
  controller: webview.WebviewController = new webview.WebviewController()   
  
  build() {  
    Column() {  
      // 通过$rawfile加载本地资源文件。   
      Web({ src: $rawfile("index.html"), controller: this.controller })   
    }  
  }}
import { webview } from '@kit.ArkWeb'  
  
@Entry  
@Component  
struct Index {  
  controller: webview.WebviewController = new webview.WebviewController()   
  
  build() {  
    Column() {  
      // 通过$rawfile加载本地资源文件。   
      Web({ src: $rawfile("index.html"), controller: this.controller })   
    }  
  }}

调用H5的方法

使用runJavaScript:

js
import { webview } from '@kit.ArkWeb'

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()

  build() {
    Column() {
      Stack({ alignContent: Alignment.TopEnd }) {
        Web({ src: $rawfile("index.html"), controller: this.controller })
        Button() {
          Text("调用JS")  
            .foregroundColor(Color.White)
            .onClick(() => {
              // 执行js代码 `runJavaScript` 
              this.controller.runJavaScript("document.getElementById('xx').style.color = 'red'; changeText();") 
            })
        }
      }
    }
  }
}
import { webview } from '@kit.ArkWeb'

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()

  build() {
    Column() {
      Stack({ alignContent: Alignment.TopEnd }) {
        Web({ src: $rawfile("index.html"), controller: this.controller })
        Button() {
          Text("调用JS")  
            .foregroundColor(Color.White)
            .onClick(() => {
              // 执行js代码 `runJavaScript` 
              this.controller.runJavaScript("document.getElementById('xx').style.color = 'red'; changeText();") 
            })
        }
      }
    }
  }
}

调用H5的方法并获取返回值

runJavaScript 支持参数返回

H5调用原生方法

两种方式:

  • javaScriptProxy()
    • 只能注册一个对象
    • Web组件初始化调用
    • Web组件调用
  • Web组件初始化完成后调用registerJavaScriptProxy()
    • 可以注册多个对象
    • 在Web组件初始化完成后调用
    • webview.WebviewController对象调用

@ohos.web.webview (Webview)-registerJavaScriptProxy
前端页面调用应用侧函数-在应用中使用前端页面JavaScript-ArkWeb(方舟Web

js
registerJavaScriptProxy(
// 参与注册的应用侧JavaScript对象。可以声明方法,也可以声明属性,但是不支持h5直接调用。其中方法的参数和返回类型只能为string,number,boolean
object: object, 
// 	注册对象的名称,与window中调用的对象名一致。注册后window对象可以通过此名字访问应用侧JavaScript对象。
name: string,
// 参与注册的应用侧JavaScript对象的同步方法
methodList: Array<string>, 
// 参与注册的应用侧JavaScript对象的异步方法,默认为空。异步方法无法获取返回值
asyncMethodList?: Array<string>
): void
registerJavaScriptProxy(
// 参与注册的应用侧JavaScript对象。可以声明方法,也可以声明属性,但是不支持h5直接调用。其中方法的参数和返回类型只能为string,number,boolean
object: object, 
// 	注册对象的名称,与window中调用的对象名一致。注册后window对象可以通过此名字访问应用侧JavaScript对象。
name: string,
// 参与注册的应用侧JavaScript对象的同步方法
methodList: Array<string>, 
// 参与注册的应用侧JavaScript对象的异步方法,默认为空。异步方法无法获取返回值
asyncMethodList?: Array<string>
): void

代码示例:

html:

html
<button onclick="callNative()">good</button>
<h1 id="xx"></h1>

<script>
    function callNative() {
        const content = mtBridge.testFunc();
        document.getElementById('xx').innerHTML = content;
    }
</script>
<button onclick="callNative()">good</button>
<h1 id="xx"></h1>

<script>
    function callNative() {
        const content = mtBridge.testFunc();
        document.getElementById('xx').innerHTML = content;
    }
</script>

原生端:

js
import { webview } from '@kit.ArkWeb'

class TestClass { 
  testFunc(): string { 
    return "ArkUI Web Component"; 
  } 
} 

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()
  @State testObj: TestClass = new TestClass();

  build() {
    Column() {
      Stack({ alignContent: Alignment.TopEnd }) {
        Web({ src: $rawfile("index.html"), controller: this.controller })
          .javaScriptProxy({ 
            controller: this.controller, 
            object: this.testObj, 
            name: 'mtBridge', 
            methodList: ['testFunc'], 
            asyncMethodList: [] 
          })        
      }
    }
  }
}
import { webview } from '@kit.ArkWeb'

class TestClass { 
  testFunc(): string { 
    return "ArkUI Web Component"; 
  } 
} 

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()
  @State testObj: TestClass = new TestClass();

  build() {
    Column() {
      Stack({ alignContent: Alignment.TopEnd }) {
        Web({ src: $rawfile("index.html"), controller: this.controller })
          .javaScriptProxy({ 
            controller: this.controller, 
            object: this.testObj, 
            name: 'mtBridge', 
            methodList: ['testFunc'], 
            asyncMethodList: [] 
          })        
      }
    }
  }
}

可能有非常多的桥方法,可以改成如下方式来拆分:

js
function testFunc() {  
  return "ArkUI Web Component";  
}  
  
class TestClass {  
  testFunc = testFunc  
}
function testFunc() {  
  return "ArkUI Web Component";  
}  
  
class TestClass {  
  testFunc = testFunc  
}

动态监听h5标题

获取标题: let title = this.controller.getTitle();

js
import { webview } from '@kit.ArkWeb'

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()
  @State title: string = ""

  build() {
    Column() {
      Text(this.title)
      Button() {
        Text('返回')
          .foregroundColor(Color.White)
          .padding(8)
      }.onClick(() => {
        this.controller.backward()
      })

      Web({ src: 'https://m.baidu.com', controller: this.controller })
        .onPageBegin(() => {
          this.title = ''
        })
        .onPageEnd(() => {
          this.title = this.controller.getTitle(); 
        })
    }
  }
}
import { webview } from '@kit.ArkWeb'

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController()
  @State title: string = ""

  build() {
    Column() {
      Text(this.title)
      Button() {
        Text('返回')
          .foregroundColor(Color.White)
          .padding(8)
      }.onClick(() => {
        this.controller.backward()
      })

      Web({ src: 'https://m.baidu.com', controller: this.controller })
        .onPageBegin(() => {
          this.title = ''
        })
        .onPageEnd(() => {
          this.title = this.controller.getTitle(); 
        })
    }
  }
}

Vue页面的h5加载空白的问题

需要设置,默认是false。

js
.domStorageAccess(true)
.domStorageAccess(true)

如何进行调试

首先确保打开 setWebDebuggingAccess

js
web_webview.WebviewController.setWebDebuggingAccess(true);
web_webview.WebviewController.setWebDebuggingAccess(true);

使用hdc shell后,通过命令获取pid:

hdc shell
$ ps -ef | grep "你的包名关键字" 
exit
hdc shell
$ ps -ef | grep "你的包名关键字" 
exit

实际例子:

shell
  ~ hdc shell
$ ps -ef | grep "aaa"
20020110     42846   617 1 10:50:44 ?     00:00:03 com.aaa.xx
1000093      42972   640 2 10:50:47 ?     00:00:06 com.aaa.xx:render
shell        43525 43462 8 10:54:55 ?     00:00:00 grep aaa
exit
  ~ hdc shell
$ ps -ef | grep "aaa"
20020110     42846   617 1 10:50:44 ?     00:00:03 com.aaa.xx
1000093      42972   640 2 10:50:47 ?     00:00:06 com.aaa.xx:render
shell        43525 43462 8 10:54:55 ?     00:00:00 grep aaa
exit

映射(这里随便指定了9333端口):

shell
hdc fport tcp:9333 localabstract:webview_devtools_remote_42846  #这里我需要的pid为42846
hdc fport tcp:9333 localabstract:webview_devtools_remote_42846  #这里我需要的pid为42846

打开chrome浏览器,输入地址:chrome://inspect#devices ,并配置好端口。

刷新页面就能看到我们需要调试的页面: