首頁>技術>

一、前言

現在市面上有一些app是通過原生ios、Android載入一個網頁實現的,如圖所示,這樣的app我們稱之為 Hybrid App

那麼為什麼要用 hybrid app呢? 個人認為的原因有兩點:

1.提高開發效率,以釘釘為例在涉及到一些OA操作比如打卡,請假等功能的時候,顯然一個嵌入一個網頁就能夠滿足需求,如果在讓IOS和Android再去各自開發一套那麼效率就很低了。

2.提高迭代效率。以商城為例,商城頁面會根據市場情況實時發生變化,比如遇到各種節假日活動做促銷。那麼這個時候如果用原生,那麼迭代等使用者去升級可能這個活動都已經過了,但是用巢狀webview巢狀一個網頁只需要網頁做出修改hybrid app內的web頁面就會馬上修改,這樣效率就非常高了。

hybrid app 實際上就是利用原生的元件webview載入一個url再讓js和原生相互呼叫實現各種功能,那麼接下來我就把js和原生相互呼叫的情況做一個總結。

二、原生api實現:js和原生相互呼叫

要想讓js和原生相互呼叫,對於webview最基本的一個設定就是要允許js指令碼執行

 WebSettings settings = mWebView.getSettings(); settings.setJavaScriptEnabled(true);

(一)、js呼叫原生

第一步:在java程式碼中定義js要呼叫的方法

// 定義JS需要呼叫的方法 // 被JS呼叫的方法必須加入@JavascriptInterface註解 @JavascriptInterface public void sendMsg(String msg) {// Log.i(TAG, "JS呼叫了Android的hello方法" + msg);// Toast.makeText(mContext, "JS呼叫了Android的hello方法" + msg, Toast.LENGTH_SHORT).show(); //為了方便拿到上下文和ui元件,寫一個回撥介面。 mJSBridge.sendMsg(msg); }

這裡需要說明的是,1.要在方法上面新增“@JavascriptInterface”註解,2.定義的方法必須是公共方法

第二步:給webview新增js指令碼介面。

mWebView.addJavascriptInterface(jsInterface, "Android_Interface");

void addJavascriptInterface (Object object, String name),這個方法有兩個引數,第一個是一個注入webview中js上下文的java物件,第二個引數是在js指令碼中來暴露的名稱物件,也就是說,這裡寫什麼,待會在js呼叫原生的時候就寫什麼。

第三步:用js呼叫原生方法

function sendMsg() { Android_Interface.sendMsg("你好,這是要傳遞的引數")}

(二)、原生呼叫js

這裡直接使用webview的api就能夠實現。Android中的程式碼如下:

// 第一種呼叫js中程式碼的方法// mWebView.loadUrl("javascript:beStronger()");//第二種呼叫js中程式碼的方法,同時傳值過去 mWebView.evaluateJavascript("javascript:beStronger(‘" + str + "‘)", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { //此處為 js 返回的結果 Toast.makeText(H5Activity.this, value, Toast.LENGTH_SHORT).show(); } });

在web中的程式碼如下:

function beStronger(value) { let box = document.getElementById("box"); // box.innerText = value; box.className = "box2"; box.innerText=value; return "小明你好"}web前端開發學習Q-q-u-n: 767-273-102 ,分享學習的方法和需要注意的小細節

當點選原生按鈕web中的div就會發生變化。

(三)、可能存在的安全性問題

但是在js呼叫原生的時候,可能會存在安全問題。具體的產生原因和解決辦法可以參考這一篇文章。《你不知道的 Android WebView 使用漏洞》。那如果要做的app對安全性要求極高,該怎麼辦呢?這裡推薦一個Android的第三方庫:JSBridge

三、第三方庫實現:js和原生相互呼叫

關於這個第三方庫的介紹,在說明檔案中已經說得很清楚了:該庫是js和java相互呼叫的橋樑,它為js和java之間相互呼叫提供了一個安全且便捷的方法。

(一)、引入第三方庫

第一步是在 app/build.gradle 檔案中引入該庫。

 repositories { // ... maven { url "/file/2019/10/12/20191012122423_76529.jpg.io" } }dependencies { .....  compile ‘com.github.lzyzsd:jsbridge:1.0.4‘}

然後在佈局中新增自定義的元件,BridgeWebView,該元件繼承自原生的WebView元件。

這套框架使用的核心就是:handler的註冊的呼叫。

要先實現js呼叫原生,那麼首先要在java原生中“註冊handler”,程式碼如下

//註冊handlerwebView.registerHandler("submitFromWeb", new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { Log.i(TAG, "handler = submitFromWeb, data from web = " + data); function.onCallBack("submitFromWeb exe, response data from Java"); } });

在註冊了handler以後,就可以在js程式碼中呼叫指定的handler了,例如上面我們註冊的handler是“submitFromWeb”,js 可以通過如下的方式呼叫java中註冊的handler。

 WebViewJavascriptBridge.callHandler( ‘submitFromWeb‘ , {‘param‘: str1} , function(responseData) { document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData } );

(三)、原生呼叫js

要先實現原生呼叫js,那麼首先也要在js中註冊handler

 WebViewJavascriptBridge.registerHandler("functionInJs", function(data, responseCallback) { document.getElementById("show").innerHTML = ("data from Java: = " + data); var responseData = "Javascript Says Right back aka!"; responseCallback(responseData); });

在js中註冊了handler以後,在java程式碼中就能夠呼叫指定名稱的handler

 webView.callHandler("functionInJs", new Gson().toJson(user), new CallBackFunction() { @Override public void onCallBack(String data) { } });web前端開發學習Q-q-u-n: 767-273-102 ,分享學習的方法和需要注意的小細節

(四)、需要注意的地方

這個庫將註冊一個 WebViewJavascriptBridge 物件給window 物件。那麼在你的js程式碼中,在使用WebViewJavascriptBridge物件之前,你必須檢測WebViewJavascriptBridge物件是否存在。如果WebViewJavascriptBridge物件不存在,你可以監聽WebViewJavascriptBridgeReady事件,如下所示:

 if (window.WebViewJavascriptBridge) { //do your work here } else { document.addEventListener( ‘WebViewJavascriptBridgeReady‘ , function() { //do your work here }, false ); }

  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 鋼鐵俠視角講解Springboot元件ApplicationContextInitializer