Android与JavaScript交互上(获取Html内容)

1,346 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

在Android开发中,一般通过WebView实现与JavaScript的交互(还有其他更高级的方法!)。WebView用于加载网页内容,如果需要对该网页进行交互操作,可以通过添加一个 JavascriptInterface 交互对象,在恰当的时候调用Js语句运行接口中对应的方法,进行交互操作。

以交互掘金页面为例子。

  • 开启JavaScript:拿到webView后设置javaScriptEnabled=true,开启JavaScript。
  • 设置UserAgent:userAgentString非必需,如果需要对网页的某个元素进行解析,最好进行设置。因为一般网页会对不同浏览器进行适配,使得浏览器之间的Html代码会有差异,而导致解析失败。设置方法:电脑浏览器打开目标网页,F12开启后台模式,左上角切换到手机模式,找到user-agent(具体见下图)复制粘贴。
  • 设置交互对象:webView.addJavascriptInterface(JavaOBjectJsInterface(),"testJs")添加一个用于交互的对象,交互方法在类JavaOBjectJsInterface()中,testJs是一个自定义的名字。Js语句通过testJs调用到JavaOBjectJsInterface()内的方法。
  • 设置webClient开启交互:重写onPageFinished(view, url)方法。该方法在网页加载完成时调用,一般这个时候可以拿到完整的网页Html代码。Js语句document.getElementsByTagName('body')[0].innerHTML可以拿到网页<body>块代码,将该代码作为参数传入交互方法test(html)中。webView运行javascript:window.testJs.test(document.getElementsByTagName('body')[0].innerHTML,通过上一步设置交互对象传入的testJs调用到接口对象中的test(html)方法,实现交互。
  • 实现交互:test(html)中,通过Jsoup(一个网页解析框架)对<body>块代码进行解析,通过在网页端获得的按钮class名获取到目标元素。
val link="https://juejin.cn/?utm_source=gold_browser_extension"
val webView=findViewById<WebView>(R.id.webview)
webView.settings.run {
    javaScriptEnabled=true  //开启Js
    userAgentString="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Mobile Safari/537.36"
    useWideViewPort=true
    loadWithOverviewMode=true
    setSupportZoom(true)
    javaScriptCanOpenWindowsAutomatically=true
    loadsImagesAutomatically=true
    defaultTextEncodingName="utf - 8"
}
webView.webViewClient=object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        webView.loadUrl("javascript:window.testJs.test(document.getElementsByTagName('body')[0].innerHTML);")
    }
}
webView.addJavascriptInterface(JavaOBjectJsInterface(),"testJs")
webView.loadUrl(link)
class JavaOBjectJsInterface {
    
    private val TAG = JavaOBjectJsInterface::class.java.simpleName

    @JavascriptInterface
    fun test(html: String) {
        val document = Jsoup.parse(html)
        val btn=document.getElementsByClass("seach-icon-container")
        Log.d(TAG, "btn:" + btn);
    }
}

截屏2022-05-27 下午11.49.08.png 获取目标网页UserAgent

截屏2022-05-27 下午11.55.24.png 运行结果