移动设备无处不在
十年前,微软专业开发者大会(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
感谢李琼对本文的审校。