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简介》