先來說說什麼是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< ) {
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,,)
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,,)
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,,)
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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。