亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

利用C#開發移動跨平臺HybridApp(一):從Native端聊Hybrid的實現

2019-11-14 13:44:48
字體:
來源:轉載
供稿:網友

0x00 前言

前一段時間分別讀了兩篇博客,分別是葉小釵兄的《淺談Hybrid技術的設計與實現》以及徐磊哥的《從技術經理的角度算一算,如何可以多快好省的做個app》。受到了很多啟發,同時也有自己的一些看法。因為目前三大平臺(雖然wp的份額相對于iOS以及android來說十分可憐)的開發語言分別是Objective-C(swift)、java以及C#,先不論平臺的其他特性如何,單單是各個平臺開發語言就已經不同了。而往往一個App要同時登陸不同的多個平臺,那么如何能夠快速的開發跨平臺的App,盡量使得代碼復用便成了一個開發者不得不面對的問題。

正如葉小釵兄在他的那篇博文中所說的:“這個時候使用IOS&Andriod開發一個APP似乎成本有點過高了,而H5的低成本、高效率、跨平臺等特性馬上被利用起來形成了一種新的開發模式:Hybrid APP。”——利用Web配合Native開發的Hybrid APP出現了。所以在正式介紹C#開發跨平臺App之前,我覺得有必要先從不使用C#語言進行開發的另外兩個平臺(iOS~OC、Android~Java)的角度來聊聊Hybrid。需要提醒各位注意的是本文中我所使用的一些web端代碼來自葉小釵兄所分享的web端“簡單Hybrid框的實現”的代碼 。

本文所使用的iOS端Hybrid的代碼可以在這里查看:

https://github.com/chenjd/iOS-Hybrid-Sample

0x01 你好,WebView

由于Hybrid開發的Web端本質上是一些網絡頁面,因此在使用App的相關功能時相當于利用原生平臺去訪問一些網頁。正是因為內容來源于網頁而不是依賴于平臺,因此也就變相的實現了跨平臺。那么對于iOS和Android來說,它們需要在Native端提供一個用來訪問頁面的容器——WebView。

iOS的UIWebView

在iOS平臺我們會使用UIKit.framework的UIWebView來訪問頁面。利用UIWebView控件,iOS平臺既可以獲取網絡資源也可以加載本地的HTML代碼。這里主要會使用的是以下三個方法:

UIWebView控件中加載資源的方法
- (void)loadData:(NSData *)data        MIMEType:(NSString *)MIMETypetextEncodingName:(NSString *)encodingName         baseURL:(NSURL *)baseURL
- (void)loaDHTMLString:(NSString *)string               baseURL:(NSURL *)baseURL
- (void)loadRequest:(NSURLRequest *)request

 

下面我們就利用這些方法,在iOS平臺上使用UIWebView控件來訪問葉小釵兄所提供的web頁面。

//ViewController.h@interface ViewController : UIViewController{    UIWebView *webView;}//ViewController.m- (void)viewDidLoad {    [super viewDidLoad];    webView = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];        //load yexiaochai's html    NSBundle *thisBundle = [NSBundle mainBundle];    NSString *path = [thisBundle pathForResource:@"webapp/hotel/index" ofType:@"html"];    NSURL *baseURL = [NSURL fileURLWithPath:path];    NSURLRequest *urlReq = [NSURLRequest requestWithURL:baseURL];    [self.view addSubview: webView];    [webView loadRequest:urlReq];

在iOS模擬器中運行,我們可以看到在Native端通過UIWebView已經加載出了Web端的內容。

當然,此時我們只是邁出了第一步,即在Native端渲染出Web端的內容。但是還沒有涉及到Native和Web之間的交互。既然說道了Native和Web交互,那么便不得不提的是另外兩個重要的方法:

UIWebView控件中涉及Native和Web交互的方法

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
- (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

 

除此之外,iOS的UIWebView還有一些頁面能否前進后退的屬性以及控制它們前進后退的方法:

UIWebView控件中關于頁面前進后退的屬性和方法

canGoBack
canGoForward
- (void)goBack
- (void)goForward

 

初步介紹完iOS的UIWebView之后,再讓我們來看一看Android平臺上的Web頁面的容器——WebView。

Android的WebView

在Android的部分,我們首先需要知道的是在Andorid平臺上我們使用的是android.webkit下的WebView來訪問頁面。和iOS平臺類似,Andorid平臺是通過利用WebView來實現獲取網絡資源或是加載本地的HTML代碼的。需要提醒各位注意的一點是,為了使Activity能夠正確的連接上網絡,在使用WebView加載遠程資源時務必確保在AndroidManifest文件中開啟INTERNET權限:

<uses-permission android:name="android.permission.INTERNET" />

而WebView加載資源的方法主要包括以下幾個:

WebView加載資源的方法
public void loadUrl(String url);
public void loadUrl(String url, Map<String, String> additionalHttpHeaders);
public void loadData(String data, String mimeType, String encoding);
public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl);

下面我們就利用這些方法,在Andorid平臺上使用WebView控件來訪問葉小釵兄所提供的web頁面。

首先我們要在Native端添加一個WebView控件,通過在layout文件中添加<WebView>就可以十分容易的實現。

<?xml version="1.0" encoding="utf-8"?><WebView  xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/webview"    android:layout_width="fill_parent"    android:layout_height="fill_parent"/>

當然,除了在layout中添加<WebView>元素之外,我們可以直接通過代碼在Activity設置為WebView,

WebView webview = new WebView(this);setContentView(webview);

不過下文還是假設我們在layout中添加了<WebView>元素。
此時,我們在Native端已經準備好了盛放Web頁面的容器。接下來便是加載Html資源了。

WebView myWebView = (WebView) findViewById(R.id.webview);myWebView.loadUrl("file:///android_asset/webapp/hotel/index.html");

到這里我們便再次將葉小釵兄的Web頁面渲染了出來。
和上文描述iOS類似,此時我們也僅僅是邁出了第一步,即在Native端渲染出Web端的內容。但是還沒有涉及到Native和Web之間的交互。不過Android平臺和iOS平臺當然也存在著區別,例如默認狀態下Andorid的WebView是不支持js的,所以如果我們僅僅是將一個web頁面作為一個沒有交互的靜態UI是可以的,但是如果想要使用js進而實現Native和Web的交互,那么還需要多設置一些內容。這里我們需要獲取WebView的WebSettings對象,在WebSettings中開啟對js的支持。

WebView myWebView = (WebView) findViewById(R.id.webview);WebSettings webSettings = myWebView.getSettings();webSettings.setJavascriptEnabled(true);

好了,開啟了對js的支持,也就是開啟了對Native和Web交互的支持。而Android平臺主要通過以下方法來實現Native調用web以及web調用Native的:

  • public void evaluateJavaScript(String script, ValueCallback<String> resultCallback);方法可以在Native端調用JS代碼,當然這里存在一個Android版本的問題,下文還會詳細說明。
  • 另外我們需要使用JavascriptInterface.java,通過這個interface來完成Web調用Native的實現。

除此之外,Android的WebView當然還有和iOS的UIWebView類似的用來控制頁面行為的一些方法:

  1. canGoBack();
  2. goBack();
  3. canGoForward();
  4. goForward();

0x02 Native端調用JS

在上一小節中我分別向大家介紹了iOS和Android在Native端是如何做到既能夠訪問Native本地資源,又能夠訪問遠程資源的。這樣在App開發的過程中將部分常常需要更新的模塊以Web的形式創建,不僅僅避免了用戶升級App整包替換的情況,又能夠比較快速的實現多平臺更新迭代。

而這一切的背后都離不開Native和Web之間的交互。這種交互說起來無非是Native調用Web的方法,或是Web調用Native的方法。那么在本小節,我就和大伙分別聊聊iOS和Android是如何調用Web中的方法的。

iOS Native調用JS

//ViewController.h@interface ViewController : UIViewController{    UIWebView *webView;    NSMutableString *msg;    UITextField *msgText;    UIButton *nativeCallJsBtn;}//ViewController.m- (void)createNativeCallJsSample{    [webView loadHTMLString:@"<html><head><script language = 'JavaScript'>function msg(text){alert(text);}</script></head><body style=/"background-color: #0ff000; color: #FFFFFF; font-family: Helvetica; font-size: 10pt; width: 300px; Word-wrap: break-word;/"><button type='button' onclick=/"msg('Js調用')/" style=/"margin:30 auto;width:100;height:25;/">web button</button></body></html>" baseURL:nil];    //創建一個UITextField,用來在native調用js時向js的函數傳送參數    [self createNativeTextField];    //創建一個按鈕,用來演示Native調用js    [self createNativeCallJsButton];}...//native 調用 js- (void)btnClickMsg{    [msg setString:@"msg('"];    [msg appendString:@"native調用js:"];    [msg appendString:[msgText text]];    [msg appendString:@"')"];    [webView stringByEvaluatingJavaScriptFromString:msg];}

我們首先使用UIWebView的loadHTMLString方法,直接加載了一段Html代碼。其中的JS部分定義了一個函數function msg(text){alert(text);},即調用alert方法。而在Native端,我們使用UIWebView的stringByEvaluatingJavaScriptFromString方法來實現對JS的調用。

最左邊的截圖是直接點擊Web頁面中HTML代碼生成的Button之后觸發的JS的msg方法。

而中間和右邊的截圖,則是通過Native的UITextField控件獲得用戶的輸入之后再通過Native的按鈕控件調用btnClickMsg方法,進而調用stringByEvaluatingJavaScriptFromString方法之后,從Native端執行了JS的msg方法。

Android Native調用JS

Andorid平臺與iOS在調用JS的部分十分類似。不過需要提醒各位注意兩點,其一就是我們在上文提過的,Android的WebView默認狀態下沒有開啟和JS交互的功能。這里我們需要獲取WebView的WebSettings對象,在WebSettings中開啟對js的支持。第二點需要注意的是Android的版本問題。在Kitkat(4.4)之后,我們可以使用evaluateJavaScript方法來調用JS,而之前的版本我們直接調用WebView的loadUrl的方法,將JS代碼作為參數傳入。

@OverridePRotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    ...    WebView myWebView = (WebView) findViewById(R.id.webview);    WebSettings webSettings = myWebView.getSettings();    //開啟js支持    webSettings.setJavaScriptEnabled(true);    myWebView.loadData("<html><head><script language = 'JavaScript'>function msg(text){alert(text);}</script></head><body><button type='button' onclick= 'msg()'>web button</button></body></html>", "text/html", "utf-8");    evaluateJavascript(myWebView);}....//Native調用JSpublic static void evaluateJavascript(WebView mWebview) {    //判斷版本調用不同的方法    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {        mWebview.evaluateJavascript("msg('native call js')", null);    } else {        mWebview.loadUrl("msg('native call js')");    }}
View Code

0x03 Web調用Native

Hybrid交互設計

我想行文至此,各位應該已經明白了兩大平臺(iOS和Android)的Native端是如何調用JS代碼的了。那么本小節則主要來聊一聊Web是如何調用Native的。Web和Native之間交互的第一步便是要約定好格式。由于我直接使用了葉小釵兄的Web部分,因此按照他設計的Web請求Native的模型:

requestHybrid({  //創建一個新的webview對話框窗口  tagname: 'hybridapi',  //請求參數,會被Native使用  param: {},  //Native處理成功后回調前端的方法  callback: function (data) {  }});//index.html中的實際例子requestHybrid({    tagname: 'forward',    param: {        topage: 'webapp/flight/index',        type: 'webview'    }});

而Native端會收到一個URL,例如:

hybrid://forward?t=1447949881120&param=%7B%22topage%22%3A%22webapp%2Fflight%2Findex%22%2C%22type%22%3A%22webview%22%7D
十分清楚,這里我們交互使用的schema是hybrid://,在Native部分會監控Webview發出的所有schema://請求,然后分發到“控制器”hybridapi處理程序,Native控制器處理時會需要param提供的參數。下面就讓我們來分別看一下iOS和Android是如何使用Web調用Native的吧。(這里我只是簡單的實現了和葉小釵兄web交互的iOS部分,Android部分演示的是一個簡單的Web調用Native的例子)。

iOS Web調用Native

在iOS平臺,我們會用到shoudStartLoadWithRequest這個方法來捕獲Web所發出的請求。下面我們就來看一段簡單的演示吧。

//按照和web端規定的格式,獲取數據- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {    NSURL * url = [request URL];    if ([[url scheme] isEqualToString:@"hybrid"]) {        NSString *actionType = request.URL.host;        //從url中獲取web傳來的參數        NSDictionary *actionDict = [self getDicFromUrl : url];        //根據web的指示,native端相應的做出回應        [self doActionType:actionType : actionDict];        return NO;    }    return YES;}//從url中獲取web傳來的參數- (NSDictionary *) getDicFromUrl : (NSURL *)url{    NSArray* paramArray = [[url query] componentsSeparatedByString:@"param="];    NSString* paramStr = paramArray[1];    NSString *jsonDictString = [paramStr stringByRemovingPercentEncoding];    NSData *jsonData = [jsonDictString dataUsingEncoding:NSUTF8StringEncoding];    NSError *e;    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e];    return dict;}//根據web的指示,native端相應的做出回應-(void) doActionType : (NSString*) type : (NSDictionary*) dict{        if ([type isEqualToString:@"forward"]) {        [webView goForward];    }    //打開一個新的Web    if([dict[@"type"] isEqualToString: @"webview"]){        [self web2Web: dict[@"topage"]];    }    //打開一個Native頁面(我簡化為了控件)    else if ([dict[@"type"] isEqualToString: @"native"]){        [self web2Native];    }}

 最左邊的圖是最開始的Web頁面,點擊“新開webview...”按鈕之后,Native端又打開了一個新的Web頁面,即中間的圖所示。

最右邊的圖演示的是點擊“跳轉native...”按鈕之后,Native端創建了一個Native的UI控件。

Android Web調用Native

Android平臺上Web調用Native要比iOS稍微復雜一些。因為在Android平臺上我們需要借助JavaScriptInterface來實現Web調用Native的功能。

下面就讓我們演示一個小例子,不讓Web調用JS的alert,相反使用Web調用Native的Dialog來顯示提示吧。

首先我們要在Android應用中引入JavaScriptInterface。

......import android.webkit.JavascriptInterface;public class WebAppInterface {    Context mContext;    WebAppInterface(Context c) {        mContext = c;    }    @JavascriptInterface    public void showToast(String toast) {        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();    }}

之后,我們使用WebView的 addJavascriptInterface()方法將這個類和JS代碼綁定,作為Web調用Native的橋梁。

WebView webView = (WebView) findViewById(R.id.webview);webView.addJavascriptInterface(new WebAppInterface(this), "Android");

最后,在Web端也做相應的實現。點擊Web中的button會調用Native的showToast方法。

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /><script type="text/javascript">    function showAndroidToast(toast) {        Android.showToast(toast);    }</script>

 

0x04 讓Web的歸Web,Native的歸Native

到此,在沒有使用C#作為開發語言的兩大平臺上使用Hybrid的方式令Web和Native交互的內容就介紹完了。但是,不知道各位讀者是否和我有相同的感覺呢?那就web和native之間的界線仍然十分明顯。

事實上我認為Hybrid的最大價值其實并不在于跨平臺。相反,在一些常常變動的模塊的熱更新的問題上使用這種將Web和Native結合的Hybrid方式是十分適合的。

這是因為它并沒有從本質上解決所謂的跨平臺的問題,而是采用了一個十分討巧的方式或者說是逃避問題的方式超脫于平臺的范疇。而這也導致了Hybrid的缺點,比如Hybrid體驗和Native相比是有距離的。因此,Hybrid是一種優秀的熱更新技術,同時也是一個不完美的跨平臺方案。

至于解決跨平臺問題更好的方案,就交給Native端自己去想辦法吧。比如三大移動平臺都使用同一種語言甚至是同一個IDE進行Native部分的開發,看上去似乎就是一個很美妙的方案。如果再加上利用Hybrid方式帶來的熱更新加持,結果就更棒了。

所以,就讓Web的歸Web,Native的歸Native吧。

未完待續~~~~~

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本精品免费观看| 中文字幕精品网| 欧美性videos高清精品| 视频一区视频二区国产精品| 午夜精品免费视频| 久久夜精品va视频免费观看| 国产主播在线一区| 亚洲国产成人精品久久久国产成人一区| 日韩一区二区三区国产| 国产精品主播视频| 欧美日韩中文字幕综合视频| 尤物九九久久国产精品的特点| 欧美性一区二区三区| 欧美日韩精品在线播放| 日韩男女性生活视频| 欧美一区视频在线| 亚洲图片在线综合| 亚洲国产成人精品久久| 国产精品美乳在线观看| 日韩中文在线观看| 亚洲欧美中文在线视频| 欧美疯狂做受xxxx高潮| 成人亚洲综合色就1024| 久久国产天堂福利天堂| 综合国产在线观看| 亚洲精品久久7777777| 日韩精品免费在线视频观看| 亚洲欧美中文字幕在线一区| 91久久久久久久久久| www高清在线视频日韩欧美| 久久久亚洲影院| 国产拍精品一二三| 精品中文字幕乱| 欧美成人国产va精品日本一级| 最近中文字幕2019免费| 国产精品久久久久9999| 97激碰免费视频| 欧美在线激情视频| 久久乐国产精品| 69国产精品成人在线播放| 91探花福利精品国产自产在线| 日韩国产精品视频| 啊v视频在线一区二区三区| 欧美国产日韩视频| 岛国精品视频在线播放| 亚洲成avwww人| 亚洲乱码av中文一区二区| 久久人人看视频| 日韩在线播放一区| 日韩在线精品一区| 亚洲欧美日韩国产中文| 久久久久亚洲精品国产| 成人午夜一级二级三级| 色偷偷av亚洲男人的天堂| 国产精品免费在线免费| 亚洲色图校园春色| 亚洲综合社区网| 欧美大尺度电影在线观看| 亚洲欧美国产另类| 欧美精品一区二区三区国产精品| 亚洲第一页自拍| 成人国产精品久久久| 亚洲欧美在线免费| 成人国产精品久久久久久亚洲| 亚洲欧美制服另类日韩| 日本成人黄色片| 中文字幕综合在线| 亚洲第一黄色网| 国产精品成人免费视频| 精品国产乱码久久久久久天美| 最近2019中文字幕mv免费看| 国产一区二区激情| 日韩国产精品一区| 国产丝袜精品第一页| 日韩在线视频一区| 亚洲人成伊人成综合网久久久| 国产日韩欧美日韩大片| 国产亚洲免费的视频看| 日韩av在线免费看| 97精品视频在线| 国产z一区二区三区| 亚洲精品视频免费| 国产精品入口免费视| 日韩在线观看免费av| 97免费中文视频在线观看| 国模gogo一区二区大胆私拍| 亚洲天堂av在线免费观看| 欧美在线国产精品| 亚洲国产精彩中文乱码av在线播放| 国产精品视频自在线| 伊人一区二区三区久久精品| 在线视频亚洲欧美| 欧洲精品久久久| 久久久久久久久久久免费| 亚洲第一精品久久忘忧草社区| 91精品国产乱码久久久久久久久| 亚洲香蕉在线观看| 国产美女直播视频一区| 久久久亚洲精品视频| 欧美亚洲成人xxx| 亚洲成人教育av| 午夜精品视频网站| 91综合免费在线| 亚洲午夜小视频| 91免费看视频.| 日韩国产高清视频在线| 亚洲天堂av在线播放| 欧美精品福利视频| 色噜噜狠狠狠综合曰曰曰| 在线午夜精品自拍| 亚洲欧美日韩一区二区三区在线| 韩国欧美亚洲国产| 国产精品丝袜视频| 日韩高清电影好看的电视剧电影| 日韩av有码在线| 一区二区三区精品99久久| 色偷偷888欧美精品久久久| 日本19禁啪啪免费观看www| 色妞久久福利网| 日韩人在线观看| 亚洲国产中文字幕在线观看| 欧美午夜视频一区二区| www国产91| 国产91亚洲精品| 亚洲欧美中文日韩在线v日本| 国产视频在线观看一区二区| 在线视频精品一| 青青草原一区二区| 亚洲国产成人91精品| 久久精品99国产精品酒店日本| 一本色道久久88综合亚洲精品ⅰ| 欧美中文在线视频| 91欧美精品午夜性色福利在线| 国产午夜精品全部视频播放| 亚洲午夜久久久影院| 久久全国免费视频| 精品国偷自产在线视频| 97在线视频国产| 亚洲精品720p| 国产在线观看一区二区三区| 91国产一区在线| 98精品国产高清在线xxxx天堂| 国产suv精品一区二区| 日韩av在线天堂网| 97在线精品视频| 国产精品久久久久久中文字| 国产专区精品视频| 黑人欧美xxxx| 亚洲欧美一区二区三区情侣bbw| 欧美制服第一页| 岛国av午夜精品| 国产欧美一区二区三区久久人妖| 久久久在线免费观看| 欧洲日韩成人av| 久久精品中文字幕一区| 少妇av一区二区三区| 91在线视频一区| 亚洲国产日韩一区| 色妞色视频一区二区三区四区| 欧美与欧洲交xxxx免费观看| 国产精品私拍pans大尺度在线| 精品久久久久久中文字幕大豆网| 91在线视频精品| 欧美日韩在线视频一区二区|