Kotlin實現Android與js的互調,js調用安卓方法獲得數據然後傳回js,做邏輯操作

 

          最近在研究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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章