PhoneGap



在2012年3月份程序员杂志上,应邀撰写了一篇关于phoneGap的介绍,题目为《关于PhoneGap的7件事》,限于篇幅,一些内容没有加入。现把该文章同时发布到博客上,并会逐步填充更详尽的内容。

一切源自iphone。

2008年旧金山的iPhoneDevCamp上,来自Nitobi的工程师Brock Whitten,Rob Ellis和Andre Charland萌发并初步实现了一个想法:构建一个Web技术和Object-C之间的桥梁,亦即让Web技术和Object-C之间能够互联互通。通过标准的Web技术(HTML,JavaScript,CSS),开发者能够开发类似本地应用的iphone应用。

这是一个标准之外的世界,通过非标准的类“黑客”方式,这种技术填充了Web和智能移动设备本地SDK之间的鸿沟。

这个想法迅即获得了大量支持,并普及到了安卓、Windows Phone7,Symbian,黑莓、WebOS和Bada各个平台。

PhoneGap诞生了。

一、PhoneGap是什么

PhoneGap是使用HTML、JavaScript和CSS等Web技术来创建跨平台移动应用的,基于标准的,开源的开发框架。

PhoneGap是为Web应用开发者准备的,那些使用HTML、JavaScript和CSS开发Web应用的开发者。使用PhoneGap,Web应用开发者的开发范畴被进一步拓展到类本地应用(混合应用)的开发领域。

PhoneGap从三个方面帮助开发者:

1.打包:

标准的Web应用,消费者需要打开移动设备上的浏览器,输入URL然后才能访问Web应用。

PhoneGap可以打包Web应用为本地应用格式,比如IOS的ipa、安卓的apk。 对于应用的消费者来说,通过PhoneGap打包的应用和那些使用本地SDK(比如IOS的ObjectC,安卓的Java)开发的应用没什么区别。消费者需要到移动应用商店下载这些应用,安装然后运行。

为了方便,在下文中我们把这些使用Web技术开发,通过PhoneGap打包成本地格式的移动应用统称为“PhoneGap应用”。

2.访问智能移动设备本地特性:

智能移动设备上的现代浏览器提供了一些本地特性的访问,比如GPS。然而,对于移动应用开发来说,需要能够访问更多的本地特性,比如设备摄像头、设备信息、通讯录等等。

PhoneGap提供了诸多的本地特性的JavaScript API接口,使得开发者使用JavaScript即可访问这些浏览器本身不能够支持的本地特性。下图展示了在不同平台上,PhoneGap1.3版本支持的本地特性概览:

本地特性

3. 扩展插件:

PhoneGap在不断推出访问本地功能的新API接口,但对于移动应用的开发者来说,仍然可能需要访问一些PhoneGap尚不支持的功能,或者希望能够使用本地API来解决一些需要重度计算的功能。这时,PhoneGap提供了一套插件体系来帮助开发者定制扩展插件。事实上,标准的PhoneGap本地API也是以插件方式的方式提供的。

通过插件方式,开发者可以使用平台指定的本地语言(比如Java、ObjectC等)编写功能,并通过JavaScript把这些定制化的本地代码暴露出来供PhoneGap应用访问。

二、PhoneGap不是什么

PhoneGap不是JavaScript框架,也不是类似JQuery Mobile这样的移动应用框架,PhoneGap也并不提供IDE环境。

开发者仍然需要依赖类似JQuery Mobile,Sencha Touch这样的第三方Web移动应用开发框架开发基本的Web移动应用。但是,PhoneGap支持这些移动应用开发框架。事实上,PhoneGap并不局限域任何一种JavaScript框架。

三、PhoneGap的现状

截止本文发表,PhoneGap的最新版本是1.5。2011年10月,Adobe公司收购了PhoneGap,并将其贡献给Apache软件基金会,命名为Apache Callback。在经过正式审核和必要的流程之前,PhoneGap仍然处在孵化器阶段。在这个过程中,Apache Callback的名称近来再次变更为Apache Cordova。

PhoneGap作为产品的商业名称仍然被使用。开发者可以在Apache和Github上访问PhoneGap的源代码:https://github.com/callback  或者 https://svn.apache.org/repos/asf/incubator/callback/

四、打包

让我们回到PhoneGap的第一个重要功能:打包。

有三种不同的方式打包生成PhoneGap应用。

使用Dreamweaver打包:

Adobe Dreamweaver可以帮助开发者创建JQuery Mobile+PhoneGap的移动应用项目。如下图:

dreamweave创建phonegap项目

针对移动项目,Dreamweaver提供了一键式打包命令。然而,这种方式一方面只支持IOS和Android两种移动平台应用,另一方面,开发者仍然需要先下载并配置平台对应的SDK。

Dreamweaver打包

使用不同平台的IDE和SDK打包:

更加直接的打包方式是使用针对不同平台的IDE环境和对应的SDK手工打包。在PhoneGap网站的Get Started Guide上,详细介绍了针对不同平台的打包指南:http://phonegap.com/start

使用这种方式,不同平台的打包方式都略有不同,开发者甚至需要自己编写打包代码,比如针对Android平台,并配置相关的配置文件和SDK。尽管这些步骤都非常简单,但实际上对于那些希望能够覆盖尽可能多平台的移动应用开发者来说,这种方式还是非常繁琐。

使用PhoneGap Build服务打包

为了解决繁琐的打包问题,PhoneGap提供了在线打包服务:PhoneGap Build(https://build.phonegap.com/)。开发者需要注册帐号,并上传代码到Github,在完成相关配置后,PhoneGap Build在云端直接编译打包Web应用为本地格式的应用,甚至同时生成了相关的应用二维条形码。

五、 使用PhoneGap访问本地特性

开发者使用JavaScript调用PhoneGap业已提供的本地特性,就像使用任何标准的JavaScript类库一样。

在PhoneGap的官方网站上,可以查看到编写良好的本地特性API列表和代码示例:http://docs.phonegap.com/en/1.3.0/index.html。如下图:

API

我们摘录其中访问运动传感器(Accelerometer)的示例代码来做简单说明,代码中的注释清楚的解释了如何通过JavaScript访问PhoneGap本地API接口。

代码如下:

<script charset="utf-8" type="text/javascript" src="phonegap.js"></script><script charset="utf-8" type="text/javascript">// < ![CDATA[
// < ![CDATA[
    // 监听deviceready事件,等待PhoneGap加载完毕
    //
    document.addEventListener("deviceready", onDeviceReady, false);
 
    // PhoneGap加载完毕,监听运动传感器,设定成功和失败的回调函数(事件侦听器)
    //
    function onDeviceReady() {
        navigator.accelerometer.getCurrentAcceleration(onSuccess, onError);
    }
 
    // onSuccess: 成功得到当前在X,Y,Z轴的运动变化值
    //
    function onSuccess(acceleration) {
        alert('Acceleration X: ' + acceleration.x + '\n' +
              'Acceleration Y: ' + acceleration.y + '\n' +
              'Acceleration Z: ' + acceleration.z + '\n' +
              'Timestamp: '      + acceleration.timestamp + '\n');
    }
 
    // onError: 失败的事件侦听器
    //
    function onError() {
        alert('onError!');
    }
 
// ]]></script>




六、PhoneGap的本质

PhoneGap的本质是解决两个问题:

  • 在移动设备上像本地应用一样运行Web应用;
  • 实现JavaScript和本地API之间的调用和通讯。

在Android和IOS平台上,PhoneGap应用运行在WebView中,具体来说,在Android平台上,PhoneGap应用运行于WebView组件中,而在IOS上,则运行与UIWebView组件中。

WebView和UIWebView用来在移动设备上显示网页,二者都使用WebKit引擎。WebView提供了与浏览器同样的功能,但是不提供浏览器边框。在WebView方式下运行的Web应用,在用户看来就像本地应用一样。WebView封装了Web应用。

下面代码展示了如何在Android项目中使用Android SDK手工打包PhoneGap应用。



public class DemoActivity extends DroidGap {
 
@Override
 
public void onCreate(Bundle savedInstanceState) {
 
super.onCreate(savedInstanceState);
 
super.loadUrl("file:///android_asset/www/index.html");
 
}
 
}

从这个例子中,我们可以看到,首先需要继承DroidGap父类,并覆盖其onCreate方法。在该方法中调用 super.loadUrl(“file:///android_asset/www/index.html”)来运行PhoneGap打包的应用首页。

如果进一步深入查看PhoneGap源码,在PhoneGap提供的父类DroidGap.java中可以看到,DroidGap初始化时实例化了android.webkit.WebView,并在其loadUrl方法中调用WebView.loadUrl方法加载了指定的URL页面。

所以,PhoneGap应用实际上就是运行在移动设备中WebView组件内的Web应用。

七、“黑客”的手段:JavaScript和本地API间的相互调用

PhoneGap解决的本质问题并不仅仅是打包,PhoneGap需要解决的更困难的问题是如何实现JavaScript和本地API之间的调用和通讯,PhoneGap的开发者根据不同的移动平台,采用了巧妙的方式实现了二者的相互调用和通讯。

为了达到目标,PhoneGap团队在不同的平台上采用了不同的方式。

  • IOS:  通过让本地代码拦截JavaScript中调用的window.location=”gap://Class.method/args”命令,来实现从JavaScript到本地代码之间的通讯。在本地代码拦截该命令后,解析获取的参数,然后调用对应的类、方法并传递参数。对应的,使用 UIWebView.stringByEvaluatingJavaScriptFromString来实现本地代码调用JavaScript.
  • Android: 从JavaScript到本地代码的通讯是通过拦截JavaScript的prompt命令来实现的。JavaScript prompt命令默认会弹出对话框,而PhoneGap的android本地代码会拦截该对话框,并进一步取得JavaScript数据。相应的,Android上的PhoneGap内部,使用Java实现了一个HTTP服务器,通过持久性的XHR连接,JavaScript可以不断轮询内部XHR服务器存储的信息,从而实现了从Java到JavaScript方向的通讯。
  • BlackBerry 4.x:   JavaScript与本地代码之间的唯一通讯方式是通过document.cookie实现的。JavaScript设定cookie,本地代码从cookie中获取信息。而对应的,本地代码也可以设定cookie,允许JavaScript从cookie中获取本地代码信息。
  • BlackBerry WebWorks: 新的 BlackBerry WebWorks SDK更好的支持了Java与JavaScript之间的交互通讯。通过 ScriptEngine.addExtension ,Java对象可以被暴露给JavaScript,而对应的Java可以使用ScriptEngine.executeScript来调用JavaScript。
  • Windows Phone 7: 在Windows Phone 7中,JavaScript通过window.external.Notify可以将信息发送给本地代码。而相应的,WebBrowser.InvokeScript允许本地代码调用JavaScript。

小结

PhoneGap为使用Web技术的开发者打开了一扇新的大门,HTML、JavaScript和CSS成为了跨平台移动应用开发中的一级语言。

而更重要的是,PhoneGap延展了浏览器功能,提供了一个基本的框架来实现那些浏览器本身没有提供的功能。甚至,通过PhoneGap,我们可以把那些JavaScript无法承担的任务移交给本地代码完成,以达成更好的性能。这种面向跨平台移动应用的混合编程模式(Web技术+本地代码)能够提供更高效的开发速度和更高性能和质量的应用。

注:本文第七节中主要内容基于博客http://nullisnotanobject.com/phonegap-native-bridge



public class DemoActivity extends DroidGap {
 
@Override
 
public void onCreate(Bundle savedInstanceState) {
 
super.onCreate(savedInstanceState);
 
super.loadUrl("file:///android_asset/www/index.html");
 
}
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值