在Android原生開發(fā)中砌左,應該80%的都會遇到原生與Js的混合調用淆两,網(wǎng)上有很多示例住闯,都可以實現(xiàn)需求瓜浸,但是基本是表層實現(xiàn),當然也有一些也寫的非常不錯比原,但是不知為什么就沒有更新了插佛,然后工程還缺少文件。其實我們在WebView和原生相互調用量窘,無非就以下幾個問題:
- 原生調用Js雇寇,Js如何異步回調給原生,同一個調用多次回調呢蚌铜,一次回調锨侯、兩次回調、三次......呢冬殃?
- Js調用原生囚痴,原生如何異步回調給Js,同一個調用多次回調呢审葬,一次回調深滚、兩次回調奕谭、三次......呢?不通過WebView的
loadUrl
執(zhí)行js進行回調呢痴荐? - 我想在寫Js時候這樣操作呢血柳?
JsBridge.nativeDeleteCallback("調用原生方法后刪除回調",function(result){
alert(JSON.stringify(result))
},function(error){
alert(JSON.stringify(result))
});
針對上面問題,本文也相應的解決了這寫問題蹬昌,參考Demo ,也可以先下載Demo運行之后一目了然混驰。
SDK支持
- Js調用原生方法并支持異步回調和同步回調
- 原生調用Js方法并支持異步回調
- Js調用名稱空間可自由配置,統(tǒng)一管理命名空間
- 支持Js調用原生方法多次回調皂贩,如果不想多次回調可以刪除回調方法
- 支持部分Js框架中window并非頂級window
API介紹
callJsFunction(function: String)
原生調用Js的方法栖榨,不支持傳遞參數(shù)和回調
參數(shù):
function:調用Js的方法名稱
callJsFunction(function: String, callback: JsCallback?)
原生調用Js的方法,不支持傳遞參數(shù)但支持回調
參數(shù)
function:調用Js的方法名稱
callback:回調函數(shù)
callJsFunction(function: String, data: String?)
原生調用Js的方法明刷,支持傳遞參數(shù)婴栽,但不支持回調
參數(shù)
function:調用Js的方法名稱
data:字符串,傳遞給Js的參數(shù)
callJsFunction(function: String, data: String?, callback: JsCallback?)
原生調用Js的方法辈末,支持傳遞參數(shù)和回調
參數(shù)
function:調用Js的方法名稱
data:字符串愚争,傳遞給Js的參數(shù)
callback:回調函數(shù)
jsCallName()
Js調用原生的API命名空間,SDK統(tǒng)一了命名空間挤聘,默認為JsBridge
轰枝,整個Js調用中只會使用這個命名,當然组去,如果是你不喜歡這個命名鞍陨,或者需要根據(jù)項目更改為項目有關的命名,可以自定義WebView繼承至BaseWebView重寫該方法从隆。
getWindow()
Js中獲取window的方法诚撵,建議不要隨意修改。在特殊的Js框架中键闺,獲取系統(tǒng)的window需要window.window才能獲取到寿烟,所以這時候可以自定義WebView繼承至BaseWebView重寫該方法。
如何使用
依賴引入
Step 1.先在 build.gradle(Project:XXX) 的 repositories 添加:
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
Step 2. 然后在 build.gradle(Module:XXX) 的 dependencies 添加:
dependencies {
implementation 'com.github.ChinaLike:JsBridge:0.0.2'
}
新建Js調用原生方法的類辛燥,參考:JsBridgeToast
package com.like.jsbridge
import android.content.Context
import android.os.Handler
import android.util.Log
import android.webkit.JavascriptInterface
import android.widget.Toast
import com.core.web.Callback
import com.core.web.CallbackBean
class JsBridgeToast(private val context: Context) {
@JavascriptInterface
fun nativeNoArgAndNoCallback(){
Toast.makeText(context,"調用原生無參數(shù)無回調方法",Toast.LENGTH_SHORT).show()
}
@JavascriptInterface
fun nativeNoArgAndCallback(callback: Callback){
callback.success()
}
@JavascriptInterface
fun nativeArgAndNoCallback(params:String){
Toast.makeText(context,params,Toast.LENGTH_SHORT).show()
}
@JavascriptInterface
fun nativeArgAndCallback(params:String,callback: Callback):Boolean{
Toast.makeText(context,params,Toast.LENGTH_SHORT).show()
callback.success()
return false
}
@JavascriptInterface
fun nativeDeleteCallback(params:String,callback: Callback){
Toast.makeText(context,params,Toast.LENGTH_SHORT).show()
callback.success(isDelete = true)
Handler().postDelayed(Runnable {
callback.error(1,"錯誤回調")
},3000)
}
@JavascriptInterface
fun nativeNoDeleteCallback(params:String,callback: Callback){
Toast.makeText(context,params,Toast.LENGTH_SHORT).show()
callback.success(isDelete = false)
Handler().postDelayed(Runnable {
callback.error(1,"錯誤回調")
},3000)
}
@JavascriptInterface
fun nativeSyncCallback():String{
return "原生同步回調"
}
}
新建MainActivity和xml文件,參考:MainActivityKotlin和activity_main
- 在xml文件中引入JsBridgeWebView
<com.core.web.JsBridgeWebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
當然筛武,如果沒有特殊需要使用
JsBridgeWebView
就可以了,如果有定制WebView挎塌,則引入自己定制那個WebView就可以了畅铭,但是自定義的WebView需要繼承BaseWebView
- 在Activity中調用
addJavascriptInterface
添加
import com.core.web.JsBridgeWebView;
class MainActivityKotlin : AppCompatActivity() {
private var webView: JsBridgeWebView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.webView)
webView?.addJavascriptInterface(JsBridgeToast(this))
webView?.loadUrl("file:///android_asset/test.html")
}
注意:
webView的addJavascriptInterface
方法可以多次調用,開發(fā)時可以根據(jù)業(yè)務功能進行解耦勃蜘,addJavascriptInterface
方法支持傳遞一個或兩個參數(shù),傳遞兩個參數(shù)時第二個參數(shù)無效假残。
在Js中調用原生方法缭贡,參考:test.html
-
Js調用原生無參無回調方法
- Kotlin代碼
@JavascriptInterface fun nativeNoArgAndNoCallback(){ Toast.makeText(context,"調用原生無參數(shù)無回調方法",Toast.LENGTH_SHORT).show() }
- Java代碼
@JavascriptInterface public void nativeNoArgAndNoCallback(){ Toast.makeText(context,"調用原生無參數(shù)無回調方法",Toast.LENGTH_SHORT).show(); }
- Js代碼
JsBridge.nativeNoArgAndNoCallback();
-
Js調用原生無參有回調方法
- Kotlin代碼
@JavascriptInterface fun nativeNoArgAndCallback(callback: Callback){ callback.success() }
- Java代碼
@JavascriptInterface public void nativeNoArgAndCallback(Callback callback){ callback.success(); }
- Js代碼
JsBridge.nativeNoArgAndCallback(function(result){ alert(JSON.stringify(result)); });
-
Js調用原生有參無回調方法
- Kotlin代碼
@JavascriptInterface fun nativeArgAndNoCallback(params:String){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show() }
- Java代碼
@JavascriptInterface public void nativeArgAndNoCallback(String params){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show(); }
- Js代碼
JsBridge.nativeArgAndNoCallback("調用原生有參數(shù)無回調方法");
-
Js調用原生有參有回調方法
- Kotlin代碼
@JavascriptInterface fun nativeArgAndCallback(params:String,callback: Callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show() callback.success() }
- Java代碼
@JavascriptInterface public void nativeArgAndCallback(String params,Callback callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show(); callback.success(); }
- Js代碼
JsBridge.nativeArgAndCallback("調用原生有參數(shù)有回調方法",function(result){ alert(JSON.stringify(result)) });
-
Js調用原生有參有回調方法炉擅,且只能回調一次
- Kotlin代碼
@JavascriptInterface fun nativeDeleteCallback(params:String,callback: Callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show() callback.success(true) Handler().postDelayed(Runnable { callback.error(1,"錯誤回調") },3000) }
- Java代碼
@JavascriptInterface public void nativeDeleteCallback(String params,Callback callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show(); callback.success(true); new Handler().postDelayed(new Runnable() { @Override public void run() { callback.error(1,"錯誤回調"); } },3000); }
- Js代碼
JsBridge.nativeDeleteCallback("調用原生方法后刪除回調",function(result){ alert(JSON.stringify(result)) },function(error){ alert(JSON.stringify(result)) });
-
Js調用原生有參有回調方法飘弧,且能回調多次
- Kotlin代碼
@JavascriptInterface fun nativeNoDeleteCallback(params:String,callback: Callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show() callback.success(false) Handler().postDelayed(Runnable { callback.error(1,"錯誤回調") },3000) }
- Java代碼
@JavascriptInterface public void nativeNoDeleteCallback(String params,Callback callback){ Toast.makeText(context,params,Toast.LENGTH_SHORT).show(); callback.success(false); new Handler().postDelayed(new Runnable() { @Override public void run() { callback.error(1,"錯誤回調"); } },3000); }
- Js代碼
JsBridge.nativeNoDeleteCallback("調用原生方法后不刪除回調",function(result){ alert(JSON.stringify(result)) },function(error){ alert(JSON.stringify(error)) });
-
Js調用原生同步回調數(shù)據(jù)
- Kotlin代碼
@JavascriptInterface fun nativeSyncCallback():String{ return "原生同步回調" }
- Java代碼
@JavascriptInterface public String nativeSyncCallback(){ return "原生同步回調"; }
- Js代碼
var result = JsBridge.nativeSyncCallback(); alert(result)
注意:
被@JavascriptInterface
注解的方法谷扣,只支持最多兩個參數(shù)泣矛,不論順序测蹲。無參數(shù):
代表Js不傳遞參數(shù)過來也不回調骤竹;一個參數(shù):
可以是傳遞過來的參數(shù)或回調猜谚;兩個參數(shù):
一個為參數(shù)雕薪,一個是回調曙博。
在原生中調用Js方法纲岭,參考:MainActivity
-
原生調用JS無參數(shù)無回調
- Js代碼
function jsNoArgAndNoCallback(){ alert("原生調用JS無參數(shù)無回調"); }
- Java代碼
webView.callJsFunction("jsNoArgAndNoCallback");
- Kotlin代碼
webView?.callJsFunction("jsNoArgAndNoCallback")
-
原生調用Js無參數(shù)有回調
- Js代碼
function jsNoArgAndCallback(callback){ alert("原生調用JS無參數(shù)有回調"); callback("我是JS回調數(shù)據(jù)"); }
- Java代碼
webView.callJsFunction("jsNoArgAndCallback", callback -> Toast.makeText(this, "" + callback, Toast.LENGTH_SHORT).show());
- Kotlin代碼
webView?.callJsFunction("jsNoArgAndCallback", object : JsCallback { override fun onCallback(callback: Any) { Toast.makeText(this@MainActivityKotlin, "$callback", Toast.LENGTH_SHORT).show() } })
-
原生調用Js有參數(shù)無回調
- Js代碼
function jsArgAndNoCallback(params){ alert(params); }
- Java代碼
webView.callJsFunction("jsArgAndNoCallback", "原生傳遞過來的參數(shù)");
- Kotlin代碼
webView?.callJsFunction("jsArgAndNoCallback","原生傳遞過來的參數(shù)")
-
原生調用Js有參數(shù)有回調(可回調多次)
- Js代碼
function jsArgAndCallback(params,callback){ alert(params); callback("我是JS第一次回調數(shù)據(jù)"); setTimeout(function() { callback("我是JS第二次回調數(shù)據(jù)"); }, 500); }
- Java代碼
webView.callJsFunction("jsArgAndCallback", "原生傳遞過來的參數(shù)", callback -> Toast.makeText(this, "" + callback, Toast.LENGTH_SHORT).show());
- Kotlin代碼
webView?.callJsFunction("jsArgAndCallback","原生傳遞過來的參數(shù)", object : JsCallback { override fun onCallback(callback: Any) { Toast.makeText(this@MainActivityKotlin, "$callback", Toast.LENGTH_SHORT).show() } })
-
調用Js有參數(shù)有回調(只能回調一次)
- Js代碼
function jsArgAndDeleteCallback(params,callback){ alert(params); callback("我是JS第一次回調數(shù)據(jù)",true); setTimeout(function() { callback("我是JS第二次回調數(shù)據(jù)"); }, 500); }
- Java代碼
webView.callJsFunction("jsArgAndDeleteCallback", "原生傳遞過來的參數(shù)", callback -> Toast.makeText(this, "" + callback, Toast.LENGTH_SHORT).show());
- Kotlin代碼
webView?.callJsFunction("jsArgAndDeleteCallback","原生傳遞過來的參數(shù)", object : JsCallback { override fun onCallback(callback: Any) { Toast.makeText(this@MainActivityKotlin, "$callback", Toast.LENGTH_SHORT).show() } })
注意:
原生調用Js代碼抹竹,Js的方法最多支持兩個參數(shù),無參數(shù):
代表原生不傳遞參數(shù)過來也不用回調給原生止潮;一個參數(shù):
可以是參數(shù)也可以是回調窃判;兩個參數(shù):
有序,第一個為參數(shù)喇闸,第二個為回調袄琳,代表原生傳遞過來參數(shù),且需要回調給原生
如有問題歡迎留言 源碼地址