最近在研究kotlin,今天來整一下kotlin實現安卓和js的互調。大概的方法和java差不多。有一些小地方有差別,這裏寫這篇博客記錄一下,有需要的朋友可以看下。在後面我也會附上源碼。
Android和js的交互主要分爲三種:1,安卓調用js的方法。2,js調用安卓的方法。3,回調,即js調用安卓的方法獲得數據,然後數據回傳給js,js做業務處理。
首先我們用Webview來顯示頁面,如果是簡單的顯示,沒有js操作,就直接mWebView.loadUrl(" file:///android_asset/js.html ")就可以了。但是我們今天要講的是互相交互,當然不能那麼簡單了,首先要對WebView做一些設置。
* 設置webview
*/
var setWebView = {
//1,開啓h5與kotlin的通訊開關
mWebView.settings.javaScriptEnabled = true//可以調用js
//2,設置兩個webviewclient
mWebView.webChromeClient = MyWebChromeClient()
mWebView.webViewClient = MyWebViewClient()
//3設置Android 和 js溝通的橋樑
mWebView.addJavascriptInterface(JavaScriptMoths(this,mWebView),"JavaScriptMoth")
//4,加載這個html頁面
mWebView.loadUrl(" file:///android_asset/js.html ")
}
一,js調用安卓的方法。
如果js要調用安卓的方法,安卓中需要把給js調用的方法全部都放到一個類裏面,我這裏用的是JavaScriptMoths類。然後把js需要調用的方法都寫裏面。而且方法需要加上註解。@JavascriptInterface。然後將這個類添加到webview上就可以了。mWebView.addJavascriptInterface(JavaScriptMoths(this,mWebView),"JavaScriptMoth"),這個方法兩個參數,第一個就是這個接口工具類的對象,第二個就是自己隨便取得別名。js裏面調用直接 window.別名.方法就可以了。
Android的代碼(寫在JavaScriptMoths類裏面)
/**
* js要調用的安卓的無參方法
*/
@JavascriptInterface
fun jsCallAndroidMoth() {
mContext!!.toast("js要調用的安卓的方法")
}
/**
* js要調用的安卓的有參方法
*/
@JavascriptInterface
fun jsCallAndroidMoth2(string: String) {
mContext!!.toast(string)
}
js的代碼
//js調用安卓的無參方法
function callAndroid(){
window.JavaScriptMoth.jsCallAndroidMoth();
}
//js調用安卓的有參方法
function callAndroid2(){
var string= "我來自 js"
window.JavaScriptMoth.jsCallAndroidMoth2(string);
}
二,安卓調用js的方法。
Android調用js方法很簡單,但是有一點,需要html5頁面加載完了纔可以調用。至於什麼時候加載完,我下面的代碼裏面有註釋。直接用 mWebView.loadUrl("javascript:方法名()")就可以了。
js代碼:
//Android調用的無參方法
function callJS(){
alert("Android 調用無參方法!");
}
//Android調用的有參方法
function callJS1(a) {
alert(a);
}
Android代碼:
btn1.onClick {
mWebView.loadUrl("javascript:callJS()")
}
btn2.onClick {
var string= "我是安卓傳過來的參數"
mWebView.loadUrl("javascript:callJS1('$string')")
}
三,回調,即js調用安卓的方法獲得數據,然後數據回傳給js,js做業務處理。
要實現js調用安卓的方法獲得數據,然後再用安卓的方法調用js把數據傳給js,這樣有了上面的一和二步就可以了。但是實際開發中,往往是前端的工作人員寫js,安卓的開發人員寫安卓,當然不排除有些大神,一個人全寫了,這裏不說這種情況。如果js開發人員調用 安卓的 getdata()獲得了數據,然後安卓又調用了js的showAndroidData(string)來展示數據。可是過了一段時間,這個js開發人員想把showAndroidData(string)的名字換一下,這就又要找安卓開發人員改。這個是很麻煩的,於是我就想可以把showAndroidData的名字傳到安卓裏面。具體的實現方法在下面代碼裏面。
js調用Android方法的時候,這個方法添加一個參數,參數傳一個String,這個Srting就是js這邊得到數據之後要回調的方法的名字。
js代碼:
//調用安卓的方法獲得數據,然後用showAndroidData顯示
function getAndroidData(){
window.JavaScriptMoth.getData("showAndroidData");
}
//js調用安卓的方法獲得網絡數據,然後回傳給這個方法,彈出一個對話框,顯示網絡獲得的數據。
function showAndroidData(string){
alert("我是安卓從網上請求的數據:"+string);
}
Android代碼:
/**
* js要調用的安卓的方法,獲得數據,然後把數據回傳給js
*/
@JavascriptInterface
fun getData(jsMothName: String) {
//模擬去網上獲得數據
doAsync {
Thread.sleep(2 * 1000)
var string = "網絡數據"
//回調js的方法。
callbackJs(jsMothName, string)
}
}
/**
* android 回調js,並向js傳數據。
*/
private fun callbackJs(jsMothName: String, string: String) {
//調用js的方法必須在ui線程中運行。
mContext!!.runOnUiThread {
mWebView!!.loadUrl("javascript:$jsMothName('$string')")
}
}
這樣封裝之後,所有的回調都可以用callbackJs(jsMothName: String, string: String)來調用js的方法了。省事了很多。
下面是完整的代碼
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
</head>
<body>
<p>測試Android和js互相調用</p>
<input name="btn1" type="button" value="彈出自己的消息框" onclick="javascript:ceshi();"/>
<input name="btn2" type="button" value="調用安卓的無參方法" onclick="javascript:callAndroid();"/>
<input name="btn2" type="button" value="調用安卓的有參方法" onclick="javascript:callAndroid2();"/>
<p/>
<input name="btn1" type="button" value="js調用安卓方法獲得數據,然後把數據回傳給js"
onclick="javascript:getAndroidData();"/>
<script>
//Android調用的無參方法
function callJS(){
alert("Android 調用無參方法!");
}
//Android調用的有參方法
function callJS1(a) {
alert(a);
}
//js調用安卓的無參方法
function callAndroid(){
window.JavaScriptMoth.jsCallAndroidMoth();
}
//js調用安卓的有參方法
function callAndroid2(){
var string= "我來自 js"
window.JavaScriptMoth.jsCallAndroidMoth2(string);
}
//js自己彈出對話框
function ceshi(){
alert("js自己的彈框");
}
//調用安卓的方法獲得數據,然後用showAndroidData顯示
function getAndroidData(){
window.JavaScriptMoth.getData("showAndroidData");
}
//js調用安卓的方法獲得網絡數據,然後回傳給這個方法,彈出一個對話框,顯示網絡獲得的數據。
function showAndroidData(string){
alert("我是安卓從網上請求的數據:"+string);
}
</script>
</body>
</html>
package com.example.administrator.androidwithjs
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.sdk27.coroutines.onClick
class MainActivity : AppCompatActivity() {
//懶加載
val mWebView: WebView by lazy {
webview
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setWebView()//設置webview
btn1.onClick {
mWebView.loadUrl("javascript:callJS()")
}
btn2.onClick {
var string= "我是安卓傳過來的參數"
mWebView.loadUrl("javascript:callJS1('$string')")
}
}
/**
* 設置webview
*/
var setWebView = {
//1,開啓h5與kotlin的通訊開關
mWebView.settings.javaScriptEnabled = true//可以調用js
//2,設置兩個webviewclient
mWebView.webChromeClient = MyWebChromeClient()
mWebView.webViewClient = MyWebViewClient()
//3設置Android 和 js溝通的橋樑
mWebView.addJavascriptInterface(JavaScriptMoths(this,mWebView),"JavaScriptMoth")
//4,加載這個html頁面
mWebView.loadUrl(" file:///android_asset/js.html ")
}
inner class MyWebChromeClient : WebChromeClient() {
//加載網頁的時候,進度變化
override fun onProgressChanged(view: WebView?, newProgress: Int) {
super.onProgressChanged(view, newProgress)
}
}
inner class MyWebViewClient : WebViewClient() {
//網頁加載完成之後,調用這個方法
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
Log.i("gao", "url = $url")
}
}
}
package com.example.administrator.androidwithjs
import android.content.Context
import android.webkit.JavascriptInterface
import android.webkit.WebView
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.runOnUiThread
import org.jetbrains.anko.toast
/**
* Created by Administrator on 2019/3/13.
*/
class JavaScriptMoths {
var mContext: Context? = null
var mWebView: WebView? = null
constructor(mContext: Context, mWebView: WebView) {
this.mContext = mContext
this.mWebView = mWebView
}
/**
* js要調用的安卓的無參方法
*/
@JavascriptInterface
fun jsCallAndroidMoth() {
mContext!!.toast("js要調用的安卓的方法")
}
/**
* js要調用的安卓的有參方法
*/
@JavascriptInterface
fun jsCallAndroidMoth2(string: String) {
mContext!!.toast(string)
}
/**
* js要調用的安卓的方法,獲得數據,然後把數據回傳給js
*/
@JavascriptInterface
fun getData(jsMothName: String) {
//模擬去網上獲得數據
doAsync {
Thread.sleep(2 * 1000)
var string = "網絡數據"
//回調js的方法。
callbackJs(jsMothName, string)
}
}
/**
* android 回調js,並向js傳數據。
*/
private fun callbackJs(jsMothName: String, string: String) {
//調用js的方法必須在ui線程中運行。
mContext!!.runOnUiThread {
mWebView!!.loadUrl("javascript:$jsMothName('$string')")
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android調用js無參數方法" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android調用js有參數方法" />
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
對了,kotlin裏面我集成了anko implementation "org.jetbrains.anko:anko:0.10.8"
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.example.administrator.androidwithjs"
minSdkVersion 15
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "org.jetbrains.anko:anko:0.10.8"
}
有需要的朋友可以下載源碼。
寫博客不容易,希望轉發的標註,希望看到了對你有幫助,留個評論。如果有什麼疑問,可以加我QQ討論 823987786