国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

H5與Native交互之JSBridge技術

zacklee / 1813人閱讀

摘要:一原理篇下面分別介紹和與的底層交互原理在講解原理之前,首先來了解下的組件,先來看一下蘋果官方的介紹上面的意思是說是一個可加載網頁的對象,它有瀏覽記錄功能,且對加載的網頁內容是可編程的。

做過混合開發的很多人都知道Ionic和PhoneGap之類的框架,這些框架在web基礎上包了一層Native,然后通過Bridge技術使得js可以調用視頻、位置、音頻等功能。本文就是介紹這層Bridge的交互原理,通過閱讀本文你可以了解到js與ios及android底層的通訊原理及JSBridge的封裝技術及調試方法。

一、原理篇

下面分別介紹IOS和Android與Javascript的底層交互原理

IOS

在講解原理之前,首先來了解下iOS的UIWebView組件,先來看一下蘋果官方的介紹:

You can use the UIWebView class to embed web content in your application. To do so, you simply create a UIWebView object, attach it to a window, and send it a request to load web content. You can also use this class to move back and forward in the history of webpages, and you can even set some web content properties programmatically.

上面的意思是說UIWebView是一個可加載網頁的對象,它有瀏覽記錄功能,且對加載的網頁內容是可編程的。說白了UIWebView有類似瀏覽器的功能,我們使用可以它來打開頁面,并做一些定制化的功能,如可以讓js調某個方法可以取到手機的GPS信息。

但需要注意的是,Safari瀏覽器使用的瀏覽器控件和UIwebView組件并不是同一個,兩者在性能上有很大的差距。幸運的是,蘋果發布iOS8的時候,新增了一個WKWebView組件,如果你的APP只考慮支持iOS8及以上版本,那么你就可以使用這個新的瀏覽器控件了。

原生的UIWebView類提供了下面一些屬性和方法

屬性:

loading:是否處于加載中

canGoBack:A Boolean value indicating whether the receiver can move backward. (只讀)

canGoForward:A Boolean value indicating whether the receiver can move forward. (只讀)

request:The URL request identifying the location of the content to load. (read-only)

方法:

loadData:Sets the main page contents, MIME type, content encoding, and base URL.

loadRequest:加載網絡內容

loadHTMLString:加載本地HTML文件

stopLoading:停止加載

goBack:后退

goForward:前進

reload:重新加載

stringByEvaluatingJavaScriptFromString:執行一段js腳本,并且返回執行結果

Native(Objective-C或Swift)調用Javascript方法

Native調用Javascript語言,是通過UIWebView組件的stringByEvaluatingJavaScriptFromString方法來實現的,該方法返回js腳本的執行結果。

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

從上面代碼可以看出它其實就是調用了window下的一個對象,如果我們要讓native來調用我們js寫的方法,那這個方法就要在window下能訪問到。但從全局考慮,我們只要暴露一個對象如JSBridge對native調用就好了,所以在這里可以對native的代碼做一個簡單的封裝:

//下面為偽代碼
webview.setDataToJs(somedata);
webview.setDataToJs = function(data) {
 webview.stringByEvaluatingJavaScriptFromString("JSBridge.trigger(event, data)")
}
Javascript調用Native(Objective-C或Swift)方法

反過來,Javascript調用Native,并沒有現成的API可以直接拿來用,而是需要間接地通過一些方法來實現。UIWebView有個特性:在UIWebView內發起的所有網絡請求,都可以通過delegate函數在Native層得到通知。這樣,我們就可以在UIWebView內發起一個自定義的網絡請求,通常是這樣的格式:jsbridge://methodName?param1=value1¶m2=value2

于是在UIWebView的delegate函數中,我們只要發現是jsbridge://開頭的地址,就不進行內容的加載,轉而執行相應的調用邏輯。

發起這樣一個網絡請求有兩種方式:1. 通過localtion.href;2. 通過iframe方式;
通過location.href有個問題,就是如果我們連續多次修改window.location.href的值,在Native層只能接收到最后一次請求,前面的請求都會被忽略掉。

使用iframe方式,以喚起Native APP的分享組件為例,簡單的封閉如下:

var url = "jsbridge://doAction?title=分享標題&desc=分享描述&link=http%3A%2F%2Fwww.baidu.com";
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();
}, 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
        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
        }
    }
Android

在android中,native與js的通訊方式與ios類似,ios中的通過schema方式在android中也是支持的。

javascript調用native方式

目前在android中有三種調用native的方式:

1.通過schema方式,使用shouldOverrideUrlLoading方法對url協議進行解析。這種js的調用方式與ios的一樣,使用iframe來調用native代碼。
2.通過在webview頁面里直接注入原生js代碼方式,使用addJavascriptInterface方法來實現。
在android里實現如下:

class JSInterface {
    @JavascriptInterface //注意這個代碼一定要加上
    public String getUserData() {
        return "UserData";
    }
}
webView.addJavascriptInterface(new JSInterface(), "AndroidJS");

上面的代碼就是在頁面的window對象里注入了AndroidJS對象。在js里可以直接調用

alert(AndroidJS.getUserData()) //UserDate

3.使用prompt,console.log,alert方式,這三個方法對js里是屬性原生的,在android webview這一層是可以重寫這三個方法的。一般我們使用prompt,因為這個在js里使用的不多,用來和native通訊副作用比較少。

class YouzanWebChromeClient extends WebChromeClient {
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        // 這里就可以對js的prompt進行處理,通過result返回結果
    }
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {

    }
    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {

    }

}
Native調用javascript方式

在android里是使用webview的loadUrl進行調用的,如:

// 調用js中的JSBridge.trigger方法
webView.loadUrl("javascript:JSBridge.trigger("webviewReady")");
二、庫的封裝 js調用native的封裝

上面我們了解了js與native通訊的底層原理,所以我們可以封裝一個基礎的通訊方法doCall來屏蔽android與ios的差異。

YouzanJsBridge = {
    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) {
                if ($.isPlainObject(value) || $.isArray(value)) {
                    data[key] = JSON.stringify(value);
                }
            });
            var url = Args.addParameter("youzanjs://" + 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();
            }, 100);
        } else if (UA.isAndroid()) {
            window.androidJS && window.androidJS[functionName] && window.androidJS[functionName](JSON.stringify(data));
        } else {
            console.error("未獲取platform信息,調取api失敗");
        }
    }
}

上面android端我們使用了addJavascriptInterface方法來注入一個AndroidJS對象。

項目通用方法抽象

在項目的實踐中,我們逐漸抽象出一些通用的方法,這些方法基本上都是可以滿足項目的需求。如下所示:

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

使用場景:H5需要從Native APP獲取某些數據的時候,可以調用這個方法。

參數 類型 是否必須 示例值 說明
datatype String userInfo 數據類型
callback Function 回調函數
extra Object 傳遞給Native APP的數據對象

示例代碼:

JSBridge.getData("userInfo",function(data) {
    console.log(data);
});
2.putData(datatype, data) H5告訴Native APP一些數據

使用場景:H5告訴Native APP一些數據,可以調用這個方法。

參數 類型 是否必須 示例值 說明
datatype String userInfo 數據類型
data Object { username: "zhangsan", age: 20 } 傳遞給Native APP的數據對象

示例代碼:

JSBridge.putData("userInfo", {
    username: "zhangsan",
    age: 20
});
3.gotoWebview(url, page, data) Native APP新開一個Webview窗口,并打開相應網頁
參數 類型 是否必須 示例值 說明
url String http://www.youzan.com 網頁鏈接地址,一般都只要傳遞URL參數就可以了
page String web 網頁page類型,默認為web
data Object 額外參數對象

示例代碼:

// 示例1:打開一個網頁
JSBridge.gotoWebview("http://www.youzan.com");

// 示例2:打開一個網頁,并且傳遞額外的參數給Native APP
JSBridge.gotoWebview("http://www.youzan.com", "goodsDetail", {
    goods_id: 10000,
    title: "這是商品的標題",
    desc: "這是商品的描述"
});
4.gotoNative(page, data) 從H5頁面跳轉到Native APP的某個原生界面
參數 類型 是否必須 示例值 說明
page String loginPage Native頁面標示符,例如loginPage
data Object { username: "zhangsan", age: 20 } 額外參數對象

示例代碼:

// 示例1:打開Native APP登錄頁面
JSBridge.gotoNative("loginPage");

// 示例2:打開Native APP登錄頁面,并且傳遞用戶名給Native APP
JSBridge.gotoNative("loginPage", {
    username: "張三"
});
5.doAction(action, data) 功能上的一些操作
參數 類型 是否必須 示例值 說明
action String copy 操作功能類型,例如分享、復制
data Object { content: "這是要復制的內容" } 額外參數

示例代碼:

// 示例1:調用Native APP復制一段文本到剪切板
JSBridge.doAction("copy", {
    content: "這是要復制的內容"
});

// 示例2:調用Native APP的分享組件,分享當前網頁到微信
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"
});
三、調試篇 使用Safari進行UIWebView的調試

(1)首先需要打開Safari的調試模式,在Safari的菜單中,選擇“Safari”→“Preference”→“Advanced”,勾選上“Show Develop menu in menu bar”選項,如下圖所示。

(2)打開真機或iPhone模擬器的調試模式,在真機或iPhone模擬器中打開設置界面,選擇“Safari”→“高級”→“Web檢查器”,選擇開啟即可,如下圖所示。

(3)將真機通過USB連上電腦,或者開啟模擬器,Safari的“Develop”菜單下便會多出相應的菜單項,如圖所示。

(4)Safari連接上UIWebView之后,我們就可以直接在Safari中直接修改HTML、CSS,以及調試Javascript。

四、參考鏈接

UIWebView Class Reference

WKWebView Class Reference

https://github.com/marcuswestin/WebViewJavascriptBridge

本文由 @kk @勁風 共同創作,首發于有贊技術博客: http://tech.youzan.com/jsbridge/

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84341.html

相關文章

  • 原生Appjavascript交互JSBridge接口原理、設計實現

    摘要:相關參考中與之間相互調用的實現實現了與相同的機制的對象注入漏洞解決方案存在的意義 前期調研 調研對象:支付寶,微信,云之家 調研文檔:Android中JS與Java的極簡交互庫 SimpleJavaJsBridge 設計需求 閱讀類型的業務功能頁面需要由前端H5實現,需要做到服務端可控; 頁面界面更改減少重新發布新版本的頻率; 功能頁面部分原型需求無法實現,需要原生功能支持; 對未來...

    Lyux 評論0 收藏0
  • 跨平臺技術演進

    摘要:接下來,我將從原理優缺點等方面為大家分享跨平臺技術演進。小程序年是微信小程序飛速發展的一年,年,各大廠商快速跟進,已經有了很大的影響力。下面,我們以微信小程序為例,分析小程序的技術架構。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,關于這篇文章,有問題歡迎來這里討論。 隨著移動互聯網的普及和快速發展,手機成了互聯網行業最大的流量分發入口。以及隨著5G...

    魏憲會 評論0 收藏0
  • 跨平臺技術演進

    摘要:接下來,我將從原理優缺點等方面為大家分享跨平臺技術演進。小程序年是微信小程序飛速發展的一年,年,各大廠商快速跟進,已經有了很大的影響力。下面,我們以微信小程序為例,分析小程序的技術架構。 前言 大家好,我是simbawu ,@BooheeFE Team Leader,關于這篇文章,有問題歡迎來這里討論。 隨著移動互聯網的普及和快速發展,手機成了互聯網行業最大的流量分發入口。以及隨著5G...

    MasonEast 評論0 收藏0

發表評論

0條評論

zacklee

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<