Hybrid APP基礎篇(三)->Hybrid APP之Native和H5頁面交互原理

来源:http://www.cnblogs.com/dailc/archive/2016/10/04/5931322.html
-Advertisement-
Play Games

說明 Hybrid模式原生和H5交互原理 目錄 前言 參考來源 前置技術要求 楔子 Android、iOS原生和H5的基本通信機制 Android端 iOS端 原生和H5的另一種通訊方式:JSBridge 什麼是JSBridge 為什麼要用JSBridge JSBridge原理以及實現 前言 參考來 ...


說明

Hybrid模式原生和H5交互原理

目錄

前言

參考來源

前人栽樹,後臺乘涼,本文參考了以下來源

前置技術要求

閱讀本文前,建議先閱讀以下文章

楔子

Hybrid APP的關鍵是原生頁面與H5頁面直接的交互,本文做簡單介紹

Android、iOS原生和H5的基本通信機制

在Hybrid APP中,原生與H5的交互方式在Android和iOS上的實現是有異同的,原因是Android、iOS的通信機制有所區別,下麵介紹原生和H5相互調用的方法

Android端

Native調JS

4.4版本之前

// mWebView = new WebView(this); //即當前webview對象			
mWebView.loadUrl("javascript: 方法名('參數,需要轉為字元串')"); 

//ui線程中運行
 runOnUiThread(new Runnable() {  
        @Override  
        public void run() {  
            mWebView.loadUrl("javascript: 方法名('參數,需要轉為字元串')");  
            Toast.makeText(Activity名.this, "調用方法...", Toast.LENGTH_SHORT).show();  
        }  
});  
			

4.4以後(包括4.4)

//非同步執行JS代碼,並獲取返回值	
mWebView.evaluateJavascript("javascript: 方法名('參數,需要轉為字元串')", new ValueCallback() {
        @Override
        public void onReceiveValue(String value) {
    		//這裡的value即為對應JS方法的返回值
        }
});
			

如上所示,Native用H5頁面中的JS方法,有如下特點

  • 4.4之前Native通過loadUrl來調用JS方法,只能讓某個JS方法執行,但是無法獲取該方法的返回值
  • 4.4之後,通過evaluateJavascript非同步調用JS方法,並且能在onReceiveValue中拿到返回值
  • 不適合傳輸大量數據(大量數據建議用介面方式獲取)
  • mWebView.loadUrl("javascript: 方法名('參數,需要轉為字元串')");函數需在UI線程運行,因為mWebView為UI控制項(但是有一個壞處是會阻塞UI線程)

JS調Native

 WebSettings webSettings = mWebView.getSettings();  
 //Android容器允許JS腳本,必須要
webSettings.setJavaScriptEnabled(true);
//Android容器設置僑連對象
mWebView.addJavascriptInterface(getJSBridge(), "JSBridge");
			

Android中JSBridge的代碼

//Android4.2版本以上,本地方法要加上註解@JavascriptInterface,否則會找不到方法。
private Object getJSBridge(){  
    Object insertObj = new Object(){  
    	@JavascriptInterface
        public String foo(){  
            return "foo";  
        }  
        
        @JavascriptInterface
        public String foo2(final String param){  
            return "foo2:" + param;  
        }  
          
    };  
    return insertObj;  
}  
			

Html中JS調用原生的代碼

//調用方法一
window.JSBridge.foo(); //返回:'foo'
//調用方法二
window.JSBridge.foo2('test');//返回:'foo2:test'
			

如上所示,Native中通過addJavascriptInterface添加暴露出來的JS橋對象,然後再該對象內部聲明對應的API方法,有如下特點:

  • 在Android4.2以上(api17後),暴露的api要加上註解@JavascriptInterface,否則會找不到方法。
  • 在api17以前,addJavascriptInterface有風險,hacker可以通過反編譯獲取Native註冊的Js對象,然後在頁面通過反射Java的內置 靜態類,獲取一些敏感的信息和破壞

    所以,也就是為什麼Android中也會使用JSBridge來進行交互,而不是addJavascriptInterface直接暴露api

  • JS能調用到已經暴露的api,並且能得到相應返回值

iOS端

Native調JS

//可以取得JS函數執行的返回值
//方法必須是Html頁面綁定在最頂層的window上對象的
//如window.top.foo
//Swift
webview.stringByEvaluatingJavaScriptFromString("方法名(參數)")
//OC
[webView stringByEvaluatingJavaScriptFromString:@"方法名(參數);"];
			

如上所示,Native通過stringByEvaluatingJavaScriptFromString調用Html綁定在window上的函數,有如下特點

  • Native調用JS方法時,能拿到JS方法的返回值
  • 不適合傳輸大量數據(大量數據建議用介面方式獲取)

JS調Native

引入官方的庫文件

#import <JavaScriptCore/JavaScriptCore.h>

Native註冊api函數(OC)

//webview載入完畢後設置一些js介面
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    [self hideProgress];
    [self setJSInterface];
}

-(void)setJSInterface{
    
    JSContext *context =[_wv valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    // 註冊名為foo的api方法
    context[@"foo"] = ^() {
    	
    	//獲取參數
        NSArray *args = [JSContext currentArguments];
        NSString *title = [NSString stringWithFormat:@"%@",[args objectAtIndex:0]];
        //做一些自己的邏輯
        //返回一個值  'foo:'+title
        return [NSString stringWithFormat:@"foo:%@", title];
    };
    

    
}				
			

Html中JS調用原生的代碼

//調用方法,用top是確保調用到最頂級,因為iframe要用top才能拿到頂級
window.top.foo('test'); //返回:'foo:test'
			

如上所示,Native中通過引入官方提供的JavaScriptCore庫(iOS7中出現的),然後可以將api綁定到JSContext上(然後Html中JS預設通過window.top.***可調用)。有如下特點

  • iOS7才出現這種方式,在這之前,js無法直接調用Native,只能通過JSBridge方式簡介調用
  • JS能調用到已經暴露的api,並且能得到相應返回值
  • iOS原生本身是無法被JS調用的,但是通過引入官方提供的第三方"JavaScriptCore",即可開放api給JS調用

原生和H5的另一種通訊方式:JSBridge

實際上,Native與H5通信,除了前面提到的用基本方法外,還有一種廣為流行的方法:JSBridge

什麼是JSBridge

JSBridge是廣為流行的Hybrid開發中JS和Native一種通信方式,各大公司的應用中都有用到這種方法

簡單的說,JSBridge就是定義Native和JS的通信,Native只通過一個固定的橋對象調用JS,JS也只通過固定的橋對象調用Native,基本原理是:

H5->通過某種方式觸發一個url->Native捕獲到url,進行分析->原生做處理->Native調用H5的JSBridge對象傳遞迴調。如下圖

上圖簡單的介紹了下JSBridge的核心原理,具體詳細實現請參考後面詳解。

為什麼要用JSBridge

在上文中我們有提到Native和原生之間的基本通信,既然Native和原生已經能夠實現通信了,那為什麼還要這種通過url scheme的JSBridge方式呢,原因大致如下

  • Android4.2以下,addJavascriptInterface方式有安全漏掉
  • iOS7以下,JS無法調用Native
  • url scheme交互方式是一套現有的成熟方案,可以完美相容各種版本,不存在上述問題

另外,請註意,可以理解為JSBridge是一種交互理念,而上述的url scheme則是其中的一種實現,所以也就是說,就算後面實現變為了addJavascriptInterface,JavaScriptCore,也一樣是JSBridge交互

JSBridge交互的一個很大特點就是便於拓展,而且沒有重大的安全性問題,所以也就是為什麼它廣為流行

JSBridge原理以及實現

JSBridge的原理和實現請參考 JSBridge實現原理


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 【框架】: 公共部分:左側菜單、TitleBar、RadioGroup(3個RadioButton:X、Y、Z) 選擇X頁面:指示器+ViewPager 【要達成的效果】: (1)左側選擇A,進入X頁面,X1聯網刷新頁面,此時禁止X2預載入—>滑動到X2頁面,X2才聯網刷新—>X3—>X4; (2) ...
  • Activty啟動提供了四種啟動模式。launchMode: standard:每次啟動新的活動視窗(new操作) singleTop:如果在棧頂是目標活動,則直接打開.否則開啟新的活動視窗(new). singleTask和singleInstance基本上相同.差別在於若根活動設置為single ...
  • 當某個activity變得“容易”被系統銷毀時,該activity的onSaveInstanceState就會被執行,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵的時候。 註意上面的雙引號,何為“容易”?言下之意就是該activity還沒有被銷毀,而僅僅是一種可能性。這種可能性有 ...
  • 本章節主要為之前項目 JXHomepwner 添加照片功能(項目地址)。具體任務就是顯示一個 UIImagePickerController 對象,使用戶能夠為 JXItem 對象拍照並保存。拍攝的照片會和相應的 JXItem 對象建立關聯,當用戶進入某個 JXItem 對象的詳細視圖的時候,可以看 ...
  • 說明 JSBridge實現示例 目錄 前言 參考來源 楔子 JS實現部分 說明 實現 Android實現部分 說明 JSBridge類 實現 Callback類 實現 Webview容器關鍵代碼 實現 API 類實現 iOS實現部分 說明 WebViewJavascriptBridgeBase 實現 ...
  • 一直想弄清楚onTouchEvent,onInterceptTouchEvent,dispatchTouchEvent的執行順序,以及內部使用switch (event.getAction())中的執行順序。趁這次機會趕緊弄清楚。 重寫上面幾個方法後。我們在LogCat中看看列印的結果。 一.isO ...
  • 說明 JSBridge實現原理 目錄 前言 參考來源 前置技術要求 楔子 原理概述 簡介 url scheme介紹 實現流程 實現思路 第一步:設計出一個Native與JS交互的全局橋對象 第二步:JS如何調用Native 第三步:Native如何得知api被調用 第四步:分析url-參數和回調的格 ...
  • 基於OpenSLL的RSA加密應用(非演算法) === iOS開發中的小伙伴應該是經常用der和p12進行加密解密,而且在通常加密不止一種加密演算法,還可以加點兒鹽吧~本文章主要闡述的是在iOS中基於openSLL的RSA加密。一共有兩種方式,一種是基於p12加密解密的,還有一種是博客園官方提供的公鑰字 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...