當(dāng)前位置:首頁 > IT技術(shù) > 移動(dòng)平臺(tái) > 正文

安卓webview原生和JavaScript(js)交互傳值的4種方式 java和js交互 安卓JsBridge原理解析
2021-08-07 18:40:35

JsBridge:安卓和javascript最流行的交互方式,有以下4種方式可以實(shí)現(xiàn)交互傳值

  • 1,addJavascriptInterface:針對Android 4.2(API 17)及以上,只有標(biāo)有@JavascriptInterface注解的public方法才能從js調(diào)用。而對targetSdkVersion為API Level 16及以下的app,js可以調(diào)用Java所有的public方法。
    通過public void addJavascriptInterface (Object object, String name)方法把對象傳遞給js,
  • 2, loadUrl:可以實(shí)現(xiàn)安卓調(diào)用js,通過webview.loadUrl(“javascript:jsMethod()”);字符串里的javascript: 是固定寫法,后面的jsMethod可以替換成你js代碼里的方法。也可以通過"javascript:jsMethod(" + jsonParams + “)”;傳遞數(shù)據(jù)給js。這個(gè)缺點(diǎn):如果js方法返回?cái)?shù)據(jù),這里會(huì)發(fā)生重定向。解決辦法是用evaluateJavascript
  • 3,evaluateJavascript:安卓4.4以后可以實(shí)現(xiàn)安卓調(diào)用js,安卓可以傳數(shù)據(jù)給js,并且可以獲取js方法的返回值。
    缺點(diǎn):必須大于api19(4.4)才可以使用
  • 4,shouldOverrideUrlLoading:通過這個(gè)方法攔截url,并解析url攜帶的參數(shù),如:qiushi://setH5Info?params={“title”%3A"商品詳情"}

js調(diào)用安卓

  • webView.addJavascriptInterface()
  • WebViewClient.shouldOverrideUrlLoading()

安卓調(diào)用js

  • webView.loadUrl();
  • webView.evaluateJavascript()

下面我門結(jié)合代碼具體講解下這4中方式的具體代碼實(shí)現(xiàn)

  • 首先我們要在androidstudio的assets文件夾下面定義下面html。
    安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_安卓js交互
<!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  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 實(shí)現(xiàn)js調(diào)用安卓
  • 針對Android 4.2(API 17)及以上
  • js可以調(diào)用安卓方法
  • 通過調(diào)用安卓方法可以實(shí)現(xiàn)安卓向js傳遞數(shù)據(jù)
  • 要被js調(diào)用的方法必須加@JavascriptInterface注釋
  • 使用這個(gè)方法前必須設(shè)置webview.getSettings().setJavaScriptEnabled(true);

主要通過
public void addJavascriptInterface(Object object, String name) {}方法實(shí)現(xiàn)js調(diào)用安卓原生代碼,簡單講解下兩個(gè)參數(shù)。
object:安卓對象
name:安卓對象的別名。
如我們定義
webview.addJavascriptInterface(JavaH5Activity.this, “androidObject”);就是把JavaH5Activity的實(shí)例命名為androidObject傳遞給js。
我們在js里的調(diào)用如下

?

完整代碼如下:

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調(diào)用安卓
        webview.getSettings().setJavaScriptEnabled(true);//這里必須開啟
        //把當(dāng)前JavaH5Activity對象作為androidObject別名傳遞給js
        //js通過window.androidObject.androidMethod()就可以直接調(diào)用安卓的androidMethod方法
        webview.addJavascriptInterface(JavaH5Activity.this, "androidObject");
    }

    //js調(diào)用安卓,必須加@JavascriptInterface注釋的方法才可以被js調(diào)用
    @JavascriptInterface
    public String androidMethod() {
        Log.i("qcl0228", "js調(diào)用了安卓的方法");
        return "我是js調(diào)用安卓獲取的數(shù)據(jù)";
    }
}

js的代碼如下

<body>
<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();調(diào)用安卓的方法,進(jìn)而獲取到安卓傳遞過來的數(shù)據(jù)。
如下圖
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_交互_02
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_安卓JsBridge_03
同時(shí)看日志,我們能看到j(luò)s成功的調(diào)用了安卓的方法,并獲取到了安卓native傳遞過來的數(shù)據(jù)。

@JavascriptInterface
  public String androidMethod() {
        Log.i("qcl0228", "js調(diào)用了安卓的方法");
        return "我是js調(diào)用安卓獲取的數(shù)據(jù)";
   }

二,shouldOverrideUrlLoading 實(shí)現(xiàn)js調(diào)用安卓

js通過重定向出發(fā)安卓攔截,重定向的url被shouldoverrideurlloading攔截到。分發(fā)攔截到的信息指揮安卓做事情。
簡單的重定向的代碼如下

<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傳遞漢子需要編碼的問題。以后有機(jī)會(huì)再做url編碼的講解。
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_webview與js_04
安卓端的代碼做攔截解析。

 webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                Log.i("qcl0228", "攔截到的url:" + url);
                //url如果以qiushi開頭,就是h5和我們定義的傳值協(xié)議
                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攜帶的參數(shù)存到一個(gè)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", "攔截到的參數(shù):" + h5InfoParams);
                                }
                            }
                        }
                    }
                } else {
                    view.loadUrl(url);
                }
                return true;
            }
        });

打印結(jié)果如下
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_交互_05
這里我們可以看到安卓成功攔截到了url并解析出來了url里的數(shù)據(jù),這樣js就可以通過這些數(shù)據(jù)指揮安卓做事情了。并且也可以做到j(luò)s傳遞數(shù)據(jù)給安卓的效果。

三,loadUrl:安卓調(diào)用js

  • 安卓通過webview的loadUrl可以調(diào)用js方法
  • 安卓傳遞數(shù)據(jù)給js
  • js不能返回?cái)?shù)據(jù),因?yàn)閖s返回?cái)?shù)據(jù)的話,會(huì)導(dǎo)致重定向問題。下面會(huì)做講解。
    安卓端的代碼如下
String jsonParams = "123456";
 //String url = "javascript:jsMethod()";//不拼接參數(shù),直接調(diào)用js的jsMethod函數(shù)
String url = "javascript:jsMethod(" + jsonParams + ")";//拼接參數(shù),就可以把數(shù)據(jù)傳遞給js
 webview.loadUrl(url);

js的代碼如下:

<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';//如果返回?cái)?shù)據(jù),會(huì)重定向
}
</script>

運(yùn)行結(jié)果如下
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_webview與js_06
可以看到我們把數(shù)據(jù)jsonParams傳遞給了js并顯示在了h5頁面上。
上js代碼里的 //return ‘987654321’;注釋如果解開,會(huì)發(fā)生請求重定向的問題,如下圖
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_安卓js_07
這里不能通過安卓調(diào)用js代碼獲取js數(shù)據(jù),那該怎么辦呢,下面的方法正好可以彌補(bǔ)這個(gè)缺陷。

四,evaluateJavascript:安卓調(diào)用js

  • 必須大于api19(4.4)才可以使用
  • 可以實(shí)現(xiàn)安卓和js的雙向傳遞數(shù)據(jù)
    安卓端的代碼如下
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    String jsonParams = "123456";
    //String method = "jsMethod()";//不拼接參數(shù),直接調(diào)用js的jsMethod函數(shù)
    String method = "jsMethod(" + jsonParams + ")";//拼接參數(shù),就可以把數(shù)據(jù)傳遞給js
    webview.evaluateJavascript(method, new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            Log.i("qcl0228", "js返回的數(shù)據(jù)" + value);
        }
    });
}

js的代碼如下

<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';//如果返回?cái)?shù)據(jù),會(huì)重定向
}
</script>

運(yùn)行結(jié)果如下
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_webview與js_06
打印日志如下
安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_交互_09
我們可以看到,通過evaluateJavascript可以實(shí)現(xiàn)安卓調(diào)用js代碼。并且安卓的數(shù)據(jù)可以傳遞給js,js的數(shù)據(jù)也可以傳遞給安卓。

JSBridge的原理解析

JSBridge:是一座用JavaScript搭建起來的橋,替代了WebView的自帶的JavascriptInterface的接口,使得我們的開發(fā)更加靈活和安全。一端是web,一端是native,他可以根據(jù)web和native約定好的規(guī)則來通知native要做什么,從而實(shí)現(xiàn)Android和Javascript之間的交互

JSBridge的原理可以總結(jié)為以下三點(diǎn):

  • 1、Android通過loadUrl(url)調(diào)用JS對象,可以在URL內(nèi)傳遞參數(shù)。
  • 2、JS調(diào)用Android是通過shouldOverrideUrlLoading攔截uri。
  • 3、JsBridge將數(shù)據(jù)封裝成Message,然后放進(jìn)Queue,再將Queue通過協(xié)議進(jìn)行傳輸。

?

本文摘自 :https://blog.51cto.com/u

開通會(huì)員,享受整站包年服務(wù)立即開通 >