Android与JS交互详解

转自让Android与JS交互的详解_android js交互_低调函数的博客-CSDN博客

略微改动与拓展

一、什么是JS交互

先来说说什么是JS交互:
说的俗一点就是通过我们项目中的控件来调用HTML里的JS代码,也可以通过JS来调用项目中的代码。
Android与JS之间的桥梁就是WebView了,我们是通过WebView来实现他们的相互调用。
Android调用Js代码:
Android调用Js代码有两种方式

  • 通过WebView的loadUrl ()调用
  • 通过WebView的evaluateJavascript ()调用

Js调用Android代码:
Js调用Android代码有三种方式

  • 通过WebView的addJavascriptInterface ()进行对象映射
  • 通过WebViewClient的shouldOverrideUrlLoading()来拦截Url调用代 码
  • 通过WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()拦截JS中的对话框alert() / confirm() / prompt()

二 Android调用JS的代码

2.1 Android通过loadUrl()调用JS代码

JS写的Html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Android与Js交互</title>
</head>
<body>
//JS的代码
<script type="text/javascript">
              //无参方法
            function clickJS(){
                document.getElementById("zi").innerHTML = "Android调用了JS代码"
            }
             //有参方法
            function clickJSTwo(x){
                document.getElementById("zi").innerHTML = x
            }
        //与Android交互的方法
            function clickAndroid(){
                var result = prompt("js://webview?arg1=111&arg2=222")
                alert("demo" + result)
            }
        </script>

<button type="button" onclick="clickAndroid()">我是一个按钮</button>

<p id="zi">在这里改变代码</p>

</body>

<script type="text/javascript">
    function clickAndroid(){
        //用androids.调用映射的对象    这里的androids是addJavascriptInterface()的第二个参数
        androids.jsAndroid("我是JS,我调用了Android的方法")
    }
</script>
</html>

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/android_js"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:text="调用JS代码"
        android:id="@+id/android_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <WebView
        android:id="@+id/android_web"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </WebView>
</LinearLayout>

android代码:

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        val webview = findViewById<WebView>(R.id.android_web)
            webview.settings.javaScriptEnabled = true     //设置WebView可以与JS交互 这里必须设置
            webview.settings.javaScriptCanOpenWindowsAutomatically  = true  //设置允许JS中的弹窗
            webview.loadUrl("file:///android_asset/web1.html")
        val android_btn = findViewById<Button>(R.id.android_btn)
            android_btn.setOnClickListener {
                webview.post {
                    kotlin.run {
                        //第一种方法 通过loadUrl调用JS代码
                        //调用无参JS方法
                        webview.loadUrl("javascript:clickJS()")
                        //调用有参JS方法
                        // androidWeb.loadUrl("javascript:clickJS('我调用了JS的方法')")
                    }
                }
            }

    }
}

在这里插入图片描述

2.2 Android通过evaluateJavascript ()调用JS代码

使用这个方法不会重新刷新webView,而loadUrl会触发刷新,且这个方法必须要在Android4.4以上才可以使用

使用方式:
1.将minSdkVersion最低版本改为19
build.gradle----minSdkVersion
2.直接替换第一种方式

webview.evaluateJavascript("javascript:clickJS()",object :
         ValueCallback<String> {
        override fun onReceiveValue(value: String?) {
//    这里返回JS的结果
       }
})

两种方式的区别:

  • 1.loadUrl() 使用起来方便简洁。 但是他是在没有返回的情况下使用。 效率比较低,获取返回值的时候很麻烦。 并且调用的时候会刷新WebView
  • 2.evaluateJavascript () 效率比loadUrl ()高很多 虽然效率高但是只支持Android4.4以上 在获取返回值时候很方便 调用时候不刷新WebView

根据情况使用两种方式,我们可以根据当前项目开发的需求选择相应的使用方式
我们可以直接判断版本号来区分使用方式

if (Build.VERSION.SDK_INT< 18) {
  android_web.loadUrl("javascript:clickJS()")
} else {
  android_web.evaluateJavascript("javascript:clickJS()") {
    //返回JS方法中的返回值,我们没有写返回值所以为null
  }
}

三 JS调用Android代码

3.1 使用WebView的addJavascriptInterface()进行对象映射

JS代码:

<script type="text/javascript">
    function clickAndroid(){
        //用android.调用映射的对象    这里的android是addJavascriptInterface()的第二个参数
        android.jsAndroid("我是JS,我调用了Android的方法")
    }
</script>

Android代码:

 webview.addJavascriptInterface(JsObject(),"android")
inner class JsObject {
    @JavascriptInterface
    fun jsAndroid(msg : String){
        //点击html的Button调用Android的Toast代码
        //我这里让Toast居中显示了
        val makeText = Toast.makeText(this@MainActivity2, msg,Toast.LENGTH_LONG)
        makeText.setGravity(Gravity.CENTER,0,0)
        makeText.show()
    }
}

来看看效果图
在这里插入图片描述

3.2 使用WebViewClient ()的shouldOverrideUrlLoading ()方法拦截Url调用Android代码

使用这个方式需要定义一个协议进行拦截

<script type="text/javascript">
    function clickAndroid(){
        //定义url协议
        document.location = "js://webview?name=zhangsan&age=20&sex=0"
    }   
</script>

 Android代码:

webview.webViewClient = MyWebViewClient()

inner class MyWebViewClient : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
//      获取Uri  这里的URL是我们在JS方法中写的URL协议"js://webview?name=zhangsan&age=20&sex=0"
      val uri = Uri.parse(url)
      if (uri.scheme == "js") {
        if (uri.authority == "webview") {
          val makeText = Toast.makeText(this@MainActivity, url, Toast.LENGTH_LONG)
          makeText.setGravity(Gravity.CENTER, 0, 0)
          makeText.show()
        }
        return true
      }
      return super.shouldOverrideUrlLoading(view, url)
    }
  }

来看一下效果

在这里插入图片描述

3.3 使用WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()拦截JS中的对话框alert() / confirm() / prompt()

JS代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 id="h">欢迎光临启舰的blog</h1>
<button onclick="confirm('确认')">confirm</button>
<button onclick="alert('弹窗')">alert</button>
<button onclick="prompt('prompt')">prompt</button>
<button onclick="log()">log</button>
</body>

<script type="text/javascript">
function log(){
  console.log("console.log");
  console.warn("warnning");
  console.error("error");
}
</script>
</html>

Android代码:

class MainActivity : AppCompatActivity() {

    var mWebView:WebView?=null

    inner  class MyWebChromeClient:WebChromeClient(){

        override fun onJsAlert(
            view: WebView?,
            url: String?,
            message: String?,
            result: JsResult?
        ): Boolean {
            Log.d("luojie","$message + $result")
            return super.onJsAlert(view, url, message, result)
        }

        override fun onJsPrompt(
            view: WebView?,
            url: String?,
            message: String?,
            defaultValue: String?,
            result: JsPromptResult?
        ): Boolean {
            Log.d("luojie","$message + $result")
            return super.onJsPrompt(view, url, message, defaultValue, result)
        }

        override fun onJsConfirm(
            view: WebView?,
            url: String?,
            message: String?,
            result: JsResult?
        ): Boolean {
            Log.d("luojie","$message + $result")
            return super.onJsConfirm(view, url, message, result)
        }

        override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
            Log.d("luojie","${consoleMessage?.message()}")
            return super.onConsoleMessage(consoleMessage)
        }

        override fun onProgressChanged(view: WebView?, newProgress: Int) {
            Log.d("luojie","${newProgress}")
            super.onProgressChanged(view, newProgress)
        }


    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mWebView = findViewById(R.id.webview)
        mWebView?.settings?.javaScriptEnabled = true
        mWebView?.webViewClient = WebViewClient()
        mWebView?.webChromeClient = MyWebChromeClient()
        mWebView?.loadUrl("file:///android_asset/web.html")

    }
}

拓展:

WebViewClient与WebChromeClient的区别

Android应用开发的时候可能会用到WebView这个组件,使用过程中可能会接触到WebViewClient与WebChromeClient,那么这两个类到底有什么不同呢?

WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:

onLoadResource
onPageStart
onPageFinish
onReceiveError
onReceivedHttpAuthRequest

WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如

onCloseWindow(关闭WebView)
onCreateWindow()
onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
onJsPrompt
onJsConfirm
onProgressChanged
onReceivedIcon
onReceivedTitle

看上去他们有很多不同,实际使用的话,如果你的WebView只是用来处理一些html的页面内容,只用WebViewClient就行了,如果需要更丰富的处理效果,比如JS、进度条等,就要用到WebChromeClient。

猜你喜欢

转载自blog.csdn.net/u013773608/article/details/129277917