先來說說什么是JS交互:
說的俗一點(diǎn)就是通過我們項(xiàng)目中的控件來調(diào)用HTML里的JS代碼,也可以通過JS來調(diào)用項(xiàng)目中的代碼雪情。
Android與JS之間的橋梁就是WebView了,我們是通過WebView來實(shí)現(xiàn)他們的相互調(diào)用你辣。
Android調(diào)用Js代碼:
Android調(diào)用Js代碼有兩種方式
1)通過WebView的loadUrl ()調(diào)用
2)通過WebView的evaluateJavascript ()調(diào)用
Js調(diào)用Android代碼:
Js調(diào)用Android代碼有三種方式
1)通過WebView的addJavascriptInterface ()進(jìn)行對(duì)象映射
2)通過WebViewClient的shouldOverrideUrlLoading()來攔截Url調(diào)用代
碼
3)通過WebChromeClient 的onJsAlert()巡通、onJsConfirm()、
onJsPrompt()攔截JS中的對(duì)話框alert() / confirm() / prompt()
用Kotlin實(shí)現(xiàn)Android與JS交互
一舍哄、Android通過 loadUrl ()調(diào)用JS代碼
1.把需要調(diào)用的JS代碼以.Html的格式放到src/main/assets文件夾中宴凉,沒有的新建一個(gè)
<html>
<head>
<meta charset="utf-8" />
<title>Android與Js交互</title>
</head>
<body>
//JS的代碼
<script type="text/javascript">
//無(wú)參方法
function clickJS(){
document.getElementById("zi").innerHTML = "Android調(diào)用了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()">我是一個(gè)按鈕</button>
<p id="zi">在這里改變代碼</p>
</body>
</html>
2.在Android中用WebView調(diào)用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="調(diào)用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() {
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val settings = android_web.settings
// 設(shè)置WebView可以與JS交互 這里必須設(shè)置
settings.javaScriptEnabled = true
// 設(shè)置允許JS中的彈窗
settings.javaScriptCanOpenWindowsAutomatically = true
// 然后加載JS代碼
android_web.loadUrl("file:///android_asset/index.html")
// 調(diào)用JS無(wú)參方法
android_btn.setOnClickListener {
android_web.post {
run {
//第一種方法 通過loadUrl調(diào)用JS代碼
//調(diào)用無(wú)參JS方法
android_web.loadUrl("javascript:clickJS()")
//調(diào)用有參JS方法
// androidWeb.loadUrl("javascript:clickJS('我調(diào)用了JS的方法')")
}
}
}
}
}
Android通過evaluateJavascript ()調(diào)用JS代碼
先來說說使用這個(gè)方法的優(yōu)點(diǎn)
使用這個(gè)方法不會(huì)刷新頁(yè)面,如果使用第一種方法則會(huì)刷新頁(yè)面
*注意 這個(gè)方法只能在Android4.4之后使用
使用方式
1.將minSdkVersion最低版本改為19
build.gradle----minSdkVersion
2.直接替換第一種方式
androidWeb.evaluateJavascript("javascript:clickJS()",object : ValueCallback<String>{
override fun onReceiveValue(value: String?) {
// 這里返回JS的結(jié)果
}
})
兩種方式的區(qū)別
1.loadUrl()
使用起來方便簡(jiǎn)潔蠢熄。
但是他是在沒有返回的情況下使用跪解。
效率比較低,獲取返回值的時(shí)候很麻煩签孔。
并且調(diào)用的時(shí)候會(huì)刷新WebView
2.evaluateJavascript ()
效率比loadUrl ()高很多
雖然效率高但是只支持Android4.4以上
在獲取返回值時(shí)候很方便
調(diào)用時(shí)候不刷新WebView
根據(jù)情況使用兩種方式
我們可以根據(jù)當(dāng)前項(xiàng)目開發(fā)的需求選擇相應(yīng)的使用方式
我們可以直接判斷版本號(hào)來區(qū)分使用方式
if (Build.VERSION.SDK_INT< 18) {
android_web.loadUrl("javascript:clickJS()")
} else {
android_web.evaluateJavascript("javascript:clickJS()") {
//返回JS方法中的返回值叉讥,我們沒有寫返回值所以為null
}
}
二、JS調(diào)用Android代碼
1.使用WebView的addJavascriptInterface()進(jìn)行對(duì)象映射
android_web.addJavascriptInterface(JsObject(),"android")
inner class JsObject {
@JavascriptInterface
fun jsAndroid(msg : String){
//點(diǎn)擊html的Button調(diào)用Android的Toast代碼
//我這里讓Toast居中顯示了
val makeText = Toast.makeText(this@MainActivity, msg,Toast.LENGTH_LONG)
makeText.setGravity(Gravity.CENTER,0,0)
makeText.show()
}
}
2.JS的方法
<script type="text/javascript">
function clickAndroid(){
//用androids.調(diào)用映射的對(duì)象 這里的androids是addJavascriptInterface()的第二個(gè)參數(shù)
androids.jsAndroid("我是JS,我調(diào)用了Android的方法")
}
</script>
來看看效果圖
2.使用WebViewClient ()的shouldOverrideUrlLoading ()方法攔截Url調(diào)用Android代碼
使用這個(gè)方式需要定義一個(gè)協(xié)議進(jìn)行攔截
<script type="text/javascript">
function clickAndroid(){
//定義url協(xié)議
document.location = "js://webview?name=zhangsan&age=20&sex=0"
}
</script>
代碼中這樣寫
android_web.webViewClient = MyWebViewClient()
inner class MyWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
// 獲取Uri 這里的URL是我們?cè)贘S方法中寫的URL協(xié)議"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.使用WebChromeClient的onJsAlert()饥追、onJsConfirm()图仓、onJsPrompt()攔截JS中的對(duì)話框alert() / confirm() / prompt()
<script type="text/javascript">
function clickAndroid(){
// 定義一個(gè)帶輸入框的彈窗
var x = prompt("我又調(diào)用了Android的方法");
alert("我是JS"+x)
}
</script>
Android代碼
android_web.webViewClient = MyWebViewClient()
inner class MyWebChromeClient : 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)
}
}
效果圖
三種區(qū)別
1)addJavascriptInterface ()使用起來方便簡(jiǎn)潔,但是再Android低版本下有問題但绕,用于Android4.4以上
2)shouldOverrideUrlLoading ()使用起來沒有漏洞救崔,但是使用起來比較負(fù)責(zé)惶看,主要用于不需要返回值的情況
3)onJsAlert()、onJsConfirm()六孵、onJsPrompt()攔截JS中的對(duì)話框alert() / confirm() / prompt()
和第二種方式一樣纬黎,沒有漏洞,而且也復(fù)雜劫窒,并且需要協(xié)議來規(guī)定他本今。