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


什么是移動端通信?

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

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

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

 

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

 

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

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

 

loading:是否處於加載中,

canGoBack:只讀,是否可以接受后退

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

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代碼操作系統兼容性。 https://juejin.im/post/599a58f6f265da247b4e756b  這段代碼來自掘金的文章。

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM