1.首先我们来了解一下什么是JSBridge?
在开发中,为了追求开发的效率以及移植的便利性,一些展示性强的页面我们会偏向于使用h5来完成,功能性强的页面我们会偏向于使用native来完成,而一旦使用了h5,为了在h5中尽可能的得到native的体验,我们native层需要暴露一些方法给js调用,比如,弹Toast提醒,弹Dialog,分享等等,有时候甚至把h5的网络请求放到native去完成。
JSBridge做得好的一个典型就是微信,微信给开发者提供了JS SDK,该SDK中暴露了很多微信native层的方法,比如支付,定位等。
请注意:使用JSBridge框架来实现Android与H5交互和
普通的Android与H5交互(详见混合开发:Android和H5(Js)交互_android和h5混合开发是不一样的,Android端和H5端写法都不一样,所以如果Android端使用JSBridge框架写了Android与H5交互,要同步到H5端,让他也改成这种方式,不然Android与H5交互无法生效。
2.引入jsbridge依赖,在app的build.gradle中添加依赖
dependencies {
api "com.github.lzyzsd:jsbridge:1.0.4"
}
在项目的build.gradle中添加,然后同步项目。
repositories {
maven { url "https://jitpack.io" }
}
3.xml中的代码,这里用的ViewDataBinding方式写的:
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".ui.JsbridgeActivity">
<data>
<import type="android.view.View" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="UselessLeaf">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_73"
android:background="@color/color_FFFFFFFF"
app:contentInsetStart="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_25" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_48"
tools:ignore="UselessLeaf">
<FrameLayout
android:id="@+id/layout_back"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imv_back"
android:layout_width="@dimen/dp_9"
android:layout_height="@dimen/dp_16"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dp_12"
android:layout_marginEnd="@dimen/dp_12"
android:src="@mipmap/icon_arrowhead_left"
android:visibility="visible"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tev_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/mounting"
android:textColor="@color/color_80000000"
android:textSize="@dimen/sp_18" />
</FrameLayout>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tev_function_to_js"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/color_FFD0D6EC"
android:padding="@dimen/dp_10"
android:text="@string/function_to_js"
android:textColor="@color/color_FF198CFF"
android:textSize="@dimen/sp_16" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:background="@color/color_80000000" />
<TextView
android:id="@+id/tev_function_to_js2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/color_FFD0D6EC"
android:padding="@dimen/dp_10"
android:text="@string/function_to_js2"
android:textColor="@color/color_FF198CFF"
android:textSize="@dimen/sp_16" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:background="@color/color_80000000" />
<com.github.lzyzsd.jsbridge.BridgeWebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
4.BaseActivity中的代码:
package com.phone.library_common.base
import android.app.ActivityManager
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.os.Looper
import android.os.Process
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import com.gyf.immersionbar.ImmersionBar
import com.phone.library_common.BaseApplication
import com.phone.library_common.R
import com.phone.library_common.manager.ActivityPageManager
import com.phone.library_common.manager.CrashHandlerManager
import com.phone.library_common.manager.LogManager
import com.phone.library_common.manager.ResourcesManager
import com.phone.library_common.manager.ToolbarManager
import com.phone.library_common.manager.ToolbarManager.Companion.assistActivity
import com.qmuiteam.qmui.widget.QMUILoadingView
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity
abstract class BaseBindingRxAppActivity<DB : ViewDataBinding> : RxAppCompatActivity(), IBaseView {
private val TAG = BaseBindingRxAppActivity::class.java.simpleName
protected lateinit var loadView: QMUILoadingView
protected lateinit var layoutParams: FrameLayout.LayoutParams
//该类绑定的ViewDataBinding
protected lateinit var mDatabind: DB
protected lateinit var mRxAppCompatActivity: RxAppCompatActivity
protected lateinit var mBaseApplication: BaseApplication
private var mActivityPageManager: ActivityPageManager? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mRxAppCompatActivity = this
mBaseApplication = application as BaseApplication
mActivityPageManager = ActivityPageManager.get()
mActivityPageManager?.addActivity(this)
mDatabind = DataBindingUtil.setContentView(this, initLayoutId())
mDatabind.lifecycleOwner = mRxAppCompatActivity
initData()
initViews()
loadView = QMUILoadingView(this)
loadView.also {
it.visibility = View.GONE
it.setSize(100)
it.setColor(ResourcesManager.getColor(R.color.color_333333))
}
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT
)
layoutParams.gravity = Gravity.CENTER
addContentView(loadView, layoutParams)
initLoadData()
}
override fun onConfigurationChanged(newConfig: Configuration) {
//非默认值
if (newConfig.fontScale != 1f) {
resources
}
super.onConfigurationChanged(newConfig)
}
override fun getResources(): Resources? { //还原字体大小
val res = super.getResources()
//非默认值
if (res.configuration.fontScale != 1f) {
val newConfig = Configuration()
newConfig.setToDefaults() //设置默认
res.updateConfiguration(newConfig, res.displayMetrics)
}
return res
}
protected abstract fun initLayoutId(): Int
protected open fun setToolbar(isDarkFont: Boolean) {
if (isDarkFont) {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
} else {
ImmersionBar.with(this)
.statusBarDarkFont(isDarkFont)
.statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
}
ToolbarManager.assistActivity(findViewById(android.R.id.content))
}
protected open fun setToolbar(isDarkFont: Boolean, isResizeChildOfContent: Boolean) {
if (isDarkFont) {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(R.color.color_FFFFFFFF) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
} else {
ImmersionBar.with(this)
.statusBarDarkFont(isDarkFont)
.statusBarColor(R.color.color_FF198CFF) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
}
if (isResizeChildOfContent) {
ToolbarManager.assistActivity(findViewById(android.R.id.content))
}
}
protected open fun setToolbar(isDarkFont: Boolean, color: Int) {
if (isDarkFont) {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(color) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.init()
} else {
ImmersionBar.with(this)
.statusBarDarkFont(isDarkFont)
.statusBarColor(color) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.init()
}
ToolbarManager.assistActivity(findViewById(android.R.id.content))
}
protected open fun setToolbar(
isDarkFont: Boolean,
color: Int,
isResizeChildOfContent: Boolean
) {
if (isDarkFont) {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(color) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.init()
} else {
ImmersionBar.with(this)
.statusBarDarkFont(isDarkFont)
.statusBarColor(color) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.init()
}
if (isResizeChildOfContent) {
ToolbarManager.assistActivity(findViewById(android.R.id.content))
}
}
protected open fun setToolbar2(isDarkFont: Boolean, statusBarColor: Int) {
if (isDarkFont) {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
} else {
ImmersionBar.with(this)
.statusBarDarkFont(isDarkFont)
.statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
}
}
/**
* 顶部栏吸顶专用
*/
protected open fun setToolbar2(
isDarkFont: Boolean,
statusBarColor: Int,
isResizeChildOfContent: Boolean
) {
if (isDarkFont) {
val window = window
window.clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = Color.TRANSPARENT
// window.setNavigationBarColor(Color.TRANSPARENT);
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
} else {
ImmersionBar.with(this) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
.statusBarDarkFont(isDarkFont)
.statusBarColor(statusBarColor) //状态栏颜色,不写默认透明色
// .autoStatusBarDarkModeEnable(true, 0.2f) //自动状态栏字体变色,必须指定状态栏颜色才可以自动变色哦
.keyboardEnable(true)
.init()
val window = window
window.clearFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.statusBarColor = Color.TRANSPARENT
// window.setNavigationBarColor(Color.TRANSPARENT);
}
if (isResizeChildOfContent) {
assistActivity(findViewById(android.R.id.content))
}
}
protected abstract fun initData()
protected abstract fun initViews()
protected abstract fun initLoadData()
protected open fun showToast(message: String?, isLongToast: Boolean) {
// Toast.makeText(this, message, Toast.LENGTH_LONG).show();
if (!mRxAppCompatActivity.isFinishing) {
val toast: Toast
val duration: Int
duration = if (isLongToast) {
Toast.LENGTH_LONG
} else {
Toast.LENGTH_SHORT
}
toast = Toast.makeText(mRxAppCompatActivity, message, duration)
toast.setGravity(Gravity.CENTER, 0, 0)
toast.show()
}
}
protected open fun showCustomToast(
left: Int, right: Int,
textSize: Int, textColor: Int,
bgColor: Int, height: Int,
roundRadius: Int, message: String?,
isLongToast: Boolean
) {
val frameLayout = FrameLayout(this)
val layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT
)
frameLayout.layoutParams = layoutParams
val textView = TextView(this)
val layoutParams1 = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height)
textView.layoutParams = layoutParams1
textView.setPadding(left, 0, right, 0)
textView.textSize = textSize.toFloat()
textView.setTextColor(textColor)
textView.gravity = Gravity.CENTER
textView.includeFontPadding = false
val gradientDrawable = GradientDrawable() //创建drawable
gradientDrawable.setColor(bgColor)
gradientDrawable.cornerRadius = roundRadius.toFloat()
textView.background = gradientDrawable
textView.text = message
frameLayout.addView(textView)
val toast = Toast(this)
toast.setView(frameLayout)
if (isLongToast) {
toast.duration = Toast.LENGTH_LONG
} else {
toast.duration = Toast.LENGTH_SHORT
}
toast.show()
}
open fun isOnMainThread(): Boolean {
return Looper.getMainLooper().thread.id == Thread.currentThread().id
}
protected open fun startActivity(cls: Class<*>?) {
val intent = Intent(this, cls)
startActivity(intent)
}
protected open fun startActivityForResult(cls: Class<*>?, requestCode: Int) {
val intent = Intent(this, cls)
startActivityForResult(intent, requestCode)
}
open fun getActivityPageManager(): ActivityPageManager? {
return mActivityPageManager
}
private fun killAppProcess() {
LogManager.i(TAG, "killAppProcess")
val manager =
mBaseApplication.getSystemService(ACTIVITY_SERVICE) as ActivityManager
val processInfos = manager.runningAppProcesses
// 先杀掉相关进程,最后再杀掉主进程
for (runningAppProcessInfo in processInfos) {
if (runningAppProcessInfo.pid != Process.myPid()) {
Process.killProcess(runningAppProcessInfo.pid)
}
}
LogManager.i(TAG, "执行killAppProcess,應用開始自殺")
val crashHandlerManager = CrashHandlerManager.get()
crashHandlerManager?.saveTrimMemoryInfoToFile("执行killAppProcess,應用開始自殺")
try {
Thread.sleep(1000)
} catch (e: InterruptedException) {
LogManager.i(TAG, "error")
}
Process.killProcess(Process.myPid())
// 正常退出程序,也就是结束当前正在运行的 java 虚拟机
System.exit(0)
}
override fun onDestroy() {
if (mActivityPageManager?.mIsLastAliveActivity?.get() == true) {
killAppProcess()
}
mActivityPageManager?.removeActivity(mRxAppCompatActivity)
super.onDestroy()
}
}
5.Activity中的代码:
package com.phone.module_square.ui
import android.net.Uri
import android.os.Build
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import com.alibaba.android.arouter.facade.annotation.Route
import com.github.lzyzsd.jsbridge.CallBackFunction
import com.github.lzyzsd.jsbridge.DefaultHandler
import com.google.gson.Gson
import com.phone.library_common.base.BaseBindingRxAppActivity
import com.phone.library_common.bean.UserBean
import com.phone.library_common.manager.LogManager
import com.phone.library_common.manager.ResourcesManager
import com.phone.module_square.R
import com.phone.module_square.databinding.SquareActivityJsbridgeBinding
@Route(path = "/module_square/jsbridge")
class JsbridgeActivity : BaseBindingRxAppActivity<SquareActivityJsbridgeBinding>() {
companion object {
private val TAG = JsbridgeActivity::class.java.simpleName
}
override fun initLayoutId(): Int {
return R.layout.square_activity_jsbridge
}
override fun initData() {
}
override fun initViews() {
setToolbar(true)
mDatabind.imvBack.setColorFilter(ResourcesManager.getColor(R.color.color_80000000))
mDatabind.tevFunctionToJs.setOnClickListener {
val userBean = UserBean()
userBean.id = 1
userBean.userId = "100"
userBean.birthday = "1998.05.10"
userBean.salary = 7000.0
mDatabind.webView.callHandler(
"functionToJs",
Gson().toJson(userBean),
CallBackFunction {
LogManager.i(TAG, "reponse data from JS $it")
})
}
mDatabind.tevFunctionToJs2.setOnClickListener {
mDatabind.webView.callHandler(
"functionToJs2",
"data from Android",
CallBackFunction { data ->
LogManager.i(TAG, "reponse data from JS $data")
})
}
mDatabind.webView.apply {
setDefaultHandler(DefaultHandler())
getSettings().setAllowFileAccess(true)
getSettings().setAppCacheEnabled(true)
getSettings().setDatabaseEnabled(true)
// 允许网页定位
// 允许网页定位
getSettings().setGeolocationEnabled(true)
// 允许网页弹对话框
// 允许网页弹对话框
getSettings().setJavaScriptCanOpenWindowsAutomatically(true)
// 加快网页加载完成的速度,等页面完成再加载图片
// 加快网页加载完成的速度,等页面完成再加载图片
getSettings().setLoadsImagesAutomatically(true)
// 开启 localStorage
// 开启 localStorage
getSettings().setDomStorageEnabled(true)
// 设置支持javascript// 本地 DOM 存储(解决加载某些网页出现白板现象)
// 设置支持javascript// 本地 DOM 存储(解决加载某些网页出现白板现象)
getSettings().setJavaScriptEnabled(true)
// 进行缩放
// 进行缩放
getSettings().setBuiltInZoomControls(true)
// 设置UserAgent
// 设置UserAgent
getSettings().setUserAgentString(getSettings().getUserAgentString() + "app")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// 解决 Android 5.0 上 WebView 默认不允许加载 Http 与 Https 混合内容
getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW)
}
webChromeClient = object : WebChromeClient() {
fun openFileChooser(
uploadMsg: ValueCallback<Uri>, AcceptType: String?, capture: String?
) {
this.openFileChooser(uploadMsg)
}
fun openFileChooser(uploadMsg: ValueCallback<Uri>, AcceptType: String?) {
this.openFileChooser(uploadMsg)
}
fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
// mUploadMessage = uploadMsg
// pictureSelector()
}
override fun onShowFileChooser(
webView: WebView,
filePathCallback: ValueCallback<Array<Uri>>,
fileChooserParams: FileChooserParams
): Boolean {
// mUploadMessageArray = filePathCallback
// pictureSelector()
return true
}
}
loadUrl("file:///android_asset/jsbridge_js_java_interaction.html")
registerHandler(
"functionToAndroid"
) { data, function ->
LogManager.i(
TAG,
"functionToAndroid handler = callNativeHandler, data from web = $data"
)
function.onCallBack("reponse data from Android 中文 from Java")
}
registerHandler(
"functionToAndroid2"
) { data, function ->
LogManager.i(
TAG,
"functionToAndroid2 handler = callNativeHandler, data from web = $data"
)
function.onCallBack("reponse data from Android 中文 from Java")
}
}
}
override fun initLoadData() {
}
override fun showLoading() {
}
override fun hideLoading() {
}
}
6.JS的代码:
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>
js调用java
</title>
</head>
<body>
<p>
<xmp id="show">
</xmp>
</p>
<p>
<xmp id="init">
</xmp>
</p>
<p>
<input type="text" id="text1" value="用户名(username)"/>
</p>
<p>
<input type="text" id="text2" value="password"/>
</p>
<!-- <p>-->
<!-- <input type="button" id="enter" value="发消息给Native" onclick="testClick();"-->
<!-- />-->
<!-- </p>-->
<p>
<input type="button" id="enter1" value="调用Native方法" onclick="testClick1();"
/>
</p>
<p>
<input type="button" id="enter2" value="调用Native方法2" onclick="testClick2();"
/>
</p>
<!-- <p>-->
<!-- <input type="button" id="enter2" value="显示html" onclick="testDiv();" />-->
<!-- </p>-->
<!-- <p>-->
<!-- <input type="file" value="打开文件" />-->
<!-- </p>-->
</body>
<script>
function testDiv() {
document.getElementById("show").innerHTML = document.getElementsByTagName("html")[0].innerHTML;
}
<!-- function testClick() {-->
<!-- var str1 = document.getElementById("text1").value;-->
<!-- var str2 = document.getElementById("text2").value;-->
<!-- //send message to native-->
<!-- var data = {id: 1, content: "这是一个图片 <img src=\"a.png\"/> test\r\nhahaha"};-->
<!-- window.WebViewJavascriptBridge.send(-->
<!-- data-->
<!-- , function(responseData) {-->
<!-- document.getElementById("show").innerHTML = "repsonseData from java, data = " + responseData-->
<!-- }-->
<!-- );-->
<!-- }-->
function testClick1() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//call native method
window.WebViewJavascriptBridge.callHandler(
'functionToAndroid'
, {'param': '中文测试'}
, function(responseData) {
document.getElementById("show").innerHTML = "functionToAndroid send responseData from java, data = " + responseData
}
);
}
function testClick2() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//call native method
window.WebViewJavascriptBridge.callHandler(
'functionToAndroid2'
, {'param': '中文测试2'}
, function(responseData) {
document.getElementById("show").innerHTML = "functionToAndroid2 send responseData from java, data = " + responseData
}
);
}
<!-- function bridgeLog(logContent) {-->
<!-- document.getElementById("show").innerHTML = logContent;-->
<!-- }-->
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
connectWebViewJavascriptBridge(function(bridge) {
bridge.init(function(message, responseCallback) {
console.log('JS got a message', message);
var data = {
'Javascript Responds': '测试中文!'
};
if (responseCallback) {
console.log('JS responding with', data);
responseCallback(data);
}
var data2 = {
'Javascript Responds': '测试中文2!'
};
if (responseCallback) {
console.log('JS responding with', data2);
responseCallback(data2);
}
});
bridge.registerHandler("functionToJs", function(data, responseCallback) {
document.getElementById("show").innerHTML = ("data from Java: = " + data);
if (responseCallback) {
var responseData = "Javascript Says Right back aka!";
responseCallback(responseData);
}
});
bridge.registerHandler("functionToJs2", function(data2, responseCallback) {
document.getElementById("show").innerHTML = ("data2 from Java: = " + data2);
if (responseCallback) {
var responseData = "Javascript2 Says Right back aka!";
responseCallback(responseData);
}
});
})
</script>
</html>
7.Android调用JS方法:
mDatabind.webView.callHandler(
"functionToJs2",
"data from Android",
CallBackFunction { data ->
LogManager.i(TAG, "reponse data from JS $data")
})
JS方法接收Android数据
bridge.registerHandler("functionToJs2", function(data2, responseCallback) {
document.getElementById("show").innerHTML = ("data2 from Java: = " + data2);
if (responseCallback) {
var responseData = "Javascript2 Says Right back aka!";
responseCallback(responseData);
}
});
8.JS调用Android方法:
function testClick2() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//call native method
window.WebViewJavascriptBridge.callHandler(
'functionToAndroid2'
, {'param': '中文测试2'}
, function(responseData) {
document.getElementById("show").innerHTML = "functionToAndroid2 send responseData from java, data = " + responseData
}
);
}
Android方法接收JS数据
registerHandler(
"functionToAndroid2"
) { data, function ->
LogManager.i(
TAG,
"functionToAndroid2 handler = callNativeHandler, data from web = $data"
)
function.onCallBack("reponse data from Android 中文 from Java")
}
推荐Android开源项目
项目功能介绍:原本是RxJava2 和Retrofit2 项目,现已更新使用Kotlin+RxJava2+Retrofit2+MVP架构+组件化和
Kotlin+Retrofit2+协程+MVVM架构+组件化, 添加自动管理token 功能,添加RxJava2 生命周期管理,集成极光推送、阿里云Oss对象存储和高德地图定位功能。