app native和 h5的通訊方式-- jsbridge

什麼是移動端通訊?javascript

有哪些是須要了解的開發背景知識?html

怎麼樣開始一個移動端項目開發和調試呢?java

看這篇文檔記錄,夠入門  go--->android

 

1   IOS 和Android底層和js的交互原理ios

 

ios提供UIWebView 組件,是一個可加載網頁的對象,提供相似瀏覽器的功能,能夠經過js代碼調用一些原生的功能,好比:獲取GPS信息。git

Safari瀏覽器的控件和原生 UIWebView不兼容,在ios8版本以後提供了WKWebView對象,提供了4個屬性、8個api供js調用:github

 

loading:是否處於加載中,web

canGoBack:只讀,是否能夠接受後退swift

canGoForward: 只讀,是否可接受向前api

request: url 請求

 

loadData: 設置主頁類型,MIME類型,文檔編碼,base url 。

loadRequest: 加載網絡資源

loadHTMLString: 加載本地 html 資源

stopLoading: 中止加載

goBack: 後退

goForward:  前進

reload: 從新加載

stringByEvaluatingJavaScriptFromString: 執行一段 js 腳本,並返回執行結果。

 

2   IOS 系統

Native 調用 JavaScript的方法 (object-c swift)

是獲取 stringByEvaluatingJavaScriptFromString 方法執行的放回結果。

// Swift
webview.stringByEvaluatingJavaScriptFromString("Math.random()")
// OC
[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];

以上例子的函數都是至關於在 window 下的方法,因此若是js的方法放在 window 下是能夠被 webview的接口調用的。

相似: 

"Math.random()"

 

 

JS 調用 Native 方法

native沒有現成的api給js調用,能夠經過發送網絡請求的方式,在 native 層獲得通知。

UIWebView 層內發起網絡請求,格式是這樣的,例如 object-c 和 swift

jsbridge://methodName?param1=value1&param2=value2    // js 調用原生的通常傳參格式。

因此,在UIWebView層若是看到這樣的schema就進行邏輯處理,不進行網絡請求。

發起這種網絡請求的方式,h5能夠用 location.href 和 iframe 的方式。

location.href 會有點問題  連續發送多個請求時,在 Native 層只能接收到最後一次的調用。

因此使用 iframe發送請求。

var url = 'jsbridge://doAction?title=標題'; // 定義請求的url,設置好對終端有效的schema。方便攔截。 var iframe = document.createElement('iframe');
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = url;
document.body.appendChild(iframe); // 將iframe添加到document,發起請求
setTimeout(function() {
    iframe.remove();  // 只須要一次請求,因此須要把 iframe 標籤從HTML文檔中移除。
}, 100);

WebView 能夠攔截這個請求並獲取對應的參數,參考以下代碼

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        print("shouldStartLoadWithRequest")  // 開始處理這個請求
        let url = request.URL
        let scheme = url?.scheme
        let method = url?.host   // 獲取host值,判斷執行的動做,交給 Object-c 處理。
        let query = url?.query   // 獲取執行的傳參 if url != nil && scheme == "jsbridge" {
            print("scheme == \(scheme)")
            print("method == \(method)")
            print("query == \(query)")

            switch method! {
                case "getData":
                    self.getData()
                case "putData":
                    self.putData()
                case "gotoWebview":
                    self.gotoWebview()
                case "gotoNative":
                    self.gotoNative()
                case "doAction":
                    self.doAction()
                case "configNative":
                    self.configNative()
                default:
                    print("default")
            }
            return false;
        } else {
            return true;
        }
    }

 

3   Android 系統

js 調用 native 的方式

在 Android 系統中有 2 種方式能夠實現,js調用 native方法。好像還有第3中,重寫console.log方法不明覺厲中。。

方法一:

經過schema方式,使用shouldOverrideUrlLoading方法對url協議進行解析。這種js的調用方式與ios的同樣,使用iframe來調用native代碼。

 

方法二:

使用原生webview提供的接口,addJavaScriptInterface 方法來實現。

class JSInterface {
    @JavascriptInterface           //注意這個代碼必定要加上,Java 代碼對類型方法的修飾。
    public String getUserData() {
        return "---- native 定義的方法";
    }
}

webView.addJavascriptInterface(new JSInterface(), "AndroidJS");複製代碼上面的代碼就是在頁面的window對象裏注入了AndroidJS對象。在js裏能夠直接調用

console.log(AndroidJS.getUserData()) // ---- native 定義的方法  JSInterface 接口的方法。 對應在 Android WebView 方法中定義的被修飾後的方法。

 

native 調用 js 的方式

webView.loadUrl("javascript:Bridge.doSomething('hello.')");

調用 JavaScript 中的 Bridge.doSomething() 方法。

 

 

4  庫的封裝

js  調用 native 的封裝

基於以前對 IOS 和Android 和js通訊的瞭解,再封裝一層,保證js代碼操做系統兼容性。 http://www.javashuo.com/article/p-rnfycncf-gr.html  這段代碼來自掘金的文章。

我再整理下邏輯並註釋。^_^

HaveJsBridge = {
    doCall: function(functionName, data, callback) {
        var _this = this;
        // 這裏實際上是一個節流,不讓你點太快或響應太快
        if (this.lastCallTime && (Date.now() - this.lastCallTime) < 100) {
            setTimeout(function() {
                _this.doCall(functionName, data, callback);
            }, 100);
            return;
        }
        this.lastCallTime = Date.now();

        data = data || {};
        if (callback) {
            $.extend(data, { callback: callback });
        }

        if (UA.isIOS()) {
            $.each(data, function(key, value) {  // 每一個 data key value 進行序列化 if ($.isPlainObject(value) || $.isArray(value)) {
                    data[key] = JSON.stringify(value);
                }
            });
            var url = Args.addParameter('jsbridge://' + functionName, data);
            var iframe = document.createElement('iframe');
            iframe.style.width = '1px';
            iframe.style.height = '1px';
            iframe.style.display = 'none';
            iframe.src = url;
            document.body.appendChild(iframe);
            setTimeout(function() {
                iframe.remove();   // 和上面的代碼執行同樣,清除dom
            }, 100);
        } else if (UA.isAndroid()) {
// 此處對接上面👆代碼中的 webView.addJavascriptInterface 接口方法 window.androidJS
&& window.androidJS[functionName] && window.androidJS[functionName](JSON.stringify(data)); } else { console.error('未獲取platform信息,調取api失敗'); } } }

好,兼容性準備工做就緒,如今開始封裝幾個 經常使用的 js能夠調用 native 的方法。

!!這幾個方法都對應上面的 func  webView 函數 👆!!

1  getData(datatype, callback, extra) H5從Native APP獲取數據 

JSBridge.getData('userInfo',function(data) {
    console.log(data);
});

 

2  putData(datatype, data) H5告訴Native APP一些數據

JSBridge.putData('userInfo', { username: 'zhangsan', age: 20 });

 

3   gotoWebview(url, page, data)  打開相應網頁傳參,打開新的webview 窗口,能夠再 webView函數中調用

JSBridge.gotoWebview('http://www.youzan.com', 'goodsDetail', {
    goods_id: 10000,
    title: '這是商品的標題',
    desc: '這是商品的描述'
});

 

4  打開某個原生 Native APP 的頁面

JSBridge.gotoNative('loginPage', {
    username: '張三'
});

 

5  作一些操做

// 封裝一個複製函數,好比點擊複製
JSBridge.doAction('copy', {
    content: '這是要複製的內容'
});

// 封裝一個分享函數,好比點擊分享到 哪哪哪。
JSBridge.doAction('share', {
    title: '分享標題',
    desc: '分享描述',
    link: 'http://www.youzan.com',
    imgs_url: 'http://wap.koudaitong.com/v2/common/url/create?type=homepage&index%2Findex=&kdt_id=63077&alias=63077'
});


// 注意,這些代碼還只是方法的僞代碼實現不要當真。

 

 

5    Safari 上的調試

第一步: 首先須要打開Safari的調試模式,在Safari的菜單中,選擇「Safari」→「Preference」→「Advanced」,勾選上「Show Develop menu in menu bar」選項

第二步: 打開iPhone模擬器的調試模式,在真機或iPhone模擬器中打開設置界面,選擇「Safari」→「高級」→「Web檢查器」,選擇開啓

第三步: 將真機經過USB連上電腦,或者開啓模擬器,Safari的「Develop」菜單下便會多出相應的菜單項

第四步: Safari鏈接上UIWebView以後,咱們就能夠直接在Safari中直接修改HTML、CSS,以及調試Javascript

什麼是 UIWebView 啓動呢?

這個是Android開發須要Java環境,起一個Android的項目,在手機或模擬器上安裝這個項目,就跑起來了。

 

6  參考文檔

UIWebView  https://developer.apple.com/documentation/uikit/uiwebview

WKWebView  

Github JSBridge    https://github.com/marcuswestin/WebViewJavascriptBridge

搭建簡單webview調試    https://www.jianshu.com/p/4f783cd34ab1

相關文章
相關標籤/搜索