安卓webview原生和JavaScript(js)互動傳值的4種方式(java和js互動,安卓JsBridge)有圖有原始碼
JsBridge:安卓和javascript最流行的互動方式,有以下4種方式可以實現互動傳值
- 1,addJavascriptInterface:針對Android 4.2(API 17)及以上,只有標有@JavascriptInterface註解的public方法才能從js呼叫。而對targetSdkVersion為API Level 16及以下的app,js可以呼叫Java所有的public方法。
通過public void addJavascriptInterface (Object object, String name)方法把物件傳遞給js, - 2, loadUrl:可以實現安卓呼叫js,通過webview.loadUrl("javascript:jsMethod()");字串裡的javascript: 是固定寫法,後面的jsMethod可以替換成你js程式碼裡的方法。也可以通過"javascript:jsMethod(" + jsonParams + ")";傳遞資料給js。這個缺點:如果js方法返回資料,這裡會發生重定向。解決辦法是用evaluateJavascript
- 3,evaluateJavascript:安卓4.4以後可以實現安卓呼叫js,安卓可以傳資料給js,並且可以獲取js方法的返回值。
缺點:必須大於api19(4.4)才可以使用 - 4,shouldOverrideUrlLoading:通過這個方法攔截url,並解析url攜帶的引數,如: qiushi://setH5Info?params= {"title"%3A"商品詳情"}
js呼叫安卓
- webView.addJavascriptInterface()
- WebViewClient.shouldOverrideUrlLoading()
安卓呼叫js
- webView.loadUrl();
- webView.evaluateJavascript()
下面我門結合程式碼具體講解下這4中方式的具體程式碼實現
-
首先我們要在androidstudio的assets資料夾下面定義下面html。
image.png
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Untitled Document</title> </head> <body> <div id="div" onclick="getAndroidValue()"style="width:100px; height:100px; background-color:#099;"></div> <script type="text/javascript"> function chongdingxiang(){ //模擬重定向 window.location.href="qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D"; } function jsMethod(jsonParams){ document.getElementById("div").style.backgroundColor='red'; document.getElementById("div").innerHTML=jsonParams; return '987654321'; } function getAndroidValue(){ document.getElementById("div").innerHTML=window.androidObject.androidMethod(); } </script> </body> </html>
一,addJavascriptInterface 實現js呼叫安卓
- 針對Android 4.2(API 17)及以上
- js可以呼叫安卓方法
- 通過呼叫安卓方法可以實現安卓向js傳遞資料
- 要被js呼叫的方法必須加@JavascriptInterface註釋
- 使用這個方法前必須設定webview.getSettings().setJavaScriptEnabled(true);
主要通過
public void addJavascriptInterface(Object object, String name) {}方法實現js呼叫安卓原生程式碼,簡單講解下兩個引數。
object:安卓物件
name:安卓物件的別名。
如我們定義
webview.addJavascriptInterface(JavaH5Activity.this, "androidObject");就是把JavaH5Activity的例項命名為androidObject傳遞給js。
我們在js裡的呼叫如下
<div id="div" onclick="window.androidObject.androidMethod()"></div>
完整程式碼如下:
public class JavaH5Activity extends AppCompatActivity { private WebView webview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_java_h5); webview = findViewById(R.id.webview); String url = "file:///android_asset/h5demo2.html"; webview.loadUrl(url); //1,js呼叫安卓 webview.getSettings().setJavaScriptEnabled(true);//這裡必須開啟 //把當前JavaH5Activity物件作為androidObject別名傳遞給js //js通過window.androidObject.androidMethod()就可以直接呼叫安卓的androidMethod方法 webview.addJavascriptInterface(JavaH5Activity.this, "androidObject"); } //js呼叫安卓,必須加@JavascriptInterface註釋的方法才可以被js呼叫 @JavascriptInterface public String androidMethod() { Log.i("qcl0228", "js呼叫了安卓的方法"); return "我是js呼叫安卓獲取的資料"; } }
js的程式碼如下
<body> <div id="div" onclick="getAndroidValue()"style="width:100px; height:100px; background-color:#099;"></div> <script type="text/javascript"> function getAndroidValue(){ document.getElementById("div").innerHTML=window.androidObject.androidMethod(); } </script> </body>
在js裡我們使用window.androidObject.androidMethod();呼叫安卓的方法,進而獲取到安卓傳遞過來的資料。
如下圖

手機執行效果

log日誌
同時看日誌,我們能看到js成功的呼叫了安卓的方法,並獲取到了安卓native傳遞過來的資料。
@JavascriptInterface public String androidMethod() { Log.i("qcl0228", "js呼叫了安卓的方法"); return "我是js呼叫安卓獲取的資料"; }
二,shouldOverrideUrlLoading 實現js呼叫安卓
js通過重定向出發安卓攔截,重定向的url被shouldoverrideurlloading攔截到。分發攔截到的資訊指揮安卓做事情。
簡單的重定向的程式碼如下
<div id="div" onclick="chongdingxiang()"style="width:100px; height:100px; background-color:#099;"></div> <script type="text/javascript"> function chongdingxiang(){ //模擬重定向 window.location.href="qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D"; } </script>
這裡的url:“ qiushi://setH5Info?params=%7B%22title%22%3A%22%E5%95%86%E5%93%81%E8%AF%A6%E6%83%85%22%7D ”是url編碼後的,編碼前的樣式如下。這裡涉及到url傳遞漢子需要編碼的問題。以後有機會再做url編碼的講解。

URL編碼
安卓端的程式碼做攔截解析。
webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.i("qcl0228", "攔截到的url:" + url); //url如果以qiushi開頭,就是h5和我們定義的傳值協議 if (url.startsWith("qiushi")) { Uri uriRequest = Uri.parse(url); String scheme = uriRequest.getScheme(); String action = uriRequest.getHost(); String query = uriRequest.getQuery(); if ("qiushi".equals(scheme)) { if (!TextUtils.isEmpty(query)) { //把url攜帶的引數存到一個map裡 HashMap maps = new HashMap(); Set<String> names = uriRequest.getQueryParameterNames(); for (String name : names) { maps.put(name, uriRequest.getQueryParameter(name)); } JSONObject jsonObject = new JSONObject(maps); if ("setH5Info".equals(action)) { if (jsonObject != null && jsonObject.has("params")) { String h5InfoParams = jsonObject.optString("params"); Log.i("qcl0228", "攔截到的引數:" + h5InfoParams); } } } } } else { view.loadUrl(url); } return true; } });
列印結果如下

日誌
這裡我們可以看到安卓成功攔截到了url並解析出來了url裡的資料,這樣js就可以通過這些資料指揮安卓做事情了。並且也可以做到js傳遞資料給安卓的效果。
三,loadUrl:安卓呼叫js
- 安卓通過webview的loadUrl可以呼叫js方法
- 安卓傳遞資料給js
- js不能返回資料,因為js返回資料的話,會導致重定向問題。下面會做講解。
安卓端的程式碼如下
String jsonParams = "123456"; //String url = "javascript:jsMethod()";//不拼接引數,直接呼叫js的jsMethod函式 String url = "javascript:jsMethod(" + jsonParams + ")";//拼接引數,就可以把資料傳遞給js webview.loadUrl(url);
js的程式碼如下:
<div id="div" style="width:100px; height:100px; background-color:#099;"></div> <script type="text/javascript"> function jsMethod(jsonParams){ document.getElementById("div").style.backgroundColor='red'; document.getElementById("div").innerHTML=jsonParams; //return '987654321';//如果返回資料,會重定向 } </script>
執行結果如下

執行結果
可以看到我們把資料jsonParams傳遞給了js並顯示在了h5頁面上。
上js程式碼裡的 //return '987654321';註釋如果解開,會發生請求重定向的問題,如下圖

image.png
這裡不能通過安卓呼叫js程式碼獲取js資料,那該怎麼辦呢,下面的方法正好可以彌補這個缺陷。
四,evaluateJavascript:安卓呼叫js
- 必須大於api19(4.4)才可以使用
- 可以實現安卓和js的雙向傳遞資料
安卓端的程式碼如下
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { String jsonParams = "123456"; //String method = "jsMethod()";//不拼接引數,直接呼叫js的jsMethod函式 String method = "jsMethod(" + jsonParams + ")";//拼接引數,就可以把資料傳遞給js webview.evaluateJavascript(method, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { Log.i("qcl0228", "js返回的資料" + value); } }); }
js的程式碼如下
<div id="div" style="width:100px; height:100px; background-color:#099;"></div> <script type="text/javascript"> function jsMethod(jsonParams){ document.getElementById("div").style.backgroundColor='red'; document.getElementById("div").innerHTML=jsonParams; return '987654321';//如果返回資料,會重定向 } </script>
執行結果如下

執行結果
列印日誌如下

image.png
我們可以看到,通過evaluateJavascript可以實現安卓呼叫js程式碼。並且安卓的資料可以傳遞給js,js的資料也可以傳遞給安卓。