美文网首页Android开发Android开发经验谈程序员
使用Kotlin:让Android与JS交互的详解

使用Kotlin:让Android与JS交互的详解

作者: 忞鹿 | 来源:发表于2018-06-11 12:05 被阅读12394次

    先来说说什么是JS交互:
    说的俗一点就是通过我们项目中的控件来调用HTML里的JS代码,也可以通过JS来调用项目中的代码。
    Android与JS之间的桥梁就是WebView了,我们是通过WebView来实现他们的相互调用。
    Android调用Js代码:
    Android调用Js代码有两种方式
    1)通过WebView的loadUrl ()调用
    2)通过WebView的evaluateJavascript ()调用
    Js调用Android代码:
    Js调用Android代码有三种方式
    1)通过WebView的addJavascriptInterface ()进行对象映射
    2)通过WebViewClient的shouldOverrideUrlLoading()来拦截Url调用代

    3)通过WebChromeClient 的onJsAlert()、onJsConfirm()、
    onJsPrompt()拦截JS中的对话框alert() / confirm() / prompt()


    用Kotlin实现Android与JS交互


    一、Android通过 loadUrl ()调用JS代码

    1.把需要调用的JS代码以.Html的格式放到src/main/assets文件夹中,没有的新建一个

    <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>
    </html>
    

    2.在Android中用WebView调用Js代码
    //activity_main.xml布局文件

    <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>
    

    //MainActivity.kt

    class MainActivity : AppCompatActivity() {
    private var androidText : TextView? = null
    private var androidBtn : Button? = null
    private var androidWeb : WebView? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    //        初始化控件
    androidText = findViewById(R.id.android_text)
        androidBtn = findViewById(R.id.android_btn)
        androidWeb = findViewById(R.id.android_web)
    
        val settings = androidWeb!!.settings
    
    //        设置WebView可以与JS交互 这里必须设置
        settings!!.javaScriptEnabled = true
    //        设置允许JS中的弹窗
        settings!!.javaScriptCanOpenWindowsAutomatically = true
    
    //        然后加载JS代码
        androidWeb!!.loadUrl("file:///android_asset/index.html")
    //        调用JS无参方法
        androidBtn!!.setOnClickListener({
            androidWeb!!.post {
                run {
                    //第一种方法 通过loadUrl调用JS代码
                    //调用无参JS方法
                    androidWeb!!.loadUrl("javascript:clickJS()")
                    //调用有参JS方法
                   // androidWeb!!.loadUrl("javascript:clickJS("+"我调用了JS的方法"+")")
                }
            }
        })
      }
    }
    
    富江原创.gif

    Android通过evaluateJavascript ()调用JS代码

    先来说说使用这个方法的优点

     使用这个方法不会刷新页面,如果使用第一种方法则会刷新页面
     *注意 这个方法只能在Android4.4之后使用
    

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

    androidWeb!!.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) {
      androidWeb!!.loadUrl("javascript:clickJS()")
    } else {
      androidWeb!!.evaluateJavascript("javascript:clickJS()", object : ValueCallback<String> {
          override fun onReceiveValue(value: String?) {
          //返回JS方法中的返回值,我们没有写返回值所以为null
          }
       })
    }
    

    二、JS调用Android代码


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

    androidWeb!!.addJavascriptInterface(object : Object(){
            @JavascriptInterface
            fun jsAndroid(msg : String){
              //点击html的Button调用Android的Toast代码  
            //我这里让Toast居中显示了
                val makeText = Toast.makeText(this@MainActivity, msg,Toast.LENGTH_LONG)
                makeText.setGravity(Gravity.CENTER,0,0)
                makeText.show()
            }
          //第二个参数可以自己随便设置,在html里会用到
        },"androids")
    

    2.JS的方法

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

    来看看效果图


    富江原创3.gif

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

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

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

    代码中这样写

    androidWeb!!.webViewClient = object : WebViewClient(){
        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
    //      获取Uri  这里的URL是我们在JS方法中写的URL协议"js://webview?name=zhangsan&age=20&sex=0"
           var 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)
            }
        }
    

    来看一下效果


    富江原创4.gif

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

    <script type="text/javascript">
            function clickAndroid(){
                // 定义一个带输入框的弹窗
                var x = prompt("我又调用了Android的方法");
                alert("我是JS"+x)
            }
    </script>
    

    Android代码

    androidWeb!!.webChromeClient = object : WebChromeClient(){
        override fun onJsPrompt(view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult?): Boolean {
            val makeText = Toast.makeText(this@MainActivity, message, Toast.LENGTH_LONG)
            makeText!!.setGravity(Gravity.CENTER,0,0)
            makeText.show()
            return super.onJsPrompt(view, url, message, defaultValue, result)
        }
    }
    

    效果图


    富江原创5.gif

    三种区别

    1)addJavascriptInterface ()使用起来方便简洁,但是再Android低版本下有问题,用于Android4.4以上

    2)shouldOverrideUrlLoading ()使用起来没有漏洞,但是使用起来比较负责,主要用于不需要返回值的情况

    3)onJsAlert()、onJsConfirm()、onJsPrompt()拦截JS中的对话框alert() / confirm() / prompt()
    和第二种方式一样,没有漏洞,而且也复杂,并且需要协议来规定他。

    相关文章

      网友评论

      • Y_Sunny_U:作者好有才:+1:
      • 小县城公务员:你好!我们是程序员大咖旗下专注于程序员生态的公众号程序员大咖(微信号 CodePush)。我们很赞赏你的文章,希望能获得转载授权。授权后,你的文章将会在公众号程序员大咖、程序员共读、源码共读、Java编程精选、iOS开发等渠道发布。我们会注明来源和作者姓名。
        非常感谢~~~
        小县城公务员:@富江___ 十分感谢~
        忞鹿:@源码共读 好的
      • Villa__Mou:你这kotlin用得。。
        忞鹿:怎么了
      • 卓而不群_0137:有些瑕疵:stuck_out_tongue_winking_eye:
      • 6d21439f7635:杠杠滴!

      本文标题:使用Kotlin:让Android与JS交互的详解

      本文链接:https://www.haomeiwen.com/subject/fhrceftx.html