Android与js的交互方式

参考
Android:你要的WebView与 JS 交互方式 都在这里了

代码

一.交互方式总起

1.1 Android调用js

 + WebView.loadUrl(“javascript:js方法名”) 
 + WebView.evaluateJavascript("javascript:js方法名")

1.2 js调用Android

+ 通过WebView的addJavascriptInterface()进行对象映射
+ 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url
+ 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

二.Android调用js

2.1 WebView.loadUrl

如果js中有一个方法名为 callByAndroidLoadUrl

function callByAndroidLoadUrl(){
       document.getElementById("demo").innerHTML = "109876"
}

则在android中使用如下代码调用

        web_view.loadUrl("javascript:callByAndroidLoadUrl()")

2.2 WebView.evaluateJavascript

如果js中有一个名为callByAndroidEvaluateJavascript

  function callByAndroidEvaluateJavascript(){
            document.getElementById("demo").innerHTML = "678910"
            return "hahaha"
        }

则在android中使用如下代码调用

    /**
     * 使用WebView.evaluateJavascript调用js
     */
    fun androidInvokeJsByEvaluateJavascript(view: View) {
        web_view.evaluateJavascript("javascript:callByAndroidEvaluateJavascript()") {
            Log.i("MainActivity", it)
        }
    }

2.3 总结

调用方法 有点 缺点 使用场景
使用loadUrl() 方便简洁 效率低;调用的方法不能有返回值,如果方法有返回值,则webview会显示返回的内容 不需要返回值
使用WebView.evaluateJavascript 效率高 仅支持4.4以上 android4.4以上

三.js调用android代码

3.1 WebView的addJavascriptInterface()对象映射

比如 android有一个类InvokeByJs这个类,其中showMsg需要被js调用,则


    inner class InvokeByJS {
        // 被JS调用的方法必须加入@JavascriptInterface注解
        @JavascriptInterface
        fun showMsg(msg: String) {
            Toast.makeText(this@MainActivity, msg, Toast.LENGTH_LONG).show()
        }
    }
   
   //将InvokeByJS类对象映射到js的invokeByJS对象
  web_view.addJavascriptInterface(InvokeByJS(), "invokeByJS")

js中




3.2 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url

js代码



function callAndroidByLoadUrl(){
              document.location = "js://tosat?msg=需要android处理的url";
}

android代码

      //拦截url
        web_view.webViewClient = object : WebViewClient() {

            @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest?
            ): Boolean {

                val url = request?.url.toString()
                if (url.startsWith("js://tosat")) {
                    //得到的url是通过url编码的,所以这里需要url解码
                    val msg =URLDecoder.decode(url).split("msg=")[1]
                    Toast.makeText(this@MainActivity, (msg), Toast.LENGTH_LONG).show()
                    return true
                }

                return false
            }
        }

3.3 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息

以prompt为例
prompt为一个输入框。

Android与js的交互方式_第1张图片
html中prompt调用的输入框

我们可以通过拦截对话框,进行处理。
html中



 function clickPrompt(){
         var result=prompt("js://tosat?msg=通过prompt调用android");
      }

android代码

        web_view.webChromeClient = object :WebChromeClient(){
            override fun onJsPrompt(
                view: WebView?,
                url: String,
                message: String,
                defaultValue: String?,
                result: JsPromptResult
            ): Boolean {
                if(message.startsWith("js://tosat")){
                    val msg =message.split("msg=")[1]
                    Toast.makeText(this@MainActivity, (msg), Toast.LENGTH_LONG).show()
                    //result.confirm必须要赋值,表示prompt的返回值
                    result.confirm("js调用了Android的方法成功啦")
                   //返回true,表示WebChromeClient会处理prompt,WebView不需要弹出输入框
                    return true
                }
                return super.onJsPrompt(view, url, message, defaultValue, result)
            }
        }

3.4总结

调用方法 有点 缺点 使用场景
addJavascriptInterface() 方便简洁;有返回值 Android4.2存在漏洞 Android4.2以上
WebViewClient 的shouldOverrideUrlLoading () 无漏洞 需要自定定义协议;无返回值 不需要返回值
通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息 无漏洞;有返回值 需要自定定义协议 大多数情况下

你可能感兴趣的:(Android与js的交互方式)