BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

使用ASP.NET MVC开发混合移动应用

| 作者 Daniel Jebaraj 关注 0 他的粉丝 ,译者 邵思华 关注 3 他的粉丝 发布于 2013年6月8日. 估计阅读时间: 27 分钟 | QCon上海2018 关注大数据平台技术选型、搭建、系统迁移和优化的经验。

移动设备无处不在

十年前,微软专业开发者大会(PDC)上,主办方播放的一段视频,勾画了未来的移动领域蓝图。视频演示了一个颇具未来感的Windows手机设备,如何完成诸如定位最近诊所的任务。在那个Palm VII算是最接近智能手机的年代,这段视频所演示的未来确实令人向往。

时间飞驰到2013年:我们毫无偏差地来到了这个未来时代,智能手机和其它移动设备无处不在。各种价位任君选择,而且价格也越来越亲民。事实上,对于大多数发展中国家的人来说,他们唯一的电脑就是所拥有的智能手机。

移动应用开发:Gartner所预测的增长

Gartner预测i,到2016年,至少50%以上的企业email用户将会主要依赖于浏览器、平板电脑、或移动客户端,而不是桌面客户端。据移动设备的使用增长状况可预计,在今后的几年中,针对这些设备的软件应用开发也会飞速增长。Garnter继续预测,到2015年,针对智能手机及平板电脑的移动应用开发项目与原生PC项目之比将达到4:1。Garnter还预测,在今后的4年中,智能飞机与平板电脑在新设备中所占比重将会超过90%。

Apple的应用商店现已有超过50万的应用,Android也接近这个数字,而新贵Windows Phone近期也超过了5万,并且还在快速发展中。

移动应用行业:市场分化带来的挑战

在这个令人振奋的背景下,我们能够确信,不久的将来移动平台上将出现大量行业应用。与机遇相随的是,移动应用开发也将面临着它自身的一系列挑战。

主要的挑战之一是市场分化的问题。2012第三季度的调查显示,移动操作系统市场的分化问题非常严重。在这个季度所售出的设备中,Android的各种型号占了大约72%,iOS占了大约14%,黑莓(RIM/Blackberry)占了5%,而Windows Phone平台占了2%。(基于Gartner统计)

要开发一个能运行于所有设备上的商业应用,需要应用到以下这些的不同技术:

Platform

Primary development platform

Primary development language

Primary IDE

Development platforms

Android

Java based

Java

Eclipse

Windows, Mac OSX, Linux

iOS

Cocoa Touch framework

Objective C

Xcode

Mac OSX

RIM

Java ME

Java

Eclipse

Windows, Mac OSX

Windows Phone 8

.NET/native

C#/C++

Visual Studio

Windows

这些平台、语言及开发工具之间有着本质上的区别,一个能够运行在所有平台上的解决方案,其开发所需的投入也是很高的。

值得一提的是,即使在同一平台之下,分化的程度也很严重,当前处于领先局面的Android平台尤为明显。由于Android是开放的,并且厂家可以任意改动,导致如今市面上基于Android的设备已有几百种。其中的大部分只能使用特定版本的Android API。而即使应用在支持的API版本之内,仍然有一部分设备在使用这些应用时会遇到问题。因而结论是,处理移动市场上的市场分化问题没有捷径可言。这使得实现一个运行于多个平台的原生解决方案异常困难。

移动web应用:市场分化的解决方案?

Web应用是原生应用的一种替代方案。所有主流的移动平台都提供了可用的浏览器。而且,除Windows Phone浏览器之外,其它多数平台浏览器都是基于开源的WebKit浏览器平台,正是它实现了桌面版本的Apple Safari与Google Chrome。这些浏览器平台对JavaScript都有很好的支持,jQuery也在多数主流移动设备上得到完善的支持。另外,各浏览器也在提高对HTML 5与相关的web标准的遵循,这使得浏览器成为一个更吸引人的开发平台。使用当前的技术创建功能丰富的网站,并同样在移动设备上良好运行是完全可能的。

移动web应用:其它观点

移动web网站无法与原生应用的用户体验媲美。特定硬件平台上的用户已经习惯于原生应用所提供的良好体验,这些应用已经原生地安装于设备中,只需通过启动界面就能立即使用。而且原生应用遵守该设备上的用户界面约定,比如在Android设备上,按侧边栏分类菜单键通常会显示一个上下文菜单,这是用户所期望的表现。Web应用可以在多数设备的启动界面上安装一个快捷方式,但它们在所安装的设备上无法遵守特定的用户体验期望。Web应用的另一个劣势是,除了HTML与相关的web标准所提供的输出显示之外,它们对硬件没有任何原生访问的能力。比方如对于设备上的联系人、图片或摄像头不能直接的访问。对于许多应用来说,直接访问设备硬件上的关键元素是很重要的。

混合应用:web与原生应用的最佳结合

混合应用是指在完全的原生应用中嵌入一个特定平台的web浏览器控件。所有主流的移动平台,包括Android、iOS、Windows Phone 8与Blackberry/RIM都支持将这些平台上的web浏览器控件嵌入应用中。由于包装器是完全原生的,用户甚至不太会查觉到他们正在与一个web应用在交互,原生的应用就完全可能提供一个无缝的浏览体验。

浏览器中显示的web页面也可以通过某种JavaScript桥接方式与原生的硬件进行交互,在每种主流的平台上都有该方式的某种实现。通过这种对原生平台的回调,使得访问联系人,抓获与选择图片,以及播放媒体文件成为可能。实际上,任何通过原生代码可以完成的操作都可以通过这种桥接方式实现。当然,对每一种目标平台,桥接代码都必须重新编写,不过这部分代码通常只占用你的整个应用代码的一小部分。

另外,现今已经出现了几种JavaScript桥接框架了,最流行的一种是开源的PhoneGap平台,它提供了这种桥接的一个重要部分。不过我们在这篇文章不打算使用任何框架,而是通过一个简单的Android包装器来演示这个概念。

ASP.NET MVC:一个优雅的后端框架

混合应用可以使用任何web后端技术,不过我们相信由ASP.NET MVC实现混合应用是个理想的选择ii。下文阐述了ASP.NET MVC作为这些良好选择的原因。

清晰的职责分离

MVC环境提供了清晰的职责分离,这使得对于HTML输入的精确控制成为可能,也使得生成适合于移动平台的HTML变得非常简单。而那些内建的、独立的驱动能对所生成的标记控制。

与桌面或平板web客户端共享大部分代码

如果你有一个现成的针对桌面浏览器的ASP.NET MVC应用,那么许多代码都可以在你的移动应用中重用。Controller和Model的代码基本可以完全重用,只需要修改视觉的部分。在当前版本的ASP.NET MVC中为移动客户端指定一个定制的视觉就不是什么难事了,而下一个版本的ASP.NET MVC会使得这一切更简单。关于即将到来的ASP.NET MVC版本中,移动开发新特性的其它细节,请参考ASP.NET MVC文档。

通过以下web开发模型将市场分化问题降至最低

ASP.NET MVC对于无状态的web应用并没有创建很多抽象层,而是提供了一个非常简单的模型,它能够与底层的平台相集成,使得在客户端发起AJAX调用或使用jQuery变得非常简单。不必担心处理像ASP.NET Web Forms中的ViewState那样复杂的抽象了。

除此之外,值得一提的是,现有的.NET应用中的业务层和数据库层可以重用在ASP.NET MVC应用中。ASP.NET MVC完全不受业务层和数据库层的影响,它能够高效地应用在任何现有系统中。

混合应用示例

我们现在来看一个非常简单的示例,以演示使用ASP.NET MVC平台开发一个端到端的混合应用开发过程。该示例将显示某个虚拟的大学 - Contoso大学的学生信息,它包含一些常用信息的链接,以及能够根据姓名查找学生信息的目录。为了使这个示例更清晰,它没有包含安全或错误处理的部分。代码本身并不复杂,因为示例本身并不是为了展现ASP.NET MVC平台的强大功能,而是想表现它作为一个后端平台,非常适于开发混合的原生移动应用。

示例的完整代码可以在bit.ly/mvc-native-mobile-apps找到。

运行示例代码的条件:

  • ASP.NET MVC 3及Visual Studio 2010(包括Expression在内的任何版本)
  • Android SDK的功能安装,及Eclipse的Android开发工具插件。
  • 详细的指示及需求可以在这里找到。
  • jQuery及jQuery Mobile,这里不需要创建本地的拷贝,因为示例代码会引用jQuery CDN。

ASP.NET MVC后端部分

在示例代码中,_Layout.cshtml包含了对jQuery与jQuery Mobile库的脚本引用。它们对创建ASP.NET MVC移动应用并不是必需的,但它们解决了很大一部分工作。我们在示例中使用jQuery Mobile以简化对移动设备上内容的格式化操作。

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile
;-1.0.min.css" />
<link rel="stylesheet" type="text/css" href="@Url.Content(" site.css?)? Content ~ />

<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js">
</script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile
-1.0.min.js"></script>

多数的移动web客户端都假设web页面会缩放至900像素左右的大小,并且能够自适应大小以便在设备上显示整个页面。为了将移动网站的显示优化在某个更小的设备上,我们可以提示设备不要自动伸缩,而是使用该设备的宽度。这可以通过使用viewpoint这个meta标签来实现,如下所示:

<meta name="viewport" content="width=device-width, initial-scale=1.0 ">

在Home controller中默认的Index行为方法将映射到以下的view标签。

<nav>
     <ul id="menu" data-role="listview">
         <li>@Html.ActionLink("About Us", "AboutUs", "Home")</li>
         <li>@Html.ActionLink("Contact Us", "ContactUs", "Home")</li>
         <li>@Html.ActionLink("Student Directory", "StudentDirectory", "Home")</li>
     </ul>
</nav>

我们有一个简单的无序列表,包含三个行为链接。通过在jQuery Mobile运行时中使用“data-role=listview”这个属性设置,我们指定该列表将自动格式化为一个列表视图。这样就能够在移动设备上显示以下的初始UI。

图1,初始界面

jQuery Mobile运行时会负责将它格式化为一个列表视图。如之前所说,jQuery Mobile并非必需,你可以选择最适合你的格式化及脚本的应用方式。

该示例也包含了选择“关于我们”及“联系我们”等选项时所显示的视图,这几个界面非常直白,无需进一步的说明。

打开学生目录链接将显示一个按首字母分组的学生名称页面,并显示每个字母下的学生数目。

图2,学生目录初始界面

点击任一选项将显示学生列表,如下所示。

图3,学生目录

学生目录的view也非常简单,仅仅是将列表中的数据迭代显示。显示学生详细信息的view如下所示。

@{
    ViewBag.Title = "Student Directory";
     Layout = "~/Views/Shared/_Layout.cshtml";
     var random = new Random();
}

<ul data-role="listview">
@foreach (string student in ViewBag.Students)
{ 
     <li>

         @{var number = random.Next(1000, 9999); }

         <img src="@Url.Content("~/Content/images/UserImages/80-80/" + student + 
".jpg")" alt="@student"/>
         <h3>@student</h3>
         <h4>919-555-@number</h4>
     </li>
}
</ul>

在使用Android包装器进行查看之前,可以先在桌面游览器中运行ASP.NET MVC后端并进行完整的测试,这也不失为一个好主意。稍后我们再进行Android包装器的开发。

如果你的测试设备能够访问待测试的网站,那么你也可以直接在它的移动游览器上进行测试。如果你的开发PC与设备测试处于同一个网络中,也可以通过修改ASP.NET开发浏览器或IIS Express的配置,以允许你的测试设备访问该web应用。而在默认情况下这种访问是被禁止的。

一种较简单的替代方案是使用代理,它能够将对外部端口的访问重定向到内部的服务器,我们就经常使用这种方式。我们所使用的代理可以从GitHubiii下载。

Android包装器

Android包装器将在一个原生的Android应用中托管这个web应用,其代码所下所示。

package com.syncfusion.contoso;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class ContosoActivity extends Activity {

    WebView mWebView;

    private class ContosoWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }
     

    /** Called when the activity is first created. */          
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mWebView = (WebView) this.findViewById(R.id.webview);

        // Disable scrollbars 
        mWebView.setVerticalScrollBarEnabled(false);
        mWebView.setHorizontalScrollBarEnabled(false);

        // Scrollbar Overlay Content
        mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.getSettings().setAppCacheEnabled(false);
        mWebView.loadUrl("http://your-web-link");
        mWebView.setWebViewClient(new ContosoWebViewClient() );
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

这段代码也很容易理解。

  • WebView在Android上等同于WebBrowser控件,它是默认基于WebKit的Android浏览器的包装类。
  • 我们获取了对某个Android WebView控件的实例(它定义在某个XML layout文件中,并由Android运行时进行创建)的访问。
  • 我们为这个WebView实例开启了JavaScript功能,因为在WebView控件中,JavaScript默认是关闭的。接下来我们对拖动框的显示做了一些调整,其实就是把它关闭,以模拟原生应用的外观。
  • 再接下来,我们调用了WebView实例的loadUrl API,以加载实际的web应用。你应该修改web链接,以指向你的web应用。
  • 最后一部分代码处理了对硬件的回退按钮的调用,以使得嵌入的WebView回退到之前的页面。

如你所见,这段代码对web应用并没有直接的依赖关系,也不需要在不同的应用之间进行大量的修改。当你需要访问设备上的特定硬件功能时,你只需要添加一些额外的代码。在这里我们对这个主题不会做深入研究,如果你有兴趣进行更深入的钻研,请查看WebView中的addJavascriptInterface方法的相关内容。

出于简便,我们只介绍了Android包装器的内容,类似的包装器与扩展机制也存在于所有其它主流移动平台上。

图4,在原生应用shell中使用Android 4.0模拟器显示的“联系我们”页面

结论

对于任何移动行业应用来说,混合应用都是一种值得考虑的有前景的解决方案。对于需要对原生硬件进行大量访问(例如在游戏中)的场景来说它并不适合,但对于其它多数场景它都有良好的表现。由web后端实现的解决方案很有可能不会过时。这些年来HTML的标准在缓慢地演化中,它也不太可能像专利解决方案那样倾向于做出重大的改变。这就为应用的创建提供了一个稳定的基础,也确保这些应用在可预见的将来能够继续工作。Mobile平台的供应商为HTML 5与相关标准的实现投入了巨大的精力,它们将使web应用更加强大,并能够完成很大一部分在原生应用中可以实现的工作。

你可以充分利用你现有的.NET web开发技术,并在更多的设备上创建强大的解决方案。在Syncfusion,我们为混合应用所提供的无限潜力感到激动不已。

关于作者

Daniel Jebaraj作为副总裁,主导Syncfusion产品的开发。总体掌控产品开发并制订发布计划。通过积极地与客户沟通,Daniel确保每个新产品都能基于客户反馈进行改进。早前,作为开发团队的副总裁,她专注于驱动Syncfusion的产品开发。在2001年加入Syncfusion之前,Daniel管理Rogue Wave Software的开发团队。获得克莱蒙森大学(Clemson University)的工学硕士学位。

 

i Gartner Reveals Top Predictions for IT Organizations and Users for 2012 and Beyond

ii Ignore ASP.NET MVC at Your Own Peril: Lessons Learned from the Trenches.

iii 更多细节请参考James的代码

查看英文原文:Hybrid Mobile Apps with ASP.NET MVC


感谢李琼对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

作者是“她”吗? by Chin Jeremy

作者是“她”吗?

代码在哪里? by hu shibo

示例的完整代码可以在bit.ly/mvc-native-mobile-apps找到。
files2.syncfusion.com/dtSupport/DirectTrac/8925... mobile apps with mvc white paper862996781.zip

墙外也找不到啊。

Re: 代码在哪里? by 曾 大鹏

能找到呀。。叫同学翻墙下载的
pan.baidu.com/s/1sj4h1X7

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

3 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT