精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

移動開發中如何整合HTML 5和原生代碼

譯文
移動開發
使用HTML 5開發應用比起為每一種不同的平臺從頭開始編寫代碼,是一種能跨不同平臺而代碼量較少的一種方式。在這種情況下,大部分的用戶界面,甚至全部的界面都可以通過HTML 實現。

最近業界關于移動開發中的究竟使用原生代碼還是HTML 5代碼的爭論依然持續。目前來說有三種方式去進行移動開發

•    原生代碼,
•    hybrid(混合型)移動應用
•    移動Web app(使用HTML5)
使用HTML 5開發應用比起為每一種不同的平臺從頭開始編寫代碼,是一種能跨不同平臺而代碼量較少的一種方式。在這種情況下,大部分的用戶界面,甚至全部的界面都可以通過HTML 實現。

“Hybrid應用”一詞,指的是移動應用大部分是用HTML 5去編寫界面,而部分需要訪問特定設備功能的則使用原生代碼。大部分這些原生代碼并不是自然生成可視的,而僅僅通過特定的轉換將數據返回給應用的HTML 5界面,再經過渲染返回給用戶。PhoneGap這個框架就提供了這樣的功能。

[[88958]]

大部分關于HTML 5的爭論并不是著眼于討論它是否能勝任移動應用中的用戶體驗。Facebook創始人 Mark Zuckerberg在他的對Facebook在使用HTML 5中遇到的困難一文中作了相關評論。Facebook的一些問題可以通過由Sencha Touch框架進行解決(參考SenchaTouch自己的一個例子Fastbook),也可以通過LinkedIn在其infinite scrolling post一文中解決。此外,LinkedIn隨后還提供了使用更多的原生代碼解決關于轉換方向的問題。

為何不進行整合?

與其使用全部的原生代碼或者HTML 5代碼去開發,為什么不將兩者進行整合呢?使用混合型開發移動應用,可以同時利用原生和HTML 5代碼開發用戶界面。這就能讓開發者在設計用戶界面的時候能使用最適合的工具。

很明顯,對于開發用戶應用界面使用兩種或者更多的技術是有其缺點的。最重要的是必須讓開發者既掌握原生的開發又掌握HTML 5。使用原生代碼開發的用戶界面不大容易在其他平臺使用,并需要重新開發。由于這些技術需要更廣泛的知識面和上面提到的困難,為什么還有人嘗試努力使用這它?

HTML 富文檔界面

可能你的用戶體驗告訴你文檔可以以富文本格式進行顯示更為精彩。雖然在iOS上可以使用NSAttributedString進行富本文格式化,但這種文檔的結構并不適合遷移到其他設備平臺中,也不能完整由HTML再現。如果文檔中需要使用如表格進行顯示,則象NSAttributedString的解決方案是不能奏效的。考慮下面的一家基因檢測公司的iPad應用,如下圖,是一個混合型界面的例子:

請注意看上面的圖,很難從表面上分辨這到底哪部分是用原生代碼編寫的,哪部分是用HTML 5編寫的。這個界面中的右邊部分是可變的長度。表格是包含可擴展的行,完全使用CSS3動畫效果,而頁面中其他文字部分都是相同的高度。

Documents such as this are what HTML does best. Trying to create something like this in native code would have entailed considerably greater effort, with little benefit to the user. In this application, the HTML5 is generated with a mustache template, via theGRMustache library for iOS.

像這樣的頁面使用HTML 5實現是最好的。如果嘗試使用原生代碼去實現則要花費很大功夫,而且對用戶好處不多。在這個應用中,通過使用為iOS而設的GRMustache類庫去生成相關的HTML 5模板。下圖中用顏色區別表明了哪個部分是使用HTML5,哪個部分使用原生代碼。

注意當用戶移動滾動條的時候,在右側頂部的文檔頭部會動態改變大小以顯示更多的內容,從而說明用戶界面之間是如何互動的。用戶可以點在HTML 5實現部分的連接和按鈕,以彈出一個內置的Web瀏覽器以加載相關內容。在本文接下來的部分,會看到在原生代碼的界面和HTML 5的界面之間互相連接是很容易的事情。

兩全其美的解決方法

正如我們所看到的,可以在同一個應用的屏幕中整合兩種不同的技術以提供無縫的體驗。你可能希望在iOS上使用UINavigationController和與之相關的 UINavigationBar控件,或者在Android應用中使用action bar,而剩下的部分則使用HTML 5渲染。

下面是一個使用HTML 5設計的購物車應用體驗,但依然有保留原生的導航控件和用于頁面導航的tab工具條:

這里,HTML 5內容實際上是從服務端加載的,它在整個用戶體驗中控制著流程。有相關的API允許服務端生成的HTML去修改導航控件中的內容以適應瀏覽的過程。

你可能會發現原生的控件,如iOS中的MapKit等都提供了比HTML 5控件更好的性能體驗,在這種情況下,應該使用HTML 5代碼去和iOS原生代碼層通信,讓其返回內容并呈現。

上面的兩個圖描述了一個綜合運用原生和HTML 5的購物應用。用戶首先在地圖中選擇了商店地址,然后數據將已HTML 5的方式呈現,用戶并繼續購物。

一旦用戶完成了和地圖的交互,結果則會馬上傳遞到HTML 5頁面中以作進一步處理。原生“控件”可以在任何平臺(iOS、Android、Windows等)中實現,這取決于應用是如何架構,并且能從HTML5應用中調用。使用這個策略,HTML 5代碼將提供對整個應用流程的控制,而原生代碼則在后臺運行等到需要的時候提供數據,如果處理恰當,用戶是很難區分應用的哪一個部分是使用HTML5,哪一個部分是使用原生代碼。

#p#

更容易的應用更新

大多數人都知道為了在iOs或者Android應用中更新應用,都必須重新通過相應平臺正常的渠道去重新提交。對于Ios,可能需要等待七天去獲得蘋果的批準,這就很難在當今移動應用的狂潮中滿足用戶的迫切需要。如果通過HTML和Javascript的方法去給用戶移動體驗,則意味著可以通過Web去動態滿足用戶的需要。

正如前文說的,由于可以通過Web的方法調用應用中的原生代碼,則看上去這其實是一種”橋梁”的機制。PhoneGap就是通過PhoneGap plugin interface去實現。之前的購物商店的例子就是使用這個方法。使用這個方法可以使得購物的流程如果改變后不再需要走繁瑣的原生應用的發布流程。如果一個設計良好的界面可以使得頁面和原生容器之間的通訊變為可能。

關于內容方面

對于來自Web的內容,通常最好能限制其通過這種橋接技術的流量。類似PhoneGap的內置的功能提供了很多設備的信息,其中一些可能會遠遠超出應用程序的所需要。如果由于某種原因Web內容被泄露,比如跨站點腳本攻擊,你可能會突然發現這些內容會以某種方式調用本地代碼。

基于這個原因,當需要使用混合型移動應用的時候,應該使用你自己的橋接代碼,以嚴格控制哪些代碼可以動態加載什么樣的內容。一些平臺有自己的控制方法去限制從Web viewer中對原生代碼的調用。在Android中,類必須明確自己注冊通過JavaScript訪問。在Android 4.2中,可以進一步通過在需要從Web viewer中訪問的方法前添加@ JavaScriptInterface注解去限制其調用。

需要考慮的要點

•     如果用戶在線,直接從Web服務器容是很好的。請記住,移動應用的網絡連接問題。如果網絡連接中斷,會發生什么事? 有的時候可以通過AppCache實現一些離線功能,但這需要規劃。另一種方法在稍后介紹,使用的是本地存儲。

•     托管在Web服務器上的內容需要一定的基礎設施?,F在有更多的需要被視為移動應用組成部分的“組件”。它不再僅僅是一些通過AppStore部署的原生代碼和一些后端的服務。必須小心的是在網站更新的時候,不要移動應用程序與現有的接口間發生沖突。請記住,網站的內容發生了變化,則必須更新移動應用程序本身。出于這個原因,可能需要對網站的內容進行必要的版本標記以區分其內容。

•   
蘋果公司對僅僅包裹在原生應用中的Web view這樣類型的應用持悲觀看法。如果你只是在一個原生移動應用中,僅僅包含一些Web內容,則可能在提交iOS的AppStore審批時不會得到批準。蘋果公司希望你的應用程序將使用的一些設備自身的功能,或者好歹使用下Mobile Safari。。想想看,你的應用程序其實可以集成相機功能、聯系人列表、本地數據存儲,離線操作等,還要記得,這些Web view中提供的內容必須和原來應用提交的樣式等保持一致。

如果你創建了一個詞搜索游戲,然后突然開始在webview瀏覽器中有一些風馬牛不相及的內容,這將違反蘋果的條款,并可能在AppStore中下架。根據iOS開發者協議,每次的更新不能改變在提交appStore審核時闡述的該應用的主要功能。

體驗應用更新過程

正如上文提到的,從web服務器加載內容再刷新本地的內容。在這種方法中,只要web內容更新,服務器上的Web內容(HTML,CSS和JavaScript)會下載到移動應用程序客戶端。更新代碼就可以改變用戶的界面,應用流程等,這無需開發人通過使用iOS App Store或Google Play去處理。

注意的是只能更新HTML、CSS和Javascript,是不能更新原生代碼的。蘋果公司允許只要在iOs應用中在UIWebView控件的上下文中運行就可以下載Javascript。

上圖的應用是運行在Android中。HTML的內容是下載到用戶的移動設備中并存儲的。注意應用提供了導航條的用戶體驗。下圖則是運行在iOs的情景,使用的是UINavigationController :

除了加快更新過程,這種傳輸應用程序的方式能確保用戶獲得最新的代碼。在傳統的方法中,應用程序的更新是通過應用程序商店分發,并通知用戶有可用的更新,盡管他們并不需要安裝最新的更新。不是每個人都定期去更新應用程序。而在用戶瀏覽應用的時候,通過更新本地的HTML,CSS和JavaScript正好解決這個問題。

動態更新本地內容的功能,實際上是商業混合型移動應用開發平臺“Trigger.IO”的一部分。 Trigger.IO功能允許更新你移動應用的HTML部分。需要注意的是原生代碼不能以這種方式更新。但是,如果你應用程序的流程控制使用的JavaScript和增強的本機代碼,那么應用程序流程作發生變化的時候同步更新是可能的。

動態更新內容對開發和測試的好處

能動態更新一個移動應用,也可以加速開發進程。 iOS和Android的原生開發過程一般需要在桌面計算機上對應用程序代碼進行編譯,然后轉移到測試設備中去。一些發開發者項目,如Icenium、LiveSync或Ion則支持編譯應用的更新到云端,然后只需下載已經在設備上運行的應用程序,這就完成了更新。

當代碼進行了更改,并保存到服務器上,只需要一個簡單的三個手指頭的手勢動作就可以更新iOS設備上的應用程序。 Icenium也有類似的功能并可用于Android。 Adobe公司的PhoneGap通過一個被稱為Hydration的特性讓更新變得可能。在這種情況下,開發人員可以通過他們的IDE整合到各種設備上,而無需物理連接到這些移動設備,就可以推送新的代碼。

當Hydration功能啟用的時候,每次啟動應用程序時,應用程序將檢查PhoneGap構建服務器去看是否有新版本可用。如果有,用戶將被提示升級到新的版本。這可以使你的應用程序的質量得到保證,以及更容易使用。你將不必擔心簽署代碼更新、配置和測試等問題。

#p#

注意事項

雖然動態更新應用的功能很強,但記住并確保凡是來源于網絡的內容必須不能隨意調用設備的原生代碼。如果不這樣做,可能會導致你的用戶數據暴露給第三方,因此違反與蘋果或Google的協議。此外,動態更新內容不應該改變應用原來的功能。否則會可能被蘋果或者Google下架應用。

溝通兩個世界的橋梁

iOS和Android都提供了能在原生應用中使用的Web view控件,接下來的例子中將講解如何在Web view中使用Javascript調用原生代碼以及原生代碼如何調用在Web view中的Javascript。

[[88959]]

首先你必須使用PhoneGap(Apache Cordova),可以使用PhoneGap 1.4 for iOS 和PhoneGap 1.9 for Android。本文并不從PhoneGap的基礎開始講解,因此讀者可能需要到PhoneGap官網了解一些相關知識。對于iOs可以將CordovaWebView 放到原生的viewController控件中,而Android中也可以使用。這允許你的web代碼能訪問整個PhoneGap API并且訪問任何PhoneGap插件。當然可以根據PhoneGap plugin API 去將應用的原生代碼暴露給CordovaWebView。

假設你不需要使用PhoneGap的全部功能而只是需要在原生和HTML5兩個世界中使用它們部分的功能,則也可以自己去編寫代碼是實現這個橋梁。本文之前提到的三個應用都是使用“私有API”的方式去實現編碼的。

研究iOS中的UIWebView

在iOS中的UIWebView和相關的UIWebViewDelegate提供了相關的機制,并允許原生代碼和Javascript之間互相調用,下面準備了一個簡單的例子進行講解:

注意屏幕中的上半部分,淺灰色部分使用的是UIWebView進行渲染,而下半部分白色的使用的是原生代碼聲稱的。這個應用只是從Web view中傳遞JSON對象到原生代碼中,反之亦然,代碼和Android版本的可以在 這個地址下載:
https://github.com/ptraeg/html5-in-mobile-apps

從Javascript中調用原生代碼

從Javascript中去調用原生代碼很簡單,只是在方法中帶有command和以JSON格式要傳遞的參數,代碼如下:

  1.  var nativeBridge = { 
  2.    invoke: function (commandName, args) { 
  3.       console.log(commandName + ": " + JSON.stringify(args, null, 2)); 
  4.       window.location = 'js-call:' + commandName + ':' + 
  5.                       encodeURIComponent(JSON.stringify(args)); 
  6.   } 
  7. }; 


上面的代碼嘗試去將瀏覽器導航到一個新的URL,但并不是用傳統的http://或file://的URL。這里使用的是自定義協議js-call:,而在Objective-C方面,代碼如下:

 

  1. (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType (UIWebViewNavigationType)navigationType 

在這個調用的委托中,可以查詢傳入的URL是否是來自Javascript的調用:

 

  1. NSString *requestURLString = [[request URL] absoluteString]; 
  2. f ([requestURLString hasPrefix:@"js-call:"]) { 

接下來是判斷command的名字和JSON參數字符串:

 

  1.  NSArray *components = [requestURLString componentsSeparatedByString:@":"]; 
  2. NSString *commandName = (NSString*)[components objectAtIndex:1]; 
  3. NSString *argsAsString = [ (NSString*)[components objectAtIndex:2] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; 

 既然我們將參數作為字符串,則可以將其轉換為NSDictionary對象:

 

  1.  NSError *error = nil; 
  2. NSData *argsData = [argsAsString dataUsingEncoding:NSUTF8StringEncoding]; 
  3. NSDictionary *args = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:argsData options:kNilOptions error:&error]; 

最后,是時候調用正確的原生方法以處理Javascript調用的參數并且刷新原生UI:

 

  1. if ([commandName isEqualToString:@"updateNames"]) { 
  2.    [self updateNativeNameValuesWithFirstName:[args objectForKey:@"fname"
  3.                                     LastName:[args objectForKey:@"lname"]]; 

記得在通過js-call調用方法的時候,必須從委托中返回boolean值為no,以防止Web view嘗試訪問URL。

#p#

iOS原生代碼中訪問Javascript

這種方法比較簡單,因為我們沒有使用委托方法。我們可以簡單通過傳入要調用的JavaScript函數名和需要的參數作為字符串,傳給UIWebView的stringByEvaluatingJavaScriptFromString方法就可以了
在這里,我們從本地視圖中獲得值并且通過NSDictionary將其變成一個JSON對象。

 

  1.  NSDictionary *namesDict = @{@"fname": self.fNameTextField.text,  
  2.                             @"lname": self.lNameTextField.text}; 
  3. NSError *error; 
  4. NSData *namesData = [NSJSONSerialization dataWithJSONObject:namesDict  
  5.                                                     options:0  
  6.                                                       error:&error]; 
  7. NSString *namesJSON = [ [NSString alloc] initWithData:namesData 
  8.                                              encoding:NSUTF8StringEncoding] ; 

既然已經將JSON作為字符串傳遞,只需要格式化命令并傳遞到Web view中就可以了。

 

  1. NSString *jsCommand = [NSString stringWithFormat:@"setNames(%@)", namesJSON]; 
  2. [self.webView stringByEvaluatingJavaScriptFromString:jsCommand]; 

在Android中使用Webview

同樣,下圖是使用Android的Webview實現上面iOS例子的效果:

同樣,上部分灰色的是由Web View生成的,下半部分的是原生代碼生成。

從Javascript代碼中調用原生代碼

Android Web VIEW有個好處就是能將全部的Java類暴露給Javascript,這就不用象iOS那么麻煩了。首先只需要對Android Web view進行注冊設置就可以了,代碼如下:

 

  1. @Override 
  2. public void onStart() { 
  3.    super.onStart(); 
  4.    WebSettings webSettings = webview.getSettings(); 
  5.    webSettings.setJavaScriptEnabled(true); 
  6.    webview.loadUrl("file:///android_asset/webviewContent.html"); 
  7.    webview.addJavaScriptInterface(new WebViewInterface(this), "Android"); 

注意上面最后一行代碼,注冊了一個特殊的類名為WebViewInterface,它可以通過Javacript去訪問,此外,該類還通過字符串“Android”指出其命名空間,還可以測試是否注冊了Android命名空間,代碼為:

 

  1. if (window.Android) { 
  2.    Android.updateNames(JSON.stringify(nameData)); 

而在Java服務端,WebViewInterface是一個標準的Java類,如果使用的是Android 4.2 SDK,則必須使用@JavaScriptInterface去注解要暴露給Javascript的方法。

 

  1. public class WebViewInterface { 
  2.    Context mContext; 
  3.  
  4.    /** Instantiate the interface and set the context */ 
  5.    WebViewInterface(Context c) { 
  6.        mContext = c; 
  7.    } 
  8.  
  9.    @JavaScriptInterface 
  10.    public void updateNames(String namesJsonString) { 
  11.       Log.d(getPackageName(), "Sent from webview: " + namesJsonString); 
  12.       try { 
  13.          JSONObject namesJson = new JSONObject(namesJsonString); 
  14.          final String firstName = namesJson.getString("fname"); 
  15.          final String lastName = namesJson.getString("lname"); 
  16.  
  17.          // When invoked from JavaScript, this is executed on a thread  
  18.          // other than the UI thread. 
  19.          // Because we want to update the native UI controls, we must  
  20.          // create a runnable for the main UI thread. 
  21.          runOnUiThread(new Runnable() { 
  22.             public void run() { 
  23.                fnameEditText.setText(firstName); 
  24.                lnameEditText.setText(lastName); 
  25.              } 
  26.          }); 
  27.       } catch (JSONException e) { 
  28.          Log.e(getPackageName(),  
  29.             "Failed to create JSON object from Web view data"); 
  30.       } 
  31.    } 

注意當Javascript調用這個類中的方法的時候,它們并不是在主UI 線程中執行的,如果我們的目的是更新UI部分,則必須創建新的runnable線程并且傳遞給主UI線程執行:

 

  1. runOnUiThread(new Runnable() { 
  2.    public void run() { 
  3.       fnameEditText.setText(firstName); 
  4.       lnameEditText.setText(lastName); 
  5.    } 
  6. }); 

而在原生代碼中調用Javascript則比較簡單。將數據用JSON的形式存放到字符串中然后就可以給Javascript調用,注意要使用的是Javascript:協議:

 

  1. public void sendNamesToWebView() { 
  2.    JSONObject namesJson = new JSONObject(); 
  3.    try { 
  4.       namesJson.put("fname", fnameEditText.getText().toString()); 
  5.       namesJson.put("lname", lnameEditText.getText().toString()); 
  6.       webview.loadUrl( "JavaScript:setNames(" + namesJson.toString() + ")" ); 
  7.    } catch (JSONException e) { 
  8.       Log.e(getPackageName(),  
  9.         "Failed to create JSON object for Web view"); 
  10.    } 

WebView的缺點分析

和軟件開發的大多數情況一樣,我們必須審視WebView的一些缺點,特別是在制作混合移動應用時要注意:

•     不是所有的Web view都渲染成同樣的效果 在過去的兩年中,Web view的功能有明顯提高。然而,你的用戶群可能不會運行Android或iOS的最新和最優秀的版本。 Android平臺在Web view方面已普遍落后于iOS。Google似乎在重新努力來改善這種情況,但那些停留在舊版本的Android(尤其是Ice Cream Sandwich 4.x版本前)的用戶可能會發現Web view的性能尤其是復雜的表格,其效果和在iOS上呈現的并不一樣。開發人員需要在Android 2.2,2.3和4.x上測試HTML5代碼以確保內容呈現的一致。
•    性能問題
Web view的性能通常是比不上原生代碼。然而,在許多情況下,你可能會發現性能是完全可以接受的,特別是在當前的硬件飛速發展的情況下。請記住,原生代碼和代碼Web view部分調用的銜接性能會有一定的影響。但一般來說,不會要求在毫秒級完成調用,對于大多數應用,這是不是一個問題。
•    滾動條問題

用戶可能無法區分Web view的滾動條滾動方式和應用程序原生代碼滾動方式的不同。這其中的一些問題可以通過在新版本的WebKit中使用CSS3的-webkit-overflow-scrolling:touch屬性去解決。你可能也想看看解決方案,如FTScroller 和 iScroll。
•    復雜性

正如前面提到的,如果將內容從Web服務器中下載到移動設備,必須確保擁有必要的基礎設施來支持。因為現在應用程序既有原生代碼,也有Web服務器和潛在的后端服務參與,這會存在更多的故障點。你必須針對早期部署版本的應用程序做好兼容性測試,以確保當有應用更新的時候,現有版本的應用程序仍然運行。
•    遵守開發者協議

開發者的你必須熟悉每一類移動應用商店對web方面內容的限制。正如本文所提到的,特別是在iOS平臺上要額外注意,否則會不允許發布甚至下架。
•    安全性

如前所述對于所有來源于web的內容都應該持有懷疑的態度,尤其是如果將和你的本機原生代碼交互的。確保你只暴露你需要使用的原生代碼部分。如果不這樣做,可能會導致一些Web的惡意代碼能調用本機代碼。必須確保將Web的安全實踐考慮進來以確保Web代碼的安全調用。

鑒于一個混合型移動應用所帶來的靈活性,如果你發現Web view的性能在交互方面不夠優秀,則可以在應用中編寫原生代碼。當然,編寫更多的本機代碼,則在平臺遷移的時候需要更多的重新改寫,這是一種利弊權衡。總的來說,混合型移動應用的解決方案能讓你最大限度掌控應用的性能和靈活性。

小結
移動應用開發中使用HTML5目前是個有點爭議性的話題。然而,重要的是要作為開發者,必須了解每一種解決方案的優缺點,了解什么樣的策略是適合你的應用程序,這些都是由需求決定的。盡管移動HTML5的解決方案在最近幾個月已經有一些負面的宣傳,但本文還是講解了使用HTML5的好處。
無論采用什么方法開發移動應用,必須保持性能的高效和安全性,并且盡早測試,采用多種設備測試。在這篇文章中,我們已經看到,HTML5帶來了許多好處,特別是采用混合HTML 5和原生代碼開發,則給開發者更高的自由度選擇。

責任編輯:張葉青 來源: 51CTO
相關推薦

2011-08-29 17:27:47

HTML 5交互移動應用

2012-02-20 13:45:26

HTML5移動開發程序

2015-10-13 11:49:06

移動·開發技術周刊

2014-03-18 09:20:17

HTML5移動開發

2015-07-03 11:07:39

HTML5移動Web

2015-01-12 09:52:08

移動應用原生混合

2015-01-12 12:11:10

移動應用原生混合

2011-12-28 15:32:46

HTML5移動App

2011-08-10 13:44:22

HTML 5

2015-10-23 13:44:14

巴巴獵

2011-12-12 10:08:39

jQuery MobiHTML5

2011-12-08 11:01:45

HTML 5

2011-05-25 09:34:30

HTML5cssjavascript

2014-12-22 15:02:48

HTML5移動應用開發

2012-02-23 10:28:43

AppCanHTML5移動應用

2013-06-27 14:33:00

2014-10-21 17:34:11

HTML5移動設計

2015-03-26 14:04:57

2017-06-27 13:34:33

移動開發直播

2011-07-12 10:15:05

點贊
收藏

51CTO技術棧公眾號

欧美激情自拍| 欧美日韩尤物久久| 国产99久久久国产精品| 91av视频导航| jizz18女人高潮| 日韩一区二区三区在线看| 精品美女久久久久久免费| 亚洲精品乱码久久久久久蜜桃91| 国产黄色片av| 久久亚洲视频| 欧美成人午夜剧场免费观看| 美女久久久久久久久久| 久久视频免费| 在线免费不卡视频| 97久久国产亚洲精品超碰热| 欧洲天堂在线观看| 国产精品一区二区不卡| 人体精品一二三区| 欧美日韩一级在线观看| 精品国产一区二区三区久久久樱花 | 奇米成人av国产一区二区三区| 能免费看av的网站| 秋霞一区二区三区| 日本高清无吗v一区| 欧美日韩视频免费| 欧美日本高清| 久久九九久精品国产免费直播| 亚洲aⅴ日韩av电影在线观看| 欧美a视频在线观看| 欧美色123| 日韩视频精品在线| 影音先锋制服丝袜| 综合亚洲自拍| 亚洲成人中文字幕| 成人三级做爰av| 欧美成人xxxx| 欧洲精品视频在线观看| 欧美日韩国产精品激情在线播放| 污污的网站在线免费观看| 中文在线一区二区| 日韩久久在线| 黑人与亚洲人色ⅹvideos| 99久久精品国产一区| 97av自拍| 精品国自产在线观看| 激情五月婷婷综合| 国产精品一区二区三区久久| 国产精品一区无码| 亚洲欧美春色| 欧美在线亚洲一区| 久久久久久久黄色片| 亚洲精品1234| 97在线视频观看| 日本学生初尝黑人巨免费视频| 欧美日韩伊人| 久久久噜久噜久久综合| 久久久久亚洲av成人片| 亚洲性图久久| 久久久亚洲成人| 综合视频免费看| 亚洲美女高潮久久久| 97精品资源在线观看| 欧美丰满少妇xxxbbb| 国内自拍第二页| 精品成人18| 日韩视频永久免费| 在线免费看黄色片| 日韩在线黄色| 一区二区中文字幕| 看免费黄色录像| 欧美日韩日本国产亚洲在线| 97高清免费视频| 丁香社区五月天| 奇米精品一区二区三区四区| 成人福利网站在线观看| 国产成人精品a视频| 成人h动漫精品| 欧美日韩在线精品一区二区三区| 国产黄在线观看| 亚洲欧洲成人av每日更新| 精品一二三四五区| 少妇淫片在线影院| 在线观看日韩av先锋影音电影院| 天天综合网久久| 亚洲精品aⅴ| 亚洲欧美国产另类| 二区三区四区视频| 亚洲电影在线| 国产精品爽爽ⅴa在线观看| 国产按摩一区二区三区| 91天堂素人约啪| 一本久道久久综合| 99热99re6国产在线播放| 色94色欧美sute亚洲线路二 | 国产高潮国产高潮久久久91| 最新亚洲一区| 国产精品一区av| 高清一区二区三区四区| 久久久精品欧美丰满| 国产奶头好大揉着好爽视频| 华人av在线| 神马久久午夜| 一本到一区二区三区| 999这里有精品| 夜夜春成人影院| 久久天天躁狠狠躁夜夜躁| 精品欧美一区二区三区免费观看| 久久99久国产精品黄毛片色诱| 粉嫩精品一区二区三区在线观看| 国产毛片在线| 亚洲成va人在线观看| 一本色道久久亚洲综合精品蜜桃 | 日本一区二区三区视频免费看| 成人黄视频在线观看| 色综合天天综合给合国产| 一级黄色免费毛片| 成人在线亚洲| 2019日本中文字幕| 97精品人妻一区二区三区| 91一区一区三区| av在线com| 999精品视频在线观看| 国产亚洲精品美女| 国产精品视频久久久久久久| 国产成人精品一区二| 亚洲精品电影在线一区| av日韩亚洲| 亚洲精品按摩视频| 豆国产97在线 | 亚洲| 狠狠色综合色综合网络| 天堂资源在线亚洲资源| 在线女人免费视频| 亚洲国产精品一区二区三区| 免费又黄又爽又色的视频| 国产一区在线观看麻豆| 亚洲精品在线免费看| 欧美va视频| 亚洲午夜久久久久久久| 国产精品久久久久久久久久久久久久久久久 | 国产麻豆精品久久一二三| 亚州欧美日韩中文视频| 999久久久久久| 亚洲欧洲日韩女同| 视频在线观看免费高清| 日韩电影在线视频| 国产精品视频公开费视频| 国产视频网站在线| 在线观看视频一区| 亚洲一级理论片| 老鸭窝一区二区久久精品| 日韩欧美亚洲精品| 韩日精品一区| 久久精品99无色码中文字幕| 91久久国语露脸精品国产高跟| 国产精品乱人伦中文| 成年人三级黄色片| 亚洲国产不卡| 99视频免费观看蜜桃视频| 不卡的av影片| 日韩成人在线视频观看| 欧美一区二区三区网站| 国产欧美日韩久久| 亚洲一区二区福利视频| 欧美影院一区| 精品无人乱码一区二区三区的优势| 春色校园综合激情亚洲| 亚洲欧美成人精品| 中文字幕第31页| 亚洲靠逼com| 在线观看成人动漫| 久久激情综合| 亚洲午夜精品一区二区三区| 国产精品视频一区二区三区| 久久久久久久电影一区| 欧美在线一卡| 欧美精品tushy高清| 亚洲国产精品久| 99久久99久久免费精品蜜臀| www.欧美日本| 亚洲影视一区| 久草热久草热线频97精品| av亚洲一区| 欧美激情中文字幕乱码免费| 欧美孕妇孕交| 欧美一级高清片| 欧美啪啪小视频| 成人欧美一区二区三区| 女王人厕视频2ⅴk| 免费亚洲网站| 好色先生视频污| 亚洲电影男人天堂| 亚洲aa在线观看| 这里有精品可以观看| 色偷偷av一区二区三区乱| 亚洲精品国产精| 欧美亚洲尤物久久| 久久精品国产av一区二区三区| 国产校园另类小说区| 国产伦理在线观看| 久久久久久久高潮| 成人午夜免费在线视频| 青青一区二区三区| 国产综合欧美在线看| 欧美一级网址| 欧美孕妇孕交黑巨大网站| 免费大片黄在线观看视频网站| 亚洲国产一区自拍| 国产精品毛片一区二区在线看舒淇| 欧美日韩国产影院| www.5588.com毛片| 欧美激情一区二区三区全黄| 国产精品久久久久久亚洲av| 老司机精品视频一区二区三区| 免费一级特黄毛片| 亚洲一区 二区 三区| 日韩欧美一区二区三区四区| 免费成人三级| 成人在线视频网址| 天堂久久一区| 国产精品久久久av久久久| 看黄在线观看| 久久久久久久久久久91| 欧美黑人激情| 一色桃子一区二区| 日韩二区三区| 日韩av在线网址| 亚洲国产一二三区| 欧美一区二区三区在线| 91片黄在线观看喷潮| 欧美性欧美巨大黑白大战| av网站中文字幕| 精品久久久久久中文字幕一区奶水| 久久久国产精华液| 亚洲精品乱码久久久久久黑人| 麻豆网址在线观看| 日韩一区欧美一区| 免费看一级大片| 亚洲精品中文字幕乱码三区 | 亚洲视频在线一区二区| 亚洲不卡的av| 国产精品毛片高清在线完整版| a天堂中文字幕| 国产亚洲精品bt天堂精选| 波多野结衣a v在线| 久久婷婷一区二区三区| 亚洲一区二区三区蜜桃| 久久亚洲二区三区| 亚洲AV无码国产成人久久| 久久久久久免费| 亚洲久久久久久久| 国产女同互慰高潮91漫画| 91精品人妻一区二区三区| 久久婷婷成人综合色| 中文字幕国产综合| 国产欧美日韩在线| 激情高潮到大叫狂喷水| 亚洲欧美日韩一区二区三区在线观看| 国产美女久久久久久| 亚洲免费伊人电影| 久久久精品视频在线| 午夜视频在线观看一区二区| 你懂的国产视频| 91国偷自产一区二区三区观看| 国产黄色免费视频| 欧美精品三级日韩久久| 国产国语亲子伦亲子| 亚洲精品福利在线观看| 国产一区二区三区福利| 日韩在线免费观看视频| 在线中文免费视频| 国内精久久久久久久久久人| 性欧美freesex顶级少妇| 国产精品久久久久免费a∨| 日本国产亚洲| 国产一区二区不卡视频在线观看| 一区二区小说| 伊人av成人| 亚洲第一毛片| 91女神在线观看| 国产激情一区二区三区| 国产高清自拍视频| 最新欧美精品一区二区三区| 国产第一页第二页| 欧美日韩一区二区在线视频| 性色av蜜臀av| 亚洲欧美综合另类中字| 最新国产在线拍揄自揄视频| 91av国产在线| 欧美经典影片视频网站| 鲁丝一区二区三区免费| 天天射天天综合网| 1024av视频| 紧缚奴在线一区二区三区| 私密视频在线观看| 中文字幕制服丝袜成人av| 日韩av男人天堂| 欧美日韩国产中文| 天堂av在线免费观看| 久久久精品中文字幕| 夜鲁夜鲁夜鲁视频在线播放| 91久久中文字幕| 久久最新网址| 国产欧美日韩小视频| 麻豆国产91在线播放| 黄色性生活一级片| 一区二区三区国产豹纹内裤在线| 亚洲 欧美 日韩 在线| 日韩欧美一二三区| 最新电影电视剧在线观看免费观看| 97国产精品视频人人做人人爱| 91成人app| 日韩久久精品一区二区三区| 一本色道久久精品| 亚洲av无码久久精品色欲| 欧美激情一区二区三区四区| 日本va欧美va国产激情| 日韩欧美国产高清| 高h视频在线观看| 国产精品入口免费视频一| 色天下一区二区三区| 欧美一区二区视频在线播放| 激情综合网激情| 99精品中文字幕| 欧美视频精品在线| 免费毛片在线| 51ⅴ精品国产91久久久久久| 高潮按摩久久久久久av免费| 男人的天堂视频在线| 国产专区综合网| 婷婷国产成人精品视频| 欧美视频精品在线| 成a人v在线播放| 国产精品久久久久久久app| 欧美**vk| 日本免费一级视频| 久久午夜羞羞影院免费观看| 日韩男人的天堂| 亚洲国产中文字幕在线观看| av免费不卡国产观看| 成人av片网址| 亚洲国产激情| 成人在线视频免费播放| 午夜激情久久久| 四虎免费在线观看| 国外色69视频在线观看| 国产精品17p| 黄色国产一级视频| 91女厕偷拍女厕偷拍高清| 久久不卡免费视频| 亚洲女人天堂色在线7777| 天然素人一区二区视频| 亚洲一区二区三区在线观看视频| 久久精品理论片| 成年人午夜剧场| 日韩精品一区二区三区视频播放| 精品精品导航| 麻豆av一区二区三区| 久久久蜜桃一区二区人| 国产精品无码无卡无需播放器| 欧美精选一区二区| 色爱综合区网| 久久久久久a亚洲欧洲aⅴ| 天堂一区二区在线| 国产一二三四视频| 日韩精品专区在线影院观看| 91福利区在线观看| 欧洲一区二区在线 | 国产在线久久久| 欧美精品麻豆| 亚洲男人在线天堂| 91成人在线精品| yourporn在线观看中文站| 国产日韩精品在线观看| 欧美三级小说| 高潮毛片无遮挡| 717成人午夜免费福利电影| 牛牛精品在线| 日本在线播放一区| 国产乱子伦视频一区二区三区| 久久综合综合久久| 亚洲欧美日韩一区二区三区在线| 欧美日韩免费电影| 蜜臀精品一区二区| 欧美国产日韩亚洲一区| 精品国产av一区二区| 欧洲亚洲在线视频| 91久久国产| 国产ts丝袜人妖系列视频| 欧美日韩国产首页| 国产精品yjizz视频网| 亚洲午夜激情| 91亚洲精华国产精华精华液| 一本色道久久综合无码人妻| 久久青草精品视频免费观看| 欧洲grand老妇人| 69xxx免费视频| 欧美日韩精品系列| 国产伦理精品| 丰满人妻一区二区三区53号| 久久久国产一区二区三区四区小说|