Hybrid App移動應用開發初探

1、移動App類型及其優缺點

1.1 Native App

  Native App(原生App)是用原生語言(Object-C/Java/C#/....)開發,用戶須要下載安裝的手機應用。javascript

  優勢是 能夠徹底利用系統的 API 和平臺特性,在性能上也是最好的。css

  缺點是 因爲開發技術不一樣,若是你要覆蓋多個平臺,則要針對每一個平臺獨立開發,無跨平臺特性。html

1.2 Web App

  Web App主要是採用統一的標準的HTML、JavaScript與CSS 等 Web 技術開發。前端

  優勢是 用戶無需下載,經過不一樣平臺的瀏覽器訪問便可實現跨平臺,同時能夠經過瀏覽器支持充分使用 HTML5 特性。java

  缺點是 這些基於瀏覽器的應用沒法調用系統 API 來實現一些高級功能(例如拍照、GPS、存儲等),也不適合高性能要求的場合。node

1.3 Hybrid App

  Hybrid App(混合式App)中和了Native App和Web App各自的優點。 咱們能夠用 HTML + CSS + JS 開發,兼容多個平臺。用戶也要下載安裝,並能調用手機的攝像頭、通信錄等功能, Hybrid App的靜態資源也在手機本地。android

  優勢是 相同的代碼只需針對不一樣平臺進行編譯就能實如今多平臺的分發,大大提升了多平臺開發的效率;而相較於 Web App,開發者能夠經過包裝好的接口,調用大 部分經常使用的系統 API。ios

2、Hybird App開發平臺介紹

2.1 PhoneGap

  PhoneGap是一個用基於HTML,CSS和JavaScript的,建立移動跨平臺移動應用程序的快速開發平臺。它使開發者可以利用iPhone,Android,Palm,Symbian,WP7,WP8,Bada和Blackberry智能手機的核心功能——包括地理定位,加速器,聯繫人,聲音和振動等,此外PhoneGap擁有豐富的插件,能夠調用。git

  業界不少主流的移動開發框架均源於PhoneGap。較著名的有Worklight、appMobi、WeX5等;其中WeX5爲國內打造,徹底Apache開源,在融合Phonegap的基礎上,作了深度優化,具有接近Native app的性能,同時開發便捷性也較好。

2.2 Cordova

  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。

2.3 Hybrid App程序結構

  爲了瞭解清楚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相機功能的層次順序以下圖所示:

3、Cordova平臺環境配置

3.1 配置JDK環境

  下載地址: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

  

3.2 配置Android-SDK環境

  下載地址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.rarD:\Develop\Android\sdk,配置環境變量:

ADT_HOME = D:\Develop\Android\sdk

Path += %ADT_HOME%\platform-tools;%ADT_HOME%\tools;

  驗證:adb -version

  

3.3 配置Apache-Ant環境

  下載地址:http://ant.apache.org/bindownload.cgi

  解壓apache-ant-1.9.6.rar配置環境變量:

ANT_HOME = D:\Develop\ApacheAnt

Path += %ANT_HOME%\bin;

  驗證:ant -versioin

  

3.4 配置GIT環境

  下載地址: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

  

3.5 配置Node環境

  下載地址:http://nodejs.org/download/

  安裝node-v0.10.29-x64.msi,配置環境變量:

NODE_HOME = C:\Program Files\Nodejs\

Path += %NODE_HOME%;

  驗證:node -v,npm -v

  

3.6 配置Cordova環境

  在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  

4、第一個移動App:簡單登陸Demo

4.1 開發流程概述

  首先,使用Visual Studio或Sublime Text等IDE開發Web網頁,而後使用Cordova平臺進行打包生成Android項目文件,最後調整配置文件和發佈成apk。

4.2 使用Visual Studio開發Web網站

  這裏只開發一個簡單的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>
View Code

  這裏須要注意的有如下幾點:

  (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;
            }
        }
    }
View Code

  這裏沒有進行數據庫的操做,而是簡單得模擬了一個含有兩條用戶信息的List集合。

4.3 使用Cordova打包apk文件

  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:

  

4.4 調整配置文件和發佈應用

  在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>
View Code

  3.編譯發佈app成apk文件

  經過命令:cordova build android 來生成最後的apk文件

  

  

  生成的apk文件位於:YourDirectory\yuema\platforms\android\build\outputs\apk 中

  

4.5 預覽咱們的app

  將生成的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簡介

 

相關文章
相關標籤/搜索