第十章 kotlin与H5混合开发
文章目录
- 第十章 kotlin与H5混合开发
- 前言
- 一、Kotlin与H5通信方式一(H5主动)
- 1.H5调用Kotlin方法
- 二、Kotlin与H5通信方式二(Kotlin主动)
- 1.Kotlin调用H5方法
- 三、Kotlin与H5通信方式三(callback)
- 1.示例1
- 2.示例2
- 四、Kotlin与H5通信-完整代码
- 1.Kotlin与H5通信-完整代码
- 总结
前言
kotlin与H5混合开发。
一、Kotlin与H5通信方式一(H5主动)
1.H5调用Kotlin方法
H5调用Kotlin方法
<script>
$("#btn").on("click",function(){
console.log("点击了");
//调用Kotlin方法
//对象.方法名(参数)
var json = {"name":"html5"}
window.jsInterface.showToast(JSON.stringify(json));
});
</script>
@JavascriptInterface //安卓4.2以后,不加上@JavascriptInterface,H5不能调用kotlin方法
fun showToast(json:String){
//Toast.makeText(mContext,json,Toast.LENGTH_SHORT).show() //Toast方法1
mContext?.let { it.toast(json) } //Toast方法2
}
二、Kotlin与H5通信方式二(Kotlin主动)
1.Kotlin调用H5方法
Kotlin调用H5方法
private inner class MyWebViewClient : WebViewClient() {
//页面加载完成调用
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
var json = JSONObject()
json.put("name","Kotlin")
mWebView.loadUrl("javascript:showMessage($json)") //Kotlin与H5通信方式二(Kotlin主动)
}
}
<script>
var showMessage = function(json){
alert(JSON.stringify(json));
};
</script>
三、Kotlin与H5通信方式三(callback)
H5 callback调用kotlin方法:H5通知Kotlin获取数据,然后Kotlin回传数据给H5
1.示例1
代码:
<script>
<!-- Kotlin与H5通信方式三(callback) -->
//H5 callback调用kotlin方法
$(btn2).on("click",function(){
//callback:1.调用kotlin方法
console.log("callback调用");
window.jsInterface.getStudentData();
});
var receiveStudentData = function(json){
alert(JSON.stringify(json));
};
</script>
@JavascriptInterface
fun getStudentData(){
// println("获取学生数据")
//异步操作,子线程请求服务器
doAsync {
var url = URL("http://192.168.0.103:8080/Test1/student.json")
//变成字符串
val result = url.readText()
println("获取学生数据="+result)
//callback步骤2:回传数据给H5
//调用js方法必须在主线程
mContext?.let {
it.runOnUiThread {
mWebView?.let {
// it.loadUrl("javascript:receiveStudentData("+result+")")
it.loadUrl("javascript:receiveStudentData($result)")
}
}
}
}
}
2.示例2
代码:
<script>
<!-- Kotlin与H5通信方式三(callback) -->
//H5 callback调用kotlin方法:H5通知Kotlin获取数据,然后Kotlin回传数据给H5
//调用kotlin方法获取学生数据
$(btn3).on("click",function(){
//callback:1.调用kotlin方法
console.log("callback调用");
var json = {"callback":"receiveStudentData2"};//设置回调方法名称
window.jsInterface.getStudentData2(JSON.stringify(json));
});
</script>
/**
* Kotlin与H5通信方式三(callback)
*/
@JavascriptInterface
fun getStudentData2(json:String){
var jsJson = JSONObject(json)
var callback = jsJson.optString("callback")
//异步操作,子线程请求服务器
doAsync {
var url = URL("http://192.168.0.103:8080/Test1/student.json")
//变成字符串
val result = url.readText()
println("获取学生数据="+result)
//callback步骤2:回传数据给H5
//调用js方法必须在主线程
// mContext?.let {
// it.runOnUiThread {
// mWebView?.let {
// it.loadUrl("javascript:$callback($result)")
// }
// }
// }
callbackJavaScript(callback, result)
}
}
/**
* 统一管理所有kotlin回调js方法
*/
private fun callbackJavaScript(callback: String?, result: String) {
mContext?.let {
it.runOnUiThread {
mWebView?.let {
it.loadUrl("javascript:$callback($result)")
}
}
}
}
四、Kotlin与H5通信-完整代码
1.Kotlin与H5通信-完整代码
Kotlin与H5通信-完整代码
\webapps\Test1\indexForJSAndKotlin.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>test For JS And Kotlin</title>
<SCRIPT src="js/jquery-1.9.1.min.js" type=text/javascript></SCRIPT>
</head>
<body>
<br/>
<div> H5网页区域:</div>
<input type="button" value="H5调用Kotlin方法" id="btn" />
<input type="button" value="H5 callback调用kotlin方法" id="btn2" />
<br/><br/>
<input type="button" value="H5 callback调用kotlin方法2" id="btn3" />
<br/><br/>
<div id="wrapper" style="background-color:white"/>
<!-- Kotlin与H5通信方式一(H5主动) -->
<script>
<!-- 点击事件-方法1: $("#btn").click(function(){ -->
<!-- 点击事件-方法2: $("#btn").on("click",function(){ -->
$("#btn").on("click",function(){
console.log("点击了");
//调用Kotlin方法
//对象.方法名(参数)
var json = {"name":"html5"}
window.jsInterface.showToast(JSON.stringify(json));
});
var showMessage = function(json){
alert(JSON.stringify(json));
};
<!-- Kotlin与H5通信方式三(callback) -->
//H5 callback调用kotlin方法
$(btn2).on("click",function(){
//callback:1.调用kotlin方法
console.log("callback调用");
window.jsInterface.getStudentData();
});
var receiveStudentData = function(json){
alert(JSON.stringify(json));
};
<!-- Kotlin与H5通信方式三(callback) -->
//H5 callback调用kotlin方法:H5通知Kotlin获取数据,然后Kotlin回传数据给H5
//调用kotlin方法获取学生数据
$(btn3).on("click",function(){
//callback:1.调用kotlin方法
console.log("callback调用");
var json = {"callback":"receiveStudentData2"};//设置回调方法名称
window.jsInterface.getStudentData2(JSON.stringify(json));
});
/**
* H5在线模板刷新数据
*
* 接收kotlin回传的学生数据
* @param json
*/
var receiveStudentData2 = function(json){
//alert(JSON.stringify(json));
//解析,设置到页面中
var nameText = '<section id="studentName" class="studentName"><div><span>学生姓名:</span><i>'+json.name+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var genderText = '<section id="gender"><div><span>性别:</span><i>'+json.gender+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var ageText = '<section id="age"><div><span>年龄:</span><i>'+json.age+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var heightText = '<section id="height"><div><span>身高:</span><i>'+json.height+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var cityText = '<section id="city"><div><span>城市:</span><i>'+json.city+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var weightText = '<section id="weight"><div><span>体重:</span><i>'+json.weight+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var phoneText = '<section id="phone" class="phone"><div><span>电话:</span><i>'+json.phone+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var classText = '<section id="class"><div><span>班级:</span><i>'+json.class+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
var InterestText = '<section id="Interest"><div><span>兴趣爱好:</span><i>'+json.Interest+'</i></div><div style="background-color:#F5F5F5"><br></div> </section>';
//动态刷新数据:
$("#wrapper").html(nameText+genderText+ageText+heightText+cityText+weightText+phoneText+classText+InterestText);
$(".phone").on("click",function(){
//调用kotlin方法
console.log("调用kotlin方法");
window.jsInterface.showPhoneDialog(json.phone);
});
};
</script>
</body>
</html>
\webapps\Test1\student.json
{
"status":"success",
"gender":"男",
"name":"张三",
"age":"20",
"height":"180厘米",
"city":"北京市",
"weight":"60公斤",
"phone":"10086",
"class":"2班",
"Interest":"篮球"
}
\app\src\main\java\com\example\testkotlin1\WebTestActivity.kt
import android.os.Bundle
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_web_test.*
import org.jetbrains.anko.sdk27.coroutines.onClick
import org.json.JSONObject
/**
* Kotlin与H5混合开发练习-知识点:
*
* Kotlin与H5通信的三种方式
* H5 callback调用Kotlin
* 本地模板动态刷新页面
* 自定义Kotlin与H5通信接口协议
*/
class WebTestActivity : AppCompatActivity() {
//懒加载:使用了才初始化
private val mWebView: WebView by lazy {
webview
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_web_test)
tv_title.setText("测试") //直接写View的id(tv_title)即可
//button.onClick { }
setWebView()
}
//lambda表达式-示例
//var add = {a:Int,b:Int -> a + b}
var setWebView = {
//1.开启Kotlin与H5通信开关
mWebView.settings.javaScriptEnabled = true
//2.设置2个WebViewClient
mWebView.webViewClient = MyWebViewClient()
mWebView.webChromeClient = MyWebChromeClient()
//Kotlin与H5通信方式1:H5调用Kotlin方法
//设置Kotlin与H5通信桥梁类
//mWebView.addJavascriptInterface(对象,字符串):对象.方法名, 字符串:就是参数1对象的别名
mWebView.addJavascriptInterface(JavaScriptMethods(this,mWebView),"jsInterface")
//3.加载网页:在线模板,便于调试
// mWebView.loadUrl("http://192.168.0.103:8080/Test1/indexForJSAndKotlin.html")
//本地模板:网页保存到assets目录,提高加载速率
mWebView.loadUrl("file:///android_asset/kotlin/indexForJSAndKotlin.html")
}
private inner class MyWebViewClient : WebViewClient() {
//页面加载完成调用
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
//Kotlin与H5通信方式2:Kotlin调用H5方法
//mWebView.loadUrl("javascript:方法名(参数)")
var json = JSONObject()
json.put("name","Kotlin")
// mWebView.loadUrl("javascript:showMessage("+json.toString()+")")//方法1
mWebView.loadUrl("javascript:showMessage($json)")//方法2 //Kotlin与H5通信方式二(Kotlin主动)
}
}
private class MyWebChromeClient : WebChromeClient() {
//加载进度条
}
}
\app\src\main\java\com\example\testkotlin1\JavaScriptMethods.kt
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.webkit.JavascriptInterface
import android.webkit.WebView
import org.jetbrains.anko.alert
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.runOnUiThread
import org.jetbrains.anko.toast
import org.json.JSONObject
import java.net.URL
/**
* Kotlin与H5通信桥梁类
*/
class JavaScriptMethods {
private var mContext: Context? = null
private var mWebView: WebView? = null
constructor(context: Context?){
this.mContext = context
}
constructor(context: Context?,webView: WebView){
this.mContext = context
this.mWebView = webView
}
@JavascriptInterface //安卓4.2以后,不加上@JavascriptInterface,H5不能调用kotlin方法
fun showToast(json:String){
//Toast.makeText(mContext,json,Toast.LENGTH_SHORT).show() //方法1
// mContext?.toast(json)
mContext?.let { it.toast(json) } //方法2
}
/**
* Kotlin与H5通信方式三(callback)
*/
@JavascriptInterface
fun getStudentData(){
// println("获取学生数据")
//异步操作,子线程请求服务器
doAsync {
var url = URL("http://192.168.0.103:8080/Test1/student.json")
//变成字符串
val result = url.readText()
println("获取学生数据="+result)
//callback步骤2:回传数据给H5
//调用js方法必须在主线程
mContext?.let {
it.runOnUiThread {
mWebView?.let {
// it.loadUrl("javascript:receiveStudentData("+result+")")
it.loadUrl("javascript:receiveStudentData($result)")
}
}
}
}
}
/**
* Kotlin与H5通信方式三(callback)
*/
@JavascriptInterface
fun getStudentData2(json:String){
var jsJson = JSONObject(json)
var callback = jsJson.optString("callback")
//异步操作,子线程请求服务器
doAsync {
var url = URL("http://192.168.0.103:8080/Test1/student.json")
//变成字符串
val result = url.readText()
println("获取学生数据="+result)
//callback步骤2:回传数据给H5
//调用js方法必须在主线程
// mContext?.let {
// it.runOnUiThread {
// mWebView?.let {
// it.loadUrl("javascript:$callback($result)")
// }
// }
// }
callbackJavaScript(callback, result)
}
}
/**
* 统一管理所有kotlin回调js方法
*/
private fun callbackJavaScript(callback: String?, result: String) {
mContext?.let {
it.runOnUiThread {
mWebView?.let {
it.loadUrl("javascript:$callback($result)")
}
}
}
}
//底部弹出拨号对话框
@JavascriptInterface
fun showPhoneDialog(phone:String){
println("js传递="+phone)
//设置号码到对话框
mContext?.let {
it.alert("你要拨打电话${phone}吗?", "拨打电话") {
positiveButton("ok" ) {
mContext?.let { callPhone(phone) }
}
negativeButton("cancel") {
}
}.show()
}
}
/**
* lambda表达式:调用系统拨号功能
*/
var callPhone = {
//phone:String -> Unit
phone:String ->
var intent = Intent()
intent.action = "android.intent.action.VIEW"
intent.action = "android.intent.action.DIAL"
intent.addCategory("android.intent.category.DEFAULT")
intent.addCategory("android.intent.category.BROWSABLE")
intent.setData(Uri.parse("tel:"+phone))
mContext?.let { it.startActivity(intent) }
}
}
\app\src\main\res\layout\activity_web_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Hello World!"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="js调用Kotlin方法"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />-->
<!--<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="js调用Kotlin方法(callback)"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button" />-->
<WebView
android:id="@+id/webview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
\app\src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testkotlin1">
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestKotlin1"
android:usesCleartextTraffic="true">
<activity android:name=".WebTestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
本地模板 - 网页保存到assets目录,提高加载速率:
APP截屏:
总结
以上就是今天要讲的内容,本文仅仅简单介绍了kotlin与H5混合开发知识。