Native App(原生App)是用原生語言(Object-C/Java/C#/....)開發,用戶須要下載安裝的手機應用。javascript
優勢是 能夠徹底利用系統的 API 和平臺特性,在性能上也是最好的。css
缺點是 因爲開發技術不一樣,若是你要覆蓋多個平臺,則要針對每一個平臺獨立開發,無跨平臺特性。html
Web App主要是採用統一的標準的HTML、JavaScript與CSS 等 Web 技術開發。前端
優勢是 用戶無需下載,經過不一樣平臺的瀏覽器訪問便可實現跨平臺,同時能夠經過瀏覽器支持充分使用 HTML5 特性。java
缺點是 這些基於瀏覽器的應用沒法調用系統 API 來實現一些高級功能(例如拍照、GPS、存儲等),也不適合高性能要求的場合。node
Hybrid App(混合式App)中和了Native App和Web App各自的優點。 咱們能夠用 HTML + CSS + JS 開發,兼容多個平臺。用戶也要下載安裝,並能調用手機的攝像頭、通信錄等功能, Hybrid App的靜態資源也在手機本地。android
優勢是 相同的代碼只需針對不一樣平臺進行編譯就能實如今多平臺的分發,大大提升了多平臺開發的效率;而相較於 Web App,開發者能夠經過包裝好的接口,調用大 部分經常使用的系統 API。ios
PhoneGap是一個用基於HTML,CSS和JavaScript的,建立移動跨平臺移動應用程序的快速開發平臺。它使開發者可以利用iPhone,Android,Palm,Symbian,WP7,WP8,Bada和Blackberry智能手機的核心功能——包括地理定位,加速器,聯繫人,聲音和振動等,此外PhoneGap擁有豐富的插件,能夠調用。git
Cordova是貢獻給Apache後的開源項目,是從PhoneGap中抽出的核心代碼,是驅動PhoneGap的核心引擎。你能夠把它們的關係想象成相似於Webkit和Google Chrome的關係。github
Cordova提供了一組設備相關的API,經過這組API,移動應用可以以JavaScript訪問原生的設備功能,如攝像頭、麥克風等。
Cordova還提供了一組統一的JavaScript類庫,以及爲這些類庫所用的設備相關的原生後臺代碼。
Cordova支持以下移動操做系統:iOS, Android,ubuntu phone os, Blackberry, Windows Phone, Palm WebOS, Bada 和 Symbian。
爲了瞭解清楚Hybrid App的程序結構,咱們先來複習一下普通的ASP.NET Web網站應用的結構:
最底層固然是CLR提供的運行時環境,這是全部.NET應用程序都必須賴以生存的條件。在CLR之上是.NET Framework提供的一些基類庫BCL,包括了IO、String、Thread等經常使用的類型。在BCL之上是一些經常使用的Framework,例如B/S模式的ASP.NET WebForm和ASP.NET MVC,C/S模式的Windows Form或WPF等。最上層纔是咱們得應用程序,它是基於下面的基礎環境來構建的,一層接一層,每一層都對下層有依賴。
如今咱們再來看下面一張圖,它展現了一個Hybird App的結構:
與Web網站結構圖相對應,Hybrid App結構圖的最底層是Native Code(本地代碼),這裏列舉了三種主要操做系統iOS、Android以及Windows Phone的對應開發語言Object-C、Java和C#,在Native App的開發中咱們直接使用這幾種語言開發對應操做系統的App。在Native Code之上的是Cordova/PhoneGap這樣的平臺,這些平臺提供了JavaScript執行平臺和Native API,上層經過傳遞JS代碼,由JS執行平臺進行解釋,再調用對應的Native API,由Native API去調用對應操做系統的Native Code。換句話說,Cordova/PhoneGap這一層所作的就是對Native Code層面的包裝。在平臺層之上是一些Plugins(插件),它是一堆手機的硬件組件接口,能夠方便地使用JS代碼調用相機、文件、網絡等硬件資源。最上層是一些Web前端的展現層框架,藉助這些框架能夠方便地開發出適合Hybird App的Web頁面。
一個典型的Hybrid App的調用手機硬件的Camera相機功能的層次順序以下圖所示:
下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
安裝jdk-8u71-windows-x64.exe,配置環境變量:
JAVA_HOME = C:\Program Files\Java\jdk1.8.0_71
Path += %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
CLASSPATH += %JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
驗證:java -version
下載地址1:http://developer.android.com/design/downloads/index.html
下載地址2(經過Android Studio安裝Android SDK):https://dl.google.com/dl/android/studio/install/1.2.1.1/android-studio-bundle-141.1903250-windows.exe
解壓android-sdk.rar到D:\Develop\Android\sdk,配置環境變量:
ADT_HOME = D:\Develop\Android\sdk
Path += %ADT_HOME%\platform-tools;%ADT_HOME%\tools;
驗證:adb -version
下載地址:http://ant.apache.org/bindownload.cgi
解壓apache-ant-1.9.6.rar,配置環境變量:
ANT_HOME = D:\Develop\ApacheAnt
Path += %ANT_HOME%\bin;
驗證:ant -versioin
下載地址:http://msysgit.github.io/
安裝Git_V2.5.1_64_bit_setup.1441791170.exe,配置環境變量:
GIT_HOME = C:\Program Files\Git
Path += %GIT_HOME%\bin;
驗證:git --version
下載地址:http://nodejs.org/download/
安裝node-v0.10.29-x64.msi,配置環境變量:
NODE_HOME = C:\Program Files\Nodejs\
Path += %NODE_HOME%;
驗證:node -v,npm -v
在cmd中運行npm install -g cordova(在線安裝)
或者將cordova.rar解壓到C:\Users\YourName\AppData\Roaming\npm\node_modules
PS:cordova最新版本匹配android 6.0,所以你的Android SDK也要下載6.0的包,若是你只有5.x的,那麼能夠指定cordova的版本進行安裝,例如安裝cordova 5.1.1 :npm install -g cordova@5.1.1
首先,使用Visual Studio或Sublime Text等IDE開發Web網頁,而後使用Cordova平臺進行打包生成Android項目文件,最後調整配置文件和發佈成apk。
這裏只開發一個簡單的login頁面,所以只有一個HTML文件:login.html,藉助於bootstrap和zeptojs。login.html的代碼以下:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>MyHybirdApp</title> <link href="assets/lib/bootstrap/css/bootstrap.min.css" rel="stylesheet" /> <link href="assets/css/style.css" rel="stylesheet" /> </head> <body> <!-- 表單區域 --> <form id="form_login" class="form-main" method="post" autocomplete="off"> <h2>Sign in</h2> <hr /> <div class="avator"> <img id="myavator" src="assets/img/avatar.png" /> </div> <div class="message-box"></div> <label for="username" class="sr-only">Username</label> <input id="username" type="text" class="form-control input-lg input-group-top" placeholder="Input your Username" required autofocus> <label for="password" class="sr-only">Password</label> <input id="password" type="password" class="form-control input-lg input-group-bottom" placeholder="Input your Password" required> <div class="checkbox"> <input id="remember" type="checkbox" value="remember-me" checked> <label for="remember">Remember me</label> <a class="link" href="register.html">Sign up</a> </div> <input type="hidden" name="redirect" value="/" /> <button id="btn_login" class="btn btn-lg btn-info btn-block">Sign in</button> </form> <!-- 腳本區域 --> <script type="text/javascript" src="assets/lib/zepto/zepto.min.js"></script> <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript"> $(function () { // 調用手機硬件拍照 $('#myavator').on('click', function () { navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.DATA_URL }); function onSuccess(imageData) { var image = document.getElementById('myavator'); image.src = "data:image/jpeg;base64," + imageData; } function onFail(message) { alert('Failed because: ' + message); } }); // 訪問服務端服務 $('#btn_login').on('click', function () { var userName = $('#username').val(); var password = $('#password').val(); if (userName == "") { alert('Please input your user name!'); } else if (password == "") { alert('Please input your password!'); } else { // 在PC瀏覽器端的話下面的ajax請求就涉及到跨域,而在Cordova中咱們不須要考慮麼麼噠 $.get('http://www.edisonchou.cn/AccountHandler.ashx?action=Login&username=' + userName + '&password=' + password + '', { }, function (data) { alert(data.Message); }); } return false; }); }); </script> </body> </html>
這裏須要注意的有如下幾點:
(1)訪問服務端的服務
// 訪問服務端服務 $('#btn_login').on('click', function () { var userName = $('#username').val(); var password = $('#password').val(); if (userName == "") { alert('Please input your user name!'); } else if (password == "") { alert('Please input your password!'); } else { // 在PC瀏覽器端的話下面的ajax請求就涉及到跨域,而在Cordova中咱們不須要考慮麼麼噠 $.get('http://www.edisonchou.cn/AccountHandler.ashx?action=Login&username=' + userName + '&password=' + password + '', { }, function (data) { alert(data.Message); }); } return false; });
咱們知道在傳統PC 瀏覽器端中,ajax請求受限於XMLHttpRequest沒法進行跨域請求,咱們可能須要藉助JSONP一類的幫手幫咱們解決,而在Cordova生成的Hybird App中不須要考慮這個問題。在上面的代碼中,get請求訪問的是一個位於遠端服務器中的一個服務(能夠是ashx通常處理程序,也能夠是一個MVC應用的action)。
(2)訪問Android手機的硬件
// 調用手機硬件拍照 $('#myavator').on('click', function () { navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.DATA_URL }); function onSuccess(imageData) { var image = document.getElementById('myavator'); image.src = "data:image/jpeg;base64," + imageData; } function onFail(message) { alert('Failed because: ' + message); } });
參考Cordova的API文檔,咱們能夠經過如上所示的JS代碼訪問Camera相機,並調用相機進行拍照。兩個事件onSuccess和OnFail則是拍照成功或失敗後的處理邏輯。這裏成功後,咱們將新拍的照片放到頭像Image位置。
另外,咱們還須要一個服務端,提供登陸驗證的接口供App客戶端調用,這裏咱們簡單地作一個ashx通常處理程序來進行處理,並將其發佈到阿里雲的虛擬機中以便手機能夠隨時訪問,其處理邏輯代碼以下:
public class AccountHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { if (string.IsNullOrEmpty(context.Request["action"])) { return; } string action = context.Request["action"]; JsonObject jsonObject = new JsonObject(); switch (action) { case "Login": string userName = context.Request["username"]; string password = context.Request["password"]; jsonObject.UserId = userName; bool result = CheckAccount(userName, password); if (result) { jsonObject.Message = "Success"; } else { jsonObject.Message = "Failed"; } JavaScriptSerializer serializer = new JavaScriptSerializer(); string jsonResult = serializer.Serialize(jsonObject); context.Response.ContentType = "application/json"; context.Response.Write(jsonResult); break; } } private bool CheckAccount(string userName, string password) { bool result = false; List<Account> accountList = GetAccountList(); foreach (var account in accountList) { if (account.UserName.Equals(userName) && account.Password.Equals(password)) { result = true; } } return result; } private List<Account> GetAccountList() { return new List<Account>() { new Account() { UserName="edisonchou",Password="123456" }, new Account() { UserName="zhouxulong",Password="654321"} }; } public bool IsReusable { get { return false; } } }
這裏沒有進行數據庫的操做,而是簡單得模擬了一個含有兩條用戶信息的List集合。
1.新建一個項目文件夾
有了Web網站,咱們能夠進行App的準備工做了,首先新建一個Cordova項目文件夾:
這裏咱們給app取名爲約嗎,PS:今天情人節,你約了嗎?
而後將www文件裏面的內容所有刪除,將咱們開發的web網頁以及依賴的資源(圖片、css、js等)拷貝到此目錄下:
2.增長android platform支持
有了一個Cordova的項目文件夾,咱們須要增長一個android的platform,由於咱們要作的是一個基於android的app。進入yuema文件夾,而後輸入如下命令:
3.增長android plugin支持
因爲咱們的app使用了硬件,因此須要增長針對相對應硬件的plugin支持,前面提到咱們須要調用對應的plugin,由plugin去調用JS解釋器生成對應Native API。這裏咱們增長camera的plugin:
在cordova生成的項目文件夾中,最頂層有一個config.xml,這個就是咱們須要編輯的配置文件。
1.設置app的起始頁面
<!-- 應用程序入口 --> <content src="login.html" />
2.設置app的Icon以及SplashScreen
<!-- 針對不一樣平臺單獨的設置選項 --> <platform name="android"> <allow-intent href="market:*" /> <!-- app icon image --> <icon src="www/assets/img/avatar.png" density="ldpi" /> <icon src="www/assets/img/avatar.png" density="mdpi" /> <icon src="www/assets/img/avatar.png" density="hdpi" /> <icon src="www/assets/img/avatar.png" density="xdpi" /> <!-- splash screen image --> <splash src="www/assets/img/splashscreen.png" density="land-hdpi" /> <splash src="www/assets/img/splashscreen.png" density="land-ldpi" /> <splash src="www/assets/img/splashscreen.png" density="land-mdpi" /> <splash src="www/assets/img/splashscreen.png" density="land-xdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-hdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-ldpi" /> <splash src="www/assets/img/splashscreen.png" density="port-mdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-xdpi" /> </platform>
完整的config.xml以下:
<?xml version='1.0' encoding='utf-8'?> <widget id="cn.edisonchou.app" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>約嗎</name> <description> Edison Chou的第一個Cordova應用. </description> <author email="edisonchou@hotmail.com" href="http://www.edisonchou.cn"> Edison Chou </author> <!-- 應用程序入口 --> <content src="login.html" /> <!-- 插件依賴項 --> <plugin name="cordova-plugin-whitelist" version="1" /> <!-- 網絡類型配置 *表明全部地址都可訪問--> <access origin="*" /> <allow-intent href="http://*/*" /> <allow-intent href="https://*/*" /> <allow-intent href="tel:*" /> <allow-intent href="sms:*" /> <allow-intent href="mailto:*" /> <allow-intent href="geo:*" /> <!-- 針對不一樣平臺單獨的設置選項 --> <platform name="android"> <allow-intent href="market:*" /> <!-- app icon image --> <icon src="www/assets/img/avatar.png" density="ldpi" /> <icon src="www/assets/img/avatar.png" density="mdpi" /> <icon src="www/assets/img/avatar.png" density="hdpi" /> <icon src="www/assets/img/avatar.png" density="xdpi" /> <!-- splash screen image --> <splash src="www/assets/img/splashscreen.png" density="land-hdpi" /> <splash src="www/assets/img/splashscreen.png" density="land-ldpi" /> <splash src="www/assets/img/splashscreen.png" density="land-mdpi" /> <splash src="www/assets/img/splashscreen.png" density="land-xdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-hdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-ldpi" /> <splash src="www/assets/img/splashscreen.png" density="port-mdpi" /> <splash src="www/assets/img/splashscreen.png" density="port-xdpi" /> </platform> <platform name="ios"> <allow-intent href="itms:*" /> <allow-intent href="itms-apps:*" /> </platform> </widget>
3.編譯發佈app成apk文件
經過命令:cordova build android 來生成最後的apk文件
生成的apk文件位於:YourDirectory\yuema\platforms\android\build\outputs\apk 中
將生成的apk放到咱們得android手機中並進行安裝,而後點擊進入,下面是演示圖片(演示手機:Smartisan T1)。
(1)安裝app
(2)點擊進入登陸頁面
如下兩個gif圖片受限於gif製做軟件,效果較差,可是功能已經演示了出來:
(3)調用服務端進行驗證
(4)調用相機進行拍照
1.整個項目的源代碼:http://pan.baidu.com/s/1gdVIurx
2.生成後的apk文件:http://pan.baidu.com/s/1bfvVWE
1.汪磊,《Hybird App 基礎入門公開課》
2.Apache,《Apache Cordova API Document》
3.李秉駿,《Hybrid App 開發實戰》
4.FreeZinG,《使用HTML和JS開發移動App-部署Cordova配套開發環境》
5.周金根,《新手的第一個PhoneGap Android應用》
6.zythy,《跨平臺框架Cordova命令行CLI簡介》