什麼是移動端通訊?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¶m2=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 函數 👆!!
JSBridge.getData('userInfo',function(data) { console.log(data); });
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