简述
在移动应用开发中,Android和JavaScript是两个常用的技术栈。Android作为主流的移动操作系统,而JavaScript则是用于网页前端和跨平台开发的脚本语言。为了完成更好的用户体验和功能扩展,Android与JavaScript之间的通讯变得至关重要。本文将介绍Android与JavaScript之间的回调通讯技巧
通讯基础
-
经过 WebView 进行通讯
Android 的 WebView 组件供给了
evaluateJavascript
办法,该办法能够履行 JavaScript 代码并获取回来成果。我们能够使用这一特性完成 Android 和 JavaScript 之间的通讯。详细完成过程如下:- 在 Android 代码中,经过
evaluateJavascript
办法履行 JavaScript 代码。
- 在 Android 代码中,经过
-
使用 JavaScriptInterface 完成通讯
我们能够使用
JavascriptInterface
接口完成JavaScript 与 Android 的通讯。详细完成过程如下:- 在 Android 代码中创立一个类,完成
JavascriptInterface
接口。 - 在该类中定义需要供 JavaScript 调用的办法,并添加
@JavascriptInterface
注解。 - 在 JavaScript 中经过
window.AndroidFunction
对象调用 Android 代码中的办法,完成通讯,其间AndroidFunction是注册JavascriptInterface时指定的, 如下所示:webView.addJavascriptInterface(new Object() { @JavascriptInterface public void jsCallback(String message) { // ... } }, "AndroidFunction");
- 在 Android 代码中创立一个类,完成
Android调用JavaScript函数
-
疏忽回来值
val webView = findViewById<WebView>(R.id.webView) webView.evaluateJavascript("jsFunction('message')", null)
-
获取回来值
val webView = findViewById<WebView>(R.id.webView) webView.evaluateJavascript("jsFunction('message')") { result -> Log.e("TAG", result) }
JavaScript调用Android函数
// 在JavaScript中调用Android函数,并传递参数
function callAndroidFunctionWithParameter() {
var message = "Hello from JavaScript!";
AndroidFunction.jsCallback(message);
}
在上述示例中,JavaScript函数callAndroidFunctionWithParameter()
将参数message
传递给Android函数jsCallback()
。
双向回调通讯
-
Javascript传递回调给Android
上述的
AndroidFunction.jsCallback(message)
办法目前只能传递字符串,假如不做特殊处理,是无法履行回调函数的, 履行AndroidFunction.jsCallback(message)
时,在Android中获取到的是字符串,这时将回调函数转换成回调令牌,然后经过令牌履行相应的回调函数,过程如下:-
在js中将回调函数转换成仅有令牌,然后使用map以令牌为key存储回调函数,以便让Android端根据令牌来履行回调函数
const recordCallMap = new Map<string, Function>(); // Android端调用 window.jsbridgeApiCallBack = function (callUUID: string, callbackParamsData: any) { // 经过ID获取对应的回调函数 const fun = recordCallMap.get(callUUID); // 履行回调 `callbackParamsData`回调函数的参数 可有可无 fun && fun(callbackParamsData); // 履行结束后开释资源 recordCallMap.delete(callUUID); } function getUuid() { // 生成仅有ID return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/\[xy]/g, function (c) { var r = (Math.random() \* 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } // 一致处理调用Android的办法 export function androidCall(funname: string, funData: string, fun: Function) { if (!AndroidFunction) { return; } const dataObj = { funName: funname, funData: funData } if (typeof fun === "function") { const funId = getUuid(); Object.assign(dataObj, { funId }); recordCallMap.set(funId, fun); } AndroidFunction.jsCall(JSON.stringify(dataObj)) }
-
在Android端注册JavascriptInterface一致让js调用
class JsCallbackModel { lateinit var funData: String lateinit var funId: String lateinit var funName: String } abstract class JsFunctionCallBack(var funId: String) { abstract fun callback(respData: String?) abstract fun callback() abstract fun callback(respData: Boolean) } class JavaScriptCall(private val webView: WebView) { private fun jsCall(funName: String, funData: String, jsFunction: JsFunctionCallBack) { when(funName) { "screenCapture" -> { screenshot(funData.toInt(), jsFunction) } } } @JavascriptInterface fun jsCall(data: String) { // 将json字符串解析成kotlin对象 val gson = GsonBuilder().create() val model = gson.fromJson(data, JsCallbackModel::class.java) // 假如不存在函数称号 则疏忽 if (model.funName == "") { return } val jsFunction: JsFunctionCallBack = object : JsFunctionCallBack(model.funId) { override fun callback(respData: String?) { if (webView == null) { return } if (funId.isEmpty()) { return } content.webView.post { webView.evaluateJavascript("jsBridgeApiCallBack('$funId', "$respData")", null) } } override fun callback() { if (funId.isEmpty()) { return } content.webView.post { webView.evaluateJavascript("jsBridgeApiCallBack('$funId')", null) } } override fun callback(respData: Boolean) { if (funId.isEmpty()) { return } content.webView.post { webView.evaluateJavascript("jsBridgeApiCallBack('$funId', '$respData')", null) } } } jsCall(model.funName, model.funData, jsFunction); } private fun screenshot(quality: Int, jsFunction: JsFunctionCallBack) { // 履行逻辑... // 履行js回调 jsFunction("base64...") } }
-
在js中传递回调函数调用Android截图
function screenshot(): Promise<string> { return new Promise(resolve => { androidCall("screenshot", (base64: string) => resolve(base64)) }) } screenshot().then(base64 => { })
-
-
Android传递回调给Javascript
原理跟Javascript传递回调给Android是相同的,详细完成如下:
-
Android端
class JavaScriptCall(private val webView: WebView) { companion object { val dataF: MutableMap<String, (callData: String) -> Unit> = mutableMapOf() fun jsCall(webView: WebView, funName: String, funData: String, funHandler: (callData: String) -> Unit) { val ctx: MutableMap<String, String> = mutableMapOf() ctx["funName"] = funName ctx["funData"] = funData val uuid = UUID.randomUUID().toString() ctx["funId"] = uuid dataF[uuid] = funHandler webView.post { val gson = GsonBuilder().create() val json = gson.toJson(ctx) webView.evaluateJavascript("jsCall('$json')", null) } } } @JavascriptInterface fun androidsBridgeApiCallBack(callUUID: String, callData: String) { val funHandler = dataF[callUUID]; if (funHandler != null) { funHandler(callData) dataF.remove(callUUID) } } }
-
Js端
function doSome(funId, data, callback) { // 履行逻辑... // 履行Android的回调函数 callback(funId, data) } function androidFunction(funId, respData: any?) { AndroidFunction.androidsBridgeApiCallBack(funId, respData) } function androidCallback(funId, funName, funData, fun) { switch (funName) { case 'doSome': { doSome(funId, funData, fun) } } } window.jsCall = function (json: string) { const obj = JSON.parse(json) const funName = obj['funName'] const funData = obj['funData'] const funId = obj['funId'] if (!funName) { return } androidCallback(funId, funName, funData, androidFunction) }
-
在Android中传递回调函数调用js的doSome
JavaScriptCall.jsCall(webView, "doSome", "data") { callParam -> Log.e("tAG", "回调参数: $callParam") }
-