1. 程式人生 > >h5與App原生互動方案

h5與App原生互動方案

  • 方便測試階段,H5嵌入到App當中,開發人員方便除錯與Debug。

    目前主流的技術方案:

    1.在iOS7以前,在UIWebView中實現一些代理方法攔截帶有約定好的protocol的Url,從Url上獲取get方式的引數傳遞,對映成本地原生方法,如下:
    -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
      NSString *urlString = request.URL
    .absoluteString; if ([urlString rangeOfString:@"js-call://"].location != NSNotFound) { NSString * host = [self sliceHost:urlString]; NSDictionary * params = [self sliceParams:urlString]; if ([host isEqualToString:@"openOrderDetail"]) { [self openOrderDetail:params]; } return
    NO; } return YES; }
    這僅僅解決了js呼叫原生方法的問題,至於呼叫的結果與呼叫完之後要進行一些頁面的回撥,在這個攔截的過程中根本沒有辦法進行,不過有一些蹩腳的補償措施,如下:
    -(void)webViewDidFinishLoad:(UIWebView *)webView
    {
      self.orderDetailCallBackFuncName = [webView stringByEvaluatingJavaScriptFromString:@"orderCallbackfuncName()"];
    }
    會在頁面載入完畢後主動去取頁面上設定的回撥方法的名稱,然後在原生方法中處理完邏輯再進行回撥。
    -(void
    )OpenOrderDetail:(NSDictionary *)params{ //do someting [self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"%@()",self.orderDetailCallBackFuncName ]]; }
    2.iOS7以後,大家都使用JavaScriptCore這個官方的WebKit 的 JavaScript 引擎,實現oc與JavaScript的語言穿梭。
    -(void)configJsCallBack{
      WeakSelf;
      self.jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
      self.jsContext.exceptionHandler = ^(JSContext * con,JSValue * exception){
          NSLog(@"JS Error:%@",exception);
      };
      Coordinator * coordinator = [[Coordinator alloc]init];
      self.jsContext[@"mobileCoordinator"] = coordinator;
      self.jsContext[@"console"] = coordinator;
    }
    不太瞭解JavaScriptCore的同學可以自己查閱一下官方文件或者學習資料。這裡我們使用一些技巧,將所有的App開放給js的方法都由一個叫Coordinator的排程器來排程,而這個排程器實現了JSExport協議:
    #import <Foundation/Foundation.h>
    #import <JavaScriptCore/JavaScriptCore.h>
    @protocol CoordinatorExport <JSExport>
    -(void)log:(NSString *)msg;
    -(BOOL)callNativeModule:(NSString *)url;
    /*
      js呼叫原生分享
      shareOpinion為json物件
      {
          "type":"share",
          "title":"share title",
          "content":"share content",
          "imgUrl":"",
          "clickUrl":""
      }
      其中型別type有以下幾種:
      share(只有朋友圈和微信好友),doubleShare(包含所有分享渠道),allShare(分享全部渠道)
    */
    JSExportAs(showShareMenu, -(BOOL)showShareMenu:(NSString *)url opinion:(NSString *)opinion);
    @end
    @interface Coordinator : NSObject< CoordinatorExport >
    @property(nonatomic,copy)BOOL (^openShareCallBack)(NSDictionary * opinion);
    @end
    上面的做法就是我們會在合適的實際向JavaScript的執行的環境中注入一個叫做mobileCoordinator的物件,這個物件會注入到JavaScript環境中的window物件上,全域性可用。為什麼要封裝到一個物件上,是因為js沒有名稱空間的概念並且有變數提升向上查詢,會引起命名衝突,所以我們把對外暴露的方法都進行一個物件封裝。還有一個好處就是JavaScript的開發者與app的開發者都會像編寫各自語言的程式碼一樣書寫程式碼,沒有語法損失,js同步呼叫原生方法,原生實現的時候具備返回值,js的呼叫者就可以獲取返回值,如果是非同步回撥,那可以對外暴露方法的時候提供一個callback的入參,在非同步完成後進行回撥。
    3.其他方案例如JavaScriptBridge等與第二種方案類似。

    方案比較:

    方案1的流程如下:
    互動方式為單向
    H5呼叫Native:
    H5頁面 —>發起Url Redirect(Url上攜帶帶有動作語義的引數)->Native App->攔截Url Redirect->解析動作語義引數->呼叫相關Native程式碼
    Native呼叫H5頁面:
    Native App—>獲取頁面上預留引數和解析動作語義引數->呼叫相關JavaScript程式碼
    這樣使得一個簡單的方法呼叫變得非常割裂,而且雙端維護成本非常高,不易debug。
    方案2的流程如下:
    互動為雙向:
    H5頁面(Native App)<->呼叫Native程式碼(呼叫JavaScript程式碼)<->Native App執行被呼叫Native程式碼返回呼叫結果(H5頁面執行被呼叫JavaScript程式碼並返回呼叫結果)
    方案2優勢比較明顯,一般會採用第二種。

    實現細節

    細節上有一些需要注意的東西:
    1.oc方法是帶有引數標籤的,js的方法並沒有,注意使用JSExportAs這個巨集來將oc原生語言轉換為js語法風格的程式碼。
    2.注意獲取jscontext上下文並注入方法與物件的時機,這取決於H5頁面上的js引用時機,如果H5頁面上使用require來進行順序引用,就不會出現問題,如果與原生互動的js的程式碼載入與原生注入的注入順序混亂,則呼叫不到原生暴露的方法會引起js執行異常。建議結合攔截url的方式讓H5決定何時注入,或者是前端工程師梳理規範,在H5引用js的時候做順序控制。

    防止注入與釣魚

    其實這個不太算是技術方案,不過可以提一下。有時候手機在危險的網路環境中比方說連結在不安全的路由器中,DNS進行惡意中轉到釣魚網站上,如果頁面呼叫已知的原生暴露出來的方法,同步資料或者是呼叫關鍵業務,就會有注入攻擊的風險。一般需要做的是,H5在呼叫app原生關鍵業務的時候,需要在呼叫原生方法的時候傳入票據,原生通過服務端的認證中心驗證票據,通過才可以處理頁面呼叫請求,在同步資料與狀態的時候,比方說將app中的使用者登入狀態同步到H5頁面上,一般app會同步cookie,不過這種方式維護成本較高。對於同步狀態與資料,app應該使用業務票據來傳遞給H5,H5通過票據中心置換出真正的使用者狀態或者是關鍵業務資料。更高級別的方案還有H5與App臨時握手等。

    H5在WebView中的Debug

    這個是一個比較噁心的事情,不過我們可以替換js的window物件上的console物件,將log函式轉接到原生,再通過一些其他方式進行輸出,JavaScriptCore中提供了exceptionHandler
    context.exceptionHandler = ^(JSContext *context, JSValue *exception) { NSLog(@"JS Error: %@", exception);};
    下一篇文章將會介紹一下用websocket協議,將app中的WebView的除錯資訊輸出到指定IP的電腦上,方便開發除錯,這樣就能減少溝通與配合聯調,提高開發效率。
  • 相關推薦

    h5App原生互動方案

    方便測試階段,H5嵌入到App當中,開發人員方便除錯與Debug。 目前主流的技術方案: 1.在iOS7以前,在UIWebView中實現一些代理方法攔截帶有約定好的protocol的Url,從Url上獲取get方式的引數傳遞,對映成本地原生方法,如下: -(BOOL)webView:(UIWebView *)

    記一次利用vue.js完成的h5app互動

    嘮叨:最近接收一個用vue寫的專案,對我來說甚是頭大。不得不說這是對傳統前端的一次大過濾,之前仗著html,css,js混飯吃的前端兒們,壓力越來越大,我就是這樣的一個例子。壓力越大,只要不放棄,成長的也越快啊,所以,咬牙就咔咔開始幹。 需求:一個H5分享頁面

    H5App互動(WebViewJavascriptBridge)

    最近有時間整理下H5與APP的互動框架(WebViewJavascriptBridge),既可以和ios互動也可以和安卓互動,我只做了和IOS的互動,所以只闡述和IOS的互動。 1:JS端的操作 /* WebViewJavascriptBridge框架使用 這段程式碼是固

    H5android原生的JS互動

    公司最近接手了一個電信的專案,其中最關鍵的技術就是H5頁面與android的互動。因為之前專案中H5與原生介面的載入動畫是分開寫的,導致大小以及效果有差距,所以我才有接觸兩者之間互動的學習機會。簡單

    H5頁面APP互動

    概述 APP呼叫H5頁面時,出現有些頁面頁頭重複的現象,需去掉H5頁頭使用原生APP頁頭。 解決方案 方案一: 前端在網頁中寫一個隱藏頭部的方法,客戶端直接呼叫; 方案二: 使用userAgent判斷當前頁面是否在webView裡開啟: 兩種判斷方式: 1.與

    app互動

    export const connectWebViewJavascriptBridge = (callback) => { if (window.WebViewJavascriptBridge) { callback(WebViewJavascriptBridge) }

    通過頁面呼叫APPH5APP互通】

    http://www.cnblogs.com/carlos-guo/p/3945112.html 現在H5和App原生的內容原來越互通,所涉及的業務也越來越複雜和融合,所以如何互相之間方便的呼叫才是王道。 場景1    比如用hybrid獲取地理位置和簡訊資訊,這當然

    JSAndroid原生互動

    JS與Android原生互動 在專案的開發中我們會遇到android 原生與Html5的混合開發,我們可能會需要在android中呼叫js裡面的方法進行資料互動或其他的特殊處理,又或者在Html頁面呼

    h5和iOS原生互動,h5和iOS互相傳值

    前言 : h5和iOS原生互動,互相傳值,下面程式碼是完整的.M檔案  簡單實現h5和原生互動,互相傳值。 // //  ViewController.m //  原生-H5簡單互動 // //  Created by Mr Yang on 2018/7/23. //  C

    BLE 藍芽 APP互動 內設 外設

    藍芽設定  CoreBluetooth框架的核心其實是:peripheral和central,對應他們分別有一組相關的API和類 這兩組api粉筆對應不同的業務常見:左側叫中心模式,就是以你的app作為中心,連線其他的外設的場景;而右側稱為外設模式,使用`手機作為外設`

    h5 原生 app 互動的原理

    現在移動端 web 應用,很多時候都需要與原生 app 進行互動、溝通(執行在 webview中),比如微信的 jssdk,通過 window.wx 物件呼叫一些原生 app 的功能。所以,這次就來捋一捋 h5 與原生 app 互動的原理。 h5 與原生 app 的互動,本質上說,就是兩種呼叫:

    Hybrid開發-----H5原生App互動

    http://www.cnblogs.com/yexiaochai/p/5813248.htmlhttp://www.cnblogs.com/nildog/p/5536081.htmlHybrid開發效率高、跨平臺、低層本 Hybrid從業務開發上講,沒有版本問題,有BUG能

    環法競猜項目:H5原生APP交互方式

    一個 lua shp stringify response else all alert 延遲 APP調用H5函數 (1)登錄功能——調起APP的登錄頁面 操作:點擊h5頁面的"去登錄"按鈕,執行appLogin函數,檢測window對象是否有WebViewJavascri

    H5原生Android互動

    前言: 在專案中有時候需要APP和H5之間相互呼叫方法來實現某些功能,本文主要介紹Android是怎麼實現相互呼叫對方的方法。 H5呼叫APP的方法——APP來實現一些功能 H5將所需要的引數通過JSon字串的形式傳給APP Android——根據webview

    shiroapp利用token進行互動的解決方案

    shiro在收到請求時會預設讀取cookie裡的資料來判別客戶端的身份,然而我的專案沒有用cookie,伺服器也不處理cookie資訊,我們看看shiro讀取cookie的程式碼: //SimpleCookie類的readValue方法 public Stri

    h5頁面Android原生頁面互動

    Android頁面內巢狀h5頁面已經是隨處可見了。在Android原生頁面和h5頁面的取捨上那些不是本文的重點。重點是,如此多的頁面用網頁來寫,那麼必定涉及到網頁與原生的互動,俗稱js互動。 目標:h5頁面點選按鈕Android端接收到網頁傳給的json資料。

    微信中通過頁面(H5)直接打開本地app的解決方案

    ids 支持 完全 系統默認 domain rdquo bili 通過 解決 簡述 微信中通過頁面直接打開app分為安卓版和IOS版,兩個的實現方式是完全不同的。 安卓版實現:使用騰訊的應用寶,只要配置了“微下載”之後,打開鏈接騰訊會幫你判斷本地

    Flutter的需要原生互動的一些常用庫

    轉自: https://github.com/AweiLoveAndroid/Flutter-learning/blob/master/readme/Flutter%E7%9A%84%E9%9C%80%E8%A6%81%E4%B8%8E%E5%8E%9F%E7%94%9F%E4%BA%A4%E4

    h5mui開發app標題的滑動實現和樣式追蹤

    mui.init({ gestureConfig: { longtap: true //預設為false }, swipe:true, //啟用右滑關閉功能 pullRefresh : { container:".mui-scroll-wrappe

    小程式 App H5 之間的區別

    小程式的實現原理   根據微信官方的說明,微信小程式的執行環境有 3 個平臺,iOS 的 WebKit(蘋果開源的瀏覽器核心),Android 的 X5 (QQ 瀏覽器核心),開發時用的 nw.js(C++ 實現的 web 轉桌面應用)。 平臺渲染js 執行環境 iOSWKWe