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