• 當前位置:首頁 > IT技術 > 移動平臺 > 正文

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

    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。
      安卓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 實現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里的調用如下

    ?

    完整代碼如下:

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

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

    二,shouldOverrideUrlLoading 實現js調用安卓

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

    <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編碼的講解。
    安卓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和我們定義的傳值協議
                    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;
                }
            });
    

    打印結果如下
    安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_交互_05
    這里我們可以看到安卓成功攔截到了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  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>
    

    運行結果如下
    安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_webview與js_06
    可以看到我們把數據jsonParams傳遞給了js并顯示在了h5頁面上。
    上js代碼里的 //return ‘987654321’;注釋如果解開,會發生請求重定向的問題,如下圖
    安卓webview原生和JavaScript(js)交互傳值的4種方式       java和js交互    安卓JsBridge原理解析_安卓js_07
    這里不能通過安卓調用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  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>
    

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

    JSBridge的原理解析

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

    JSBridge的原理可以總結為以下三點:

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

    ?

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

    開通會員,享受整站包年服務
    国产呦精品一区二区三区网站|久久www免费人咸|精品无码人妻一区二区|久99久热只有精品国产15|中文字幕亚洲无线码