先来说说什么是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文件夹中,没有的新建一个

  <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? = nullprivate var androidBtn : Button? = nullprivate var androidWeb : WebView? = nulloverride 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()  使用起来方便简洁。 但是他是在没有返回的情况下使用。 效率比较低,获取返回值的时候很麻烦。 并且调用的时候会刷新WebView2.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()
和第二种方式一样,没有漏洞,而且也复杂,并且需要协议来规定他。



作者:富江_ed13
链接:https://www.jianshu.com/p/826a39ed81e6
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. android EditText设置不可写
  6. android 使用html5作布局文件: webview跟javascript交互
  7. android实现字体闪烁动画的方法
  8. android studio调试c/c++代码
  9. Android(安卓)Wifi模块分析(三)

随机推荐

  1. [置顶] Android中索引关联联系人
  2. Android(安卓)Odex
  3. [置顶] android DatePicker 点击文本框,禁
  4. 写了个Android聊天客户端框架,基本聊天功
  5. Android(安卓)6.0以上权限拒绝打开权限设
  6. 搭建XMPP协议,实现自主推送消息到手机
  7. 慢学Android(安卓)Jetpack
  8. Android获取View的宽度和高度
  9. Android(安卓)关于引用jackson的jar包混
  10. 转-Lottie开源动画库介绍与使用示例