手持终端
Eclipse平台下Android开发环境的搭建
PhoneGap配置到Eclipse开发环境
使用PhoneGap开发Android应用程序
PhoneGap3.0以上版本配置到Eclipse开发环境
使用PhoneGap3.0版本开发Android应用程序
PhoneGap3.0的第三方Android插件
Cordova配置到Android Studio开发环境
Android系统基本架构
Android的字符串颜色图片样式
Android的常用控件及菜单
Android的消息提示及传递
Android系统的组件通信
Android系统的Service
Android的广播消息接收
Android的数据存储与访问
Android系统的网络应用
Android图形图像处理
Android的Fragment框架
Android系统的并发编程
Java源文件结构与保留字
Java语言的数据类型与变量
Java的运算符与流程控制
Java语言的数组及操作
Java面向对象编程
Java的常用类
Android开发常用工具及命令
Android应用程序权限管理
Android系统提供的R类内置资源
Android系统的控件类及其方法
Android系统的菜单类及其方法
Android系统的对话框
Android应用程序模型及组件
Android的绘图类及方法
Android系统的动画效果
Android的数据库操作
Android的多媒体功能
Android系统照相机的使用
Android的文本朗读TTS
获取Android系统信息
Android系统的电话操作
Android系统的定位
Android系统的传感器
一旦使用了node.js平台下的PhoneGap3.0版本创建了Android项目,只需要修改其中assets/www目录下的index.html及配合的js、css等就可以进行应用开发了,这与开发HTML5网页类似,但有一些特别注意的地方。
assets/www目录结构为:
其中加入了cordova.js和cordova_plugins.js文件,在index.html中必须引入这两个文件:
<script type="text/javasript" src="cordova.js">
<script type="text/javasript" src="cordova_plugins.js">
其中,cordova_plugins.js用于定义可用的插件列表。旧版的cordova.js有222kb,新版本只有71kb,而且也不再引入近500kb大小的cordova-2.9.0.jar,这些改进,是为了缩减代码的大小。为了配合这种优化,cordova把访问设备本地API的功能分为多种插件plugins,开发时只需要引入需要的功能插件,而不是全部加入,以便减小生成的apk程序的大小,并提高程序的运行速度。
1.安装和管理插件:
如果需要使用某个插件,可以使用cordova plugin add命令将插件添加到过程中。示例:
cordova plugin add org.apache.cordova.device
删除已经安装的插件,可以使用cordova plugin remove命令,而查看本地已经安装的插件则使用cordova plugin list命令。
Cordova可用的原生插件包括:
org.apache.cordova.device |
设备基本信息 |
org.apache.cordova.network-infornation |
网络连接事件 |
org.apache.cordova.battery-status |
电量侦测事件 |
org.apache.cordova.device-motion |
重力加速度 |
org.apache.cordova.device-orientation |
罗盘(指南针) |
org.apache.cordova.geolocation |
地理定位 |
org.apache.cordova.camera |
照相机 |
org.apache.cordova.media-capture |
捕获照片、视频 |
org.apache.cordova.media |
媒体播放 |
org.apache.cordova.file |
文件系统管理 |
org.apache.cordova.file-transfer |
文件传输 |
org.apache.cordova.dialogs |
对话框 |
org.apache.cordova.vibration |
振动 |
org.apache.cordova.contacts |
联系人管理 |
org.apache.cordova.globalization |
全球化 |
org.apache.cordova.splashscreen |
启动屏幕 |
org.apache.cordova.inappbrowser |
内置浏览器窗口 |
org.apache.cordova.console |
调试主控台 (不适合Android) |
如果需要使用上述功能,需要使用加入plugin的方法,然后就可以使用相应的功能。Android使用的插件,PhoneGap2.0之后使用config.xml文件来指定,文件位于app/res/xml/目录下,有些版本也可能是app/config.xml文件来指定。
2.PhoneGap内置事件:
在PhoneGap生命周期中,可以产生下列事件,这些事件是内置的,无需安装插件:
名称 |
说明 |
deviceready |
当设备加载完毕后会触发该事件 |
pause |
当程序被暂停到后台运行时会触发该事件 |
resume |
当程序被从后台激活到前台运行时会触发该事件 |
backbutton |
当用户单击“返回”按钮时该事件被触发 |
menulbutton |
当用户单击“菜单”按钮时会触发该事件 |
searchnutton |
当用户按下“搜索”按钮时触发该事件 |
startcallbutton |
当用户“按下”通话按钮时会触发该事件 |
endcallbutton |
当用户“挂断”通话按钮时会触发该事件 |
volumedownbutton |
当用户按下“音量减小”按钮时会触发该事件 |
volumeupbutton |
当用户按下“音量增大”按钮时会触发该事件 |
并不是每部手机设备都具有这些按钮,比如主流安卓手机一般省略了“搜索键”,只有“返回”、“菜单”键以及PhoneGap中没有提到Home键。 除了这些事件,JavaScript内建事件也是可以使用的,如网页加载完成后就会触发body元素的load事件。
上述事件可以分为内核事件和侦测设备按键事件两类,其中deviceready、pause和resume事件为内核事件,其他几种则为设备按键事件。下面详细介绍:
1)deviceready事件:
只有当PhoneGap被完全加载后这个事件才被触发,这个事件非常重要,一定会用到。PhoneGap包含原生代码库好JavaScript代码库两部分,JavaScript会在DOM加载完成后加载,PhoneGap一旦完成加载后会发出一个deviceready事件,当设备发出这个事件后,就可以安全地调用PhoneGap JavaScript API。为了安全,应该在HTML文件的DOM加载完毕后使用document.addEventListener附加deviceready事件监听器,一般是使用body的load事件来实现。示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>deviceready事件使用</title>
<script src="cordova.js" type="text/javascript" charset="utf-8"></script>
</head>
<body onload="onLoaded()">
<script>
function onLoaded(){
document.addEventListener("deviceready",onDeviceReady,false);
}
function onDeviceReady(){
console.log("PhoneGap已经准备好。");
}
</script>
</body>
</html>
2)pause事件和resume事件:
当用户按下设备按钮(如Android的Home按钮)时,会将应用程序放到后台,此时会触发pause事件,当程序从后台恢复到前台运行时将触发resume事件。可以在deviceready监听处理函数中注册相应的事件处理函数,然后定义事件处理函数。示例:
function onDeviceReady(){
document.addEventListener("pause",onPause,false);
document.addEventListener("resume",onResume,false);
}
function onPause(){
console.log("******pause");
}
function onResume(){
console.log("******resume");
}
不要在resume事件处理函数内直接使用alert()等交互性方法,因为会导致一些问题,如果必须使用,可以使用延迟调用的方法,即包含在setTimeout()内:
function onResume(){
setTimeout(function(){
//......
},0);
}
如果不这样做将会导致程序被挂起。
3)backbutton事件:
当用户点击后退按钮时触发该事件,没有后退按键的设备不支持该事件。当点击后退按键时,系统一般会有默认的响应行为,如果想覆载默认的行为,要通过注册一个事件监听器来监听backbutton事件:
document.addEventListener("backbutton",onCallbackFunction,false);
一旦注册该事件,默认的行为将取消。iOS没有后退按键,所以不支持该事件。
4)menubutton事件:
当用户点击菜单按键的时候触发该事件。当点击菜单按键时,系统一般会有默认的响应行为,如果想覆载默认的行为,要通过注册一个事件监听器来监听menubutton事件:
document.addEventListener("menubutton",onMenuFunction,false);
一旦注册该事件,默认的行为将取消。iOS没有菜单按键,所以不支持该事件。
5)searchbutton事件:
当用户点击搜索按键时触发该事件。当点击搜索按键时,系统一般会有默认的响应行为,如果想覆载默认的行为,要通过注册一个事件监听器来监听searchbutton事件:
document.addEventListener("searchbutton",onSearchFunction,false);
一旦注册该事件,默认的行为将取消。iOS没有搜索按键,所以不支持该事件。
Android手机不支持startcallbutton、endcallbutton、volumedownbutton、volumeupbutton事件。
3.应用程序的管理:
PhoneGap提供了一些程序管理方法,用来实现程序退出、清空缓存等功能,这些方法都封装在navigator.app中。
1)清空资源缓存:
当应用程序打开越来越多的网页,所连接的资源都会保存在缓存中,用户如果需要删除这些资源,就可以用清空资源缓存来实现:
navigator.app.clearCache();
2)历史管理:
PhoneGap应用程序嵌入的是一个WebView,当打开多个网页时,也会有历史记录,因此可以管理历史记录。返回上一个网页,等同于按下Back按钮:
navigator.app.backHistory();
清除历史记录:
navigator.app.clearHistory();
3)覆盖back按钮默认行为:
navigator.app.overrideBackbutton(boolean);
其中的参数是一个逻辑值,设置为true可以覆盖back按钮默认行为。
4)在系统浏览器中加载网页:
navigator.app.loadUrl(url,props);
其中的参数url是一个字符串,用来定义要打开的网页网址;参数props是一个Object,可以指定属性来定义打开网页时的行为,可用属性包括:
wait |
指定加载网页前要等待的时间,以毫秒为单位 |
loadingDialog |
指定当加载网页时显示一个内置的“正在加载”对话框,值的格式是“Title,Message” |
loadUrlTimeoutValue |
指定加载网页的超时时间,以毫秒为单位 |
clearHistory |
是一个逻辑值,指定是否清除历史记录,默认false |
openExternal |
是一个逻辑值,指定是否启动一个新的系统浏览器打开网页,默认值为false |
示例:
navigator.app.loadUrl("http://www.google.com",{wait:2000,loadingDialog:"Wait,Loading App",
loadUrlTimeoutValue:60000});
网页加载中,也可以使用下面的方法取消加载:
navigator.app.cancelLoadUrl();
不再推荐使用这两个方法,建议使用新增的window.open()方法来替代。
4.Cordova配置:
Cordova可以使用res/xml/config.xml文件来进行一些设置,也可以指定要安装的插件。这个配置文件是一个XML格式文件,根元素是widget,其他配置节点都使用特定的元素及其属性来实现。
·name元素:用来指定应用程序名
·description元素:用来给应用程序一个描述
·author元素:定义应用程序的作者
·定义默认要加载的网页,这个地址可以使用Config.getStartUrl()获取
<content src="index.html">
<content src="http://mysite.com/myapp.html">
·设置日志等级,可选值包括ERROR、WARN、INFO、DEBUG、VERBOSE,默认值是DEBUG。
<log level="DEBUG" />
还有其他一些设置。
1)白名单设置:
config.xml文件可以定义一组网址,这些网址可以被加载进DroidGap,也就是白名单,格式:
<access origin="http://server regexp" subdomains="true" />
示例配置:
<!--允许本地网页被加载-->
<access origin="http://127.0.0.1" />
<!--允许通过http访问example.com,但不允许访问子域-->
<access origin="http://example.com" />
<!--允许通过加密连接https访问example.com,但不允许访问子域-->
<access origin="https://example.com" />
<!--允许通过加密连接https访问example.com,同时允许访问子域-->
<access origin="https://example.com" subdomains="true"/>
<!--使用*号为通配符也可以实现相同的目的,访问所有子域-->
<access origin="https://*.example.com" />
<!--使用*号作为通配符,访问所有域-->
<access origin=".*" />
2)指定要安装的插件:
一个feature元素指定一个插件,name指定服务名(JavaScript程序将使用该服务名)。其下定义param元素,该元素的name属性指定所应用的平台,android-package表示适用于Android平台,ios-package表示适用于iOS平台。value属性指定插件的完全限定名。示例:
<feature name="Device">
<param name="android-package" value="org.apache.cordova.device.Device" />
</feature>
3)程序特性设置:
在res/xml/config.xml文件也可以定义多个Preference元素来描述编译时的特性,下面是两个默认设置:
<!--是否使用浏览器历史-->
<Preference name="useBrowserHistory" value="true" />
<!--如果设置为true,程序挂起时将退出,例如按Home键时-->
<Preference name="exit-on-suspend" value="false" />
每个Preference元素包含name属性用来指定特性,value属性指定特性的值。可以使用下面一些特性:
useBrowserHistory |
定义是否使用浏览器的历史记录,默认为true,不建议使用 |
loadingDialog |
在加载应用程序时显示一个平台内置的正在加载对话框,属性value的格式是Title,Message |
loadingPageDialog |
在加载一个子页时显示一个平台内置的正在加载对话框,属性value的格式是Title,Message |
errorUrl |
定义应用程序出错后要加载的网页,这个网页位于程序android_assess/www/目录下 |
backgroundColor |
设置程序的背景颜色,支持4位的16进制值,首位是alpha值,后面三位是RGB值,如黑色0x00000000 |
loadUrlTimeoutValue |
定义加载一个URL的超时设置,超过这个时间就会抛出timeout错误 |
keepRunning |
定义在点击home键或back键后程序是否保持后台运行,默认为true |
splashscreen |
定义splash屏幕,值是图片名称(不包括扩展名) |
disallowOverscroll |
当用户滚动超出视图的边缘时,该选项定义是否取消发光效果,默认false,设置true将取消发光效果 |
fullscreen |
指定是否全屏,设置值为true全屏,为默认值 |
Orientation |
指定程序的布局方向,可选值包括default landscape portrain |
HideKeyboardFormAccessoryBar |
指定是否呈现键盘上附加的工具栏,默认为false |
4)在主类中设置:
这些特性也可以在主类的onCreate()方法中设置,根据特性值的不同可以使用下面的几种方法来实现。
super.setStringProperty(); //值为字符串
super.setIntegerProperty(); //值为整数
super.setBooleanProperty(); //值为逻辑值
示例代码:
//当加载应用程序时显示内置的“正在加载”对话框,值的格式是"Title,Message"
super.setStringProperty("loadingDialog","Wait,Loading Demo...");
//当加载应用程序的一个子窗口时显示内置的“正在加载”对话框,值的格式是"Title,Message"
super.setStringProperty("loadingPageDialog","Loading page..");
//设置背景色,默认值为黑色
super.setIntegerProperty("backgroundColor",Color.WHITE);
//设置super.loadUrl()加载页面的超时设置,以毫秒为单位,默认值20000ms
super.setIntegerProperty("loadUrlTimeoutValue",60000);
//如果使用super.loadUrl()加载出错,则加载另一个网页作为替代
super.setStringProperty("errorUrl","file:///android_asset/www/error.html");
//确保应用程序保持在后台运行,默认设置为true
super.setBooleanProperty("keepRunning",true);
5)权限配置:
程序在执行时如果需要读取安全敏感的数据,或者要使用隐私功能,或者访问特定的资源以及硬件,就必须使用清单文件声明相关的权限获取许可Permission。不同的手机平台使用不同的清单文件来声明权限,而且相同手机平台可能存在多个清单文件应用于不同的目的。
大部分平台的清单文件都是一个XML格式的文件,Android平台的清单为androidManifest.xml。
5.电量侦测事件:
使用电量侦测插件,可以获取电量使用情况,插件名为org.apache.cordova.battery-status。安装插件的命令为:
cordova plugin add org.apache.cordova.battery-status
一旦安装了插件,就可以使用相关事件。
config.xml文件中配置:
<feature name="Battery"><param name="android-package" value="org.apache.cordova.batterystatus.BatteryListener" /></feature>
电量变化会触发几个事件:
事件 |
说明 |
batterycritical |
当程序侦测到电池电量降低到临界点时会触发该事件 |
batterylow |
当程序侦测到电池电量降低到几个较低水平值时触发该事件 |
batterystatus |
当程序侦测到电池电量至少发生百分之一的改变时触发该事件 |
1)batterycritical事件:
当程序侦测到电池电量降低到临界点时会触发该事件,临界点的值由设备指定。
document.addEventListener("batterycritical",onCallbackFunction,false);
事件处理函数包含一个参数,该参数是一个对象,该对象包含两个属性:
·level:获取电池剩余电量的百分比,值范围是0~100,Number类型。
·isPlugged:表示设备是否接通电源,boolean类型。
2)batterylow事件:
当程序侦测到电池电量降低到一个较低水平值时会触发该事件,水平值由设备指定。
document.addEventListener("batterylow",onCallbackFunction,false);
事件处理函数包含一个参数,该参数是一个对象,该对象包含两个属性:
·level:获取电池剩余电量的百分比,值范围是0~100,Number类型。
·isPlugged:表示设备是否接通电源,boolean类型。
3)batterystatus事件:
当程序侦测到电池电量至少发生1%的改变时会触发该事件,当设备连接或者断开电源时也会触发该事件。
document.addEventListener("batterystatus",onCallbackFunction,false);
事件处理函数包含一个参数,该参数是一个对象,该对象包含两个属性:
·level:获取电池剩余电量的百分比,值范围是0~100,Number类型。
·isPlugged:表示设备是否接通电源,boolean类型。
示例:
function onDeviceReady(){
document.addEventListener("batterystatus",onBatteryStatus,false);
}
function onBatteryStatus(status){
if(status.isPlugged){
alert("正在充电......,目前电量是:"+status.level+"%");
}else{
if(status.level<2){ //当电量小于2%
alert("电量不足,请尽快关闭应用,接到电源充电!");
}else{
alert("正在放电......,目前电量是:"+status.level+"%");
}
}
}
6.程序内置浏览器窗口:
使用window.open()方法可以让用户在应用程序内显示一个浏览器窗口,但PhoneGap覆写了这个方法,该方法返回一个InAppBrowser对象,用于引用这个新打开的窗口,从而可以在应用程序内控制这个浏览器窗口。
InAppBrowser浏览器插件名为org.apache.cordova.inappbrowser,可以使用命令安装插件:
cordova plugin add org.apache.cordova.inappbrowser
config.xml文件中配置:
<feature name="InAppBrowser"><param name="android-package" value="org.apache.cordova.inappbrowser.InAppBrowser" /></feature>
1)打开一个浏览器窗口:
使用window.open()方法会在一个新的InAppBrowser实例中打开一个URL,也可以在当前浏览器中或者在系统浏览器中打开一个URL。语法格式为:
var ref=window.open(url,target,options);
其中,ref是返回的InAppBrowser实例,使用它可以进一步操作这个窗口;参数url指定要加载的URL地址字符串,如果其中包含Unicode字符,要先用encodeURL()进行编码;参数target指定加载URL到的目标位置,这个参数可选,默认是_self。Target值见表:
_self |
如果URL在白名单列表中,在Cordova WebView中打开URL,否则在InAppBrowser窗口中打开URL |
_blank |
在InAppBrowser窗口中打开URL |
_system |
在系统浏览器中打开URL |
参数options是可选的,指定功能项,各项功能之间使用逗号隔开,且不能包含空格,默认值是“location=yes”,这也是多个平台都支持的功能项。功能项包括:
·location:设置InAppBrowser窗口是否出现地址栏,可选值包括yes和no。
·closebuttoncaption:用来设置Done按钮显示的文字。
·hidden:设置为yes则会先加载网页但不显示,然后通过调用show方法显示网页;默认值是no,表示正常加载和显示。无论是否hidden,加载完成后都会触发加载完成事件。
·clearcache:设置为yes,表示将会首先清除Cookie,然后加载网页;默认为no。
·clearsessioncache:设置为yes,表示将会首先清除Session,然后加载网页;默认为no。
iOS系统还有更多选项。
2)关闭窗口:
可以使用close()方法关闭这个窗口。语法格式:
ref.close();
示例:
function onDeviceReady(){
var ref=vimdow.open('http://apache.org','_blank','location=yes');
setTimeout(function(){ref.close();},5000);
}
上述代码,在窗口打开5秒后关闭。
3)事件处理:
可以使用addEventListener()和removeEventListener()监控和管理新窗口的事件。有以下几个事件可以监听:
loadstart |
当InAppBrowser窗口开始加载一个URL时触发该事件 |
loadstop |
当InAppBrowser窗口完成加载一个URL时触发该事件 |
loaderror |
当InAppBrowser窗口加载一个URL出错时触发该事件 |
exit |
当InAppBrowser窗口关闭时触发该事件 |
addEventListener事件处理函数包含一个参数,该参数是一个InAppBrowserEvent对象,有如下属性:
·type:事件名称字符串,也即loadstart、loadstop、loaderror、exit
·url:加载的URL地址字符串
·code:返回出错代码,仅适用于loaderror事件
·message:返回出错消息字符串,仅适用于loaderror事件
4)显示隐藏的网页:
打开网页时,功能项hidden被设置为yes,会先加载网页但不显示。需要随后显示这个网页,调用show()方法来实现。语法格式为:
ref.show();
5)执行脚本注入:
executeScript()方法可以将一个JavaScript代码注入InAppBrowser窗口并执行,语法格式为:
ref.executeScript(details,callback);
其中,参数ref是返回的InAppBrowser实例;参数details定义要注入的JavaScript代码信息,是一个Object类型,可以定义file或code属性;参数callback定义执行注入后的回调函数。
参数details的file属性,指定一个JavaScript文件地址,这个文件中的代码将会注入到当前InAppBrowser窗口;参数details的code属性,指定一个JavaScript代码字符串,这段代码将会注入到当前InAppBrowser窗口,并且将代码的返回值(Array类型),传递仅callback函数,对于多行代码,仅包含最后一行代码的返回值。示例:
ref.addEventListener('loadstop',function(){
ref.executeScript({file:"myscript.js"});
});
6)执行CSS样式注入:
insertCSS()方法可以将一个CSS样式注入InAppBrowser窗口,语法格式为:
ref.insertCSS(details,callback);
其中,参数ref是返回的InAppBrowser实例;参数details定义要注入的CSS样式信息,是一个Object类型,可以定义file或code属性;参数callback定义执行注入后的回调函数。
参数details的file属性,指定一个CSS样式文件地址,这个文件中的代码将会注入到当前InAppBrowser窗口;参数details的code属性,指定一个CSS样式代码字符串,这段代码将会注入到当前InAppBrowser窗口。这个方法一般都应该在文档加载完成后被执行。示例:
ref.addEventListener('loadstop',function(){
ref.insertCSS({file:"mystyles.css"});
});
7.设备信息提示:
使用系统消息提示,需要安装插件:
cordova plugin add org.apache.cordova.device
安装了插件就可以使用相关属性。
config.xml文件中配置:
<feature name="Device"><param name="android-package" value="org.apache.cordova.device.Device" /></feature>
AndroidManifest.xml中配置:
<uses-permission android:name="android:permission.READ_PHONE_STATE" />
包含的与设备硬件和软件相关的信息有:
属性 |
功能描述 |
device.name |
推荐使用device.model属性替代该属性 |
device.cordova |
返回Cordova版本号 |
device.platform |
返回设备使用的操作系统,例如Android、iOS、WinCE等 |
device.uuid |
返回标识该设备的唯一ID,uuid是由设备生产商及特定设备平台(或型号)所决定的。iOS在每个应用程序每次安装都会创建一个uuid。 |
device.version |
返回操作系统的版本号 |
device.model |
返回设备的型号名称,内容一般由生产厂商设置,Android获取的是产品名,及生产期间的代号。 |
这几个属性使用window.device对象访问。示例:
function onDeviceReady(){
alert('Device Model:'+device.model+"\n"+'Device Cordova:'+device.cordova+"\n"
+'Device Platform:'+device.platform+"\n"+'Device UUID:'+device.uuid+"\n";
+'Device Version:'+device.version+"\n");
}
PhoneGap运行可能会比较慢,造成页面加载完毕后会有一段等待时间,然后才会获取到设备信息,这时页面中预先加一个提示。
<body>
<h4 id="deviceProperties">正在加载设备,请等待......</h4>
</body>
8.系统消息提示对话框:
要使用系统消息提示对话框,需要安装插件:
cordova plugin add org.apache.cordova.dialogs
config.xml文件中配置:
<feature name="Notification"><param name="android-package" value="org.apache.cordova.dialogs.Notification" /></feature>
一旦安装了插件,就可以使用几个方法,它们都使用wondows.navigator对象访问,调用的是系统内置的对话框。
1)警告对话框:
notification.alert()方法弹出一个可定制的警告对话窗口,只有一个按钮,语法格式为:
navigetor.notification.alert(message,alertCallback,[title],[buttonName]);
其中,参数message定义对话框显示的信息;参数alertCallback定义当警告对话框关闭时被调用的回调函数;参数title可选,定义对话框的标题,默认为Alert;参数buttonName可选,定义按钮标签,默认为OK。示例:
function onDeviceReady(){
navigetor.notification.alert('这是PhoneGap',alertDismissed,'Hello!','OK');
}
一些平台只是使用了浏览器的alert()方法,但浏览器方法不能定制。
2)确认对话框:
notification.confirm()方法弹出一个可定制的确认对话窗口,支持一到三个按钮,语法格式为:
navigetor.notification.confirm(message,confirmCallback,[title],[buttonLabels]);
其中,参数message定义对话框显示的信息;参数confirmCallback定义一个按下按钮后触发的回调函数,回调函数的参数为按下按钮的索引,索引号从1开始;参数title可选,定义对话框的标题,默认为Confirm;参数buttonLabels可选,定义按钮标签,如果声明多个按钮以逗号分隔。示例:
function onConfirm(button){
alert('选择的按钮是:'+button);
}
function onDeviceReady(){
navigetor.notification.confirm('你赢了!',onConfirm,'Game Over!',['Restart','Exit']);
}
Android最多支持三个按钮,并且在Android3.0后序号按相反顺序排列。
可以在回调函数中使用条件语句检测这个返回的参数值来获取用户点击的按钮。
3)提示输入消息对话框:
当需要用户输入消息进行判断时,使用这种对话框。语法格式:
navigetor.notification.prompt(message,promptCallback,[title],[buttonLabels],[defaultText]);
其中,参数message定义对话框显示的信息;参数promptCallback定义一个按下按钮后触发的回调函数,回调函数的参数是Object类,包含buttonIndex和input1两个属性;参数title可选,定义对话框的标题,默认为Prompt;参数buttonLabels可选,定义按钮标签,如果声明多个按钮以逗号分隔;参数defaultText可选,用于在输入文本框中显示预置的消息。示例:
function onPrompt(returned){
if(returned.buttonIndex==2){
alert('输入值是:'+returned.input1);
}else if(returned.buttonIndex==1){
alert('你选择了重启!');
}
}
function onDeviceReady(){
navigetor.notification.prompt('你赢了!',onPrompt,'Game Over!',
['Restart','OK&Exit'],'请输入你的名字:');
}
执行代码将弹出一个提示消息对话框让用户输入,返回的Object参数,属性buttonIndex为按下按钮的索引,也就是参数buttonLabels所定义的标签的顺序,索引号从1开始,属性input1是输入文本的内容。Android最多支持三个按钮,并且在Android3.0后序号按相反顺序排列。
9.系统震动和蜂鸣提示:
要使用系统震动和蜂鸣提示需安装插件:
cordova plugin add org.apache.cordova.vibration
一旦安装了插件,就可以使用几个方法,它们都使用wondows.navigator对象访问。
1)触发设备蜂鸣:
notification.beep()方法使设备发出beep生,语法格式:
navigetor.notification.beep(times);
其中的参数times定义beep声重复的次数。示例:
navigetor.notification.beep(2);
Android系统会播放在Setting/Sound&Display面板内指定的通知铃声。iOS使用www根目录下的beep.wav音频文件,时长低于30s,忽略发声次数参数。
2)触发设备震动:
notification.vibrate()方法使设备在指定时长内震动,语法格式为:
navigetor.notification.vibrate(ms);
其中的参数ms定义以毫秒为时长的震动。示例:
navigetor.notification.vibrate(2500);
iOS系统中忽略时长参数,震动时长为预定值。
config.xml文件中配置:
<feature name="Notification"><param name="android-package" value="org.apache.cordova.dialogs.Notification" /></feature>
AndroidManifest.xml中配置:
<uses-permission android:name="android:permission.VIBRATE" />
10.文件系统处理:
JavaScript无法访问文件系统,PhoneGap插件可以实现对文件系统的访问,使用前需要安装:
cordova plugin add org.apache.cordova.file
config.xml文件中配置:
<feature name="File"><param name="android-package" value="org.apache.cordova.file.FileUtils" /></feature>
一旦安装了插件,就可以使用该插件的API:
类名或接口名 |
功能 |
DirectoryEntry |
表示一个目录 |
DirectoryReader |
表示一个目录中的文件及子目录组成的列表 |
File |
表示单个文件的当前状态,其包含当前文件的一些属性 |
FileEntry |
表示一个文件 |
FileError |
表示一个文件操作错误 |
FileReader |
用于读取文件的内容 |
FielSystem |
包含有当前文件系统的信息 |
FileTransfer |
通过网络传输文件,包括上传和下载(用于文件传输插件) |
FileTransferError |
表示网络传输出错(用于文件传输插件) |
FileUploadOptions |
定义文件上传选项(用于文件传输插件) |
FileUploadResult |
表示文件上传的结果(用于文件传输插件) |
FileWrite |
用于写入和修改文件的内容 |
标识 |
一个Object类型数据,用于为DirectoryEntry的一些方法提供参数 |
LocalFileSystem |
提供了一种获得根文件系统的方式 |
Metadata |
包含了文件或目录的元数据 |
1)Android文件系统操作权限:
对于安全至上的移动操作系统,很大程度上推崇应用隔离。Android系统中文件系统可以分为两部分。
⑴手机ROM中应用程序目录的读写:
这个属于程序的独立权限,即每个程序默认只能读写自己目录下的文件或文件夹。默认路径:
file:///data/data/your_project/
其中,your_project是程序包名。
⑵外部存储的读写:
外部存储的读写大多数情况下就是对SD卡的读写,Android系统默认对每个程序都开放SD卡读写功能,SD卡的默认路径为:
file:///mnt/sdcard/
很多厂商在生产手机时会将ROM分隔部分空间作为内置的存储,这时这一部分存储也可以将其看作一个SD卡,一般会使用如下的路径:
file:///mnt/sdcard-ext/
不过这个路径一般都不会使用,仅有定制机才会使用这个SD卡,因为定制的程序可以清楚地知道这个SD卡的路径,所以事先就会设置好。
要读写SD卡,要有相应的权限设置,即在AndroidManifest.xml文件中添加权限设置:
<uses-permission android:name="android.peimission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.peimission.MOUNT_UNMOUNT_FILESYSTEMS" />
⑶Android手机系统目录:
·/system/app目录:Android手机系统应用存放地,为系统默认组件,都是apk格式文件
·/system/bin目录:这个目录下的文件都是系统的本地程序,是二进制程序
·/system/etc目录:这里保存的都是系统的配置文件
·/system/fonts目录:这里保存着系统的字体,中文字库,或Unicode字库
·/system/framework目录:这里是系统的框架,保存着系统核心程序和Java类库,jar文件
·/system/lib目录:里面保存的是系统底层类库,如平台运行时库,很多是框架层的实现
·/system/media目录:保存着系统默认的铃声,还有一些系统提示音事件音,alarms是闹铃提醒声音,notification是短信或提示音,ringtones是来电铃声
·/data/data目录:用户安装应用程序的用户文件的存储位置,一般为设置文件、数据库或临时文件,以每个应用程序的包名来命名
2)获取文件系统:
定义了requestFileSystem和resolveLocalFileSystemURL两种方法获取根文件系统。
⑴requestFileSystem方法获取文件系统根目录:
其回调函数包含一个参数,一个FileSystem对象,该参数包含文件系统信息,可以用于获取应用程序目录。一旦获取目录,就可以对文件系统进行操作,例如遍历整个文件系统,创建、添加、移动、复制、删除文件和文件夹,也可以读取和修改文件的内容等。语法格式为:
window.requestFileSystem(type,size,onSuccess,onError);
其中,参数type指定获取操作返回的文件系统根目录是否是持久的,可以是LocalFileSystem. PERSISTENT和LocalFileSystem.TEMPORARY两个常量之一,分别用于持久化存储和不需要保证持久化的存储类型;参数size指定要存储的空间大小,以bytes为单位;参数onSuccess是成功执行后的回调函数,并且返回一个FileSystem对象;参数onError是失败回调函数,当调用过程出错,或者系统拒绝访问时调用该函数,并且返回一个FileError对象。
示例:
function onSuccess(fileSystem){
console.log(fileSystem.name);
console.log(fileSystem.root.name);
}
function onError(error){
alert(error.code);
}
window.requestFileSystem(LocalFileSystem.PERSISTENT,0,onSuccess,onError);
成功回调函数的参数是一个FileSystem对象,它表示了文件系统的信息,有name和root两个属性,name属性表示文件系统的唯一名字,取决于参数type,值可以是persistent或temporary;root属性可以返回文件系统根目录,值是一个DirectoryEntry对象,通过这个对象可以遍历这个文件系统。
⑵resolveLocalFileSystemURI方法直接读取目录或文件:
语法格式为:
resolveLocalFileSystemURI(uri,onSuccess,onError);
其中,参数uri指定本地的一个文件或目录的地址,本地文件可能是应用程序目录下的文件或目录,有可能是SD卡中的文件或目录;参数onSuccess是成功执行的回调函数,返回参数是一个DirectoryEntry对象或FileEntry对象;参数onError是失败的回调函数,当调用过程出错,或者系统拒绝访问时调用,返回的参数是一个FileError对象。
示例:
function onSuccess(fileEntry){
console.log(fileEntry.name);
}
function onError(error){
alert(error.code);
}
window.resolveLocalFileSystemURI("file:///example.txt",onSuccess,onError);
3)目录处理:
一旦读取了文件系统根目录,或者直接使用URL读取了一个目录,PhoneGap就可以使用类DirectoryEntry来处理文件系统目录。
一个DirectoryEntry实例就代表文件系统内的一个目录,使用其公开的方法和属性可以处理目录。属性见下表:
属性 |
功能描述 |
数据类型 |
isFile |
检查是否是文件,如果是文件返回false |
Boolean |
isDirectory |
检查是否是文件夹,如果是文件夹返回true |
Boolean |
name |
DirectoryEntry的名字,不包含顶层目录 |
DOMString |
fullPath |
从根到此目录的完整的绝对路径,推荐toURI()方法替代 |
DOMString |
filesystem |
返回DirectoryEntry所在的文件系统,不支持 |
FileSystem |
W3C规范内定义了filesystem属性用于获取目录所在的文件系统,但PhoneGap并不支持。
DirectoryEntry对象的方法见下表:
方法 |
功能描述 |
getMetadata() |
获得目录的元数据 |
setMetadata() |
设置目录的元数据 |
moveTo() |
移动一个目录到文件系统中不同的位置 |
copyTo() |
复制一个目录到文件系统中不同的位置 |
toURI() |
返回一个可以定位目录的URI |
remove() |
删除一个目录,这个目录必须是空的 |
getParent() |
查找父级目录 |
createReader() |
建立一个可以从目录中读取条目的新DirectoryReader对象 |
getDirectory() |
建立或者寻找一个目录 |
getFile() |
建立或者寻找一个文件 |
removeRecusively() |
删除一个目录以及它内部的所有内容 |
⑴getMetadata方法:
该方法用来查找目录的元数据,语法格式为:
getMetadata(onSuccess,onError[,metadataObject])
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个Metadata对象作为参数;参数onError定义一个回调函数,当该方法出现错误后就调用这个回调函数,并传递一个FileError对象作为参数;参数metadataObject是一个元数据对象,例如{"com.apple,MobileBackup":1}。示例:
function onSuccess(metadata){
console.log("Last Modified: "+metadata.modificationTime);
}
function onError(error){
alert(error.code);
}
entry.getMetadata(onSuccess,onError);
回调函数返回的元数据对象代表了文件或目录的元信息,DirectoryEntry.getMetadata()方法和FileEntry.getMetadate()方法都可以返回元数据对象。当前,该对象仅包含一个属性modificationTime,用于表示最后修改的时间。
⑵getParent方法:
该方法用来查找包含此目录的父级目录。语法格式为:
entry.getParent(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递标示父级目录的DirectoryEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
⑶moveTo方法:
该方法用来移动一个目录到文件系统中不同的位置。在把一个目录移动到另外的一个已经存在的空目录上时,PhoneGap会尝试去删除或者替换已存在的目录。语法格式:
entry.moveTo(parentEntry,newName,onSuccess,onError);
其中,参数parentEntry指定一个标示目标目录的DirectoryEntry对象,即要移动到的目录;参数newName可选,指定目录的新名字,如果没有指定则为当前名字;参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个DirectoryEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。示例:
function onSuccess(entry){
console.log("New Path: "+entry.fullPath);
}
function onError(error){
alert(error.code);
}
function moveDir(entry){
var parentEntry=new DirectoryEntry({fullPath:"/document"});
entry.moveTo(parentEntry,newName,onSuccess,onError);
}
做以下尝试会发生错误:移动目录到其自身,或移动到其任意深度的子目录中;在当前父目录中移动,但没有指定一个不同的目录名;目录所要移动到的目标路径以及有同名的文件;目录所要移动到的目标路径已经有同名并且不为空的目录。
⑷copyTo方法:
该方法用来复制一个目录到文件系统不同的路径,目录复制总是递归的,它们会复制目录中的所有内容。语法格式为:
entry.copyTo(parentEntry,newName,onSuccess,onError);
其中,参数parentEntry指定一个标示目标目录的DirectoryEntry对象,即要复制到的目录;参数newName可选,指定目录的新名字,如果没有指定则为当前名字;参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个DirectoryEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
做以下尝试时会发生错误:复制一个目录到其任意深度的子目录中;还是在当前父目录中复制,但是没有指定一个不同的目录名。
⑸remove方法:
该方法用来删除一个空目录。语法格式为:
entry.remove(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,该函数没有参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
当有以下行为时会发生错误:删除一个非空目录;删除文件系统的根目录。示例:
function onSuccess(entry){
console.log("Removal succeeded ");
}
function onError(error){
alert('操作没有成功:'+error.code);
}
entry.remove(onSuccess,onError);
⑹removeRecursively方法:
该方法用来删除一个目录及其内容。如果接收到一个错误信息(如目录中包含不能删除的文件),这时一部分文件就会被删除掉。语法格式为:
entry.removeRecursively(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,该函数没有参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。如果尝试删除一个目录的内容,而内容中包含一个不能被移除的文件,就接收到一个错误,而且此时可能一部分文件已经被删除。
如果试图删除文件系统中的根目录则会发生错误。
⑺createReader方法:
该方法建立一个新的DirectoryReader对象,用来读取目录的条目。语法格式为:
entry.createReader();
然后可以使用DirectoryReader对象的readEntries()方法读取列表中的条目,然后遍历这些条目,从而达到遍历目录的目的。示例:
var oDirectoryReader=oDirectoryEntry.createReader();
oDirectoryReader.readEntries(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个DirectoryEntry对象或FileEntry对象;参数onError定义一个回调函数,当该方法执行后出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
遍历目录示例:
function onSuccess(entries){
var i;
for(i=0;i<entries.length;i++){
console.log(Entries[i].name);
}
}
function onError(error){
alert('Failed to list directory contents:'+error.code);
}
var directoryReader=dirEntry.createReader;
directoryReader.readEntries(onSuccess,onError);
⑻getDirectory方法:
该方法用来新建或查询一个已经存在的目录。语法格式为:
entry.getDirectory(path,options,onSuccess,onError);
其中,参数path定义用来查找或建立目录的路径,可以是一个绝对路径或者是一个相对路径;参数options是一个Object,用于指定当指定目录不存在时是否新建目录;参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个DirectoryEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
参数options可以指定的属性见下表:
属性 |
功能描述 |
create |
用于说明文件或者目录如不存在是否将被建立 |
exclusive |
单独使用此参数不会有任何影响;配合create使用,当目标路径存在时,有可能导致建立目录或文件失败 |
在试图建立一个不存在直接父级目录的目录时会发生错误。
示例:
function onSuccess(parent){
console.log("Parent Name:"+parent.name);
}
function onError(error){
alert('操作没有成功:'+error.code);
}
function onSuccess(fileSystem){
fileSystem.root.getDirectory("app_newDir",
{create:true,exclusive:false},onCreateSuccess,onCreateError);
}
⑼getfile方法:
该方法用来创建或者查找一个文件。语法格式为:
entry.getFile(path,options,onSuccess,onError);
其中,参数path定义用来查找或建立文件的路径,可以是一个绝对路径或者是一个相对路径;参数options是一个Object,用于指定当指定文件不存在时是否新建文件;参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个FileEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。当试图建立一个不存在直接父级目录的文件时会发生错误。
getfile方法执行成功后会返回一个FileEntry对象,FileEntry类用来处理文件系统的文件,一个FileEntry实例就代表文件系统内的一个文件,其属性和方法与DirectoryEntry对象的基本一致,但包括了两个特有的方法,createWrite()和file()方法。
4)文件处理:
PhoneGap使用FileEntry类来处理文件系统目录,一个FileEntry实例就代表文件系统内的一个文件,使用其公开的属性和方法可以处理文件。FileEntry的属性见下表:
属性 |
功能描述 |
数据类型 |
isFile |
总是返回true |
boolean |
isDirectory |
总是返回false |
boolean |
name |
FileEntry的名字,不包含前置目录 |
DOMString |
fullPath |
从根到此文件条目完整的绝对路径 |
DOMString |
W3C规范定义了filesystem属性,用于获取文件所在的文件系统,但PhoneGap并不支持。
FileEntry对象的方法见下表:
方法 |
功能描述 |
getMetadata |
获得文件的元数据 |
moveTo |
移动一个文件到文件系统中不同的位置 |
copyTo |
复制一个文件到文件系统中不同的位置 |
toURI |
返回一个可以定位文件的URI |
remove |
删除一个文件 |
getParent |
查找父级目录 |
createWriter |
建立一个可用于写文件的FileWrite对象 |
file |
建立一个包含文件属性的File对象 |
这些方法的使用与前面目录操控的方法基本相同,但有专用的文件操控方法:
⑴file()方法:
该方法返回文件的当前状态,此状态用File对象来表示。语法格式:
entry.file(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个File对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。
File对象可以使用的属性见下表:
属性 |
功能描述 |
数据类型 |
name |
文件名字 |
DOMString |
fullPath |
从根到此文件条目完整的绝对路径 |
DOMString |
type |
文件的MIME类型 |
DOMString |
lastModifiedDate |
文件最后修改时间 |
Date |
size |
文件的byte大小 |
long |
示例:
function onSuccess(file){
console.log("File size: "+file.size);
}
function onError(error){
alert(error.code);
}
entry.file(onSuccess,onError);
⑵createWrite()方法:
该方法建立一个与当前文件关联的FileWrite对象,使用FileWrite对象可以修改文件的内容。语法格式为:
entry.createWrite(onSuccess,onError);
其中,参数onSuccess定义一个回调函数,成功执行该方法后就调用这个回调函数,并传递一个FileWrite对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileError对象作为参数。示例:
function onSuccess(write){
writer.write("Some text to the file ");
}
function onError(error){
alert(error.code);
}
entry.createWriter(onSuccess,onError);
5)读取文件内容:
使用FileReader类可以读取文件的内容,并且可以监控读取状态。文件可以当成文本或者base64编码的数据字符串读出来。首先要使用构造方法创建一个实例,然后就可以应用该方法和属性。语法格式为:
var reader=new FileReader();
FileReader类的属性见下表:
属性 |
功能描述 |
数据类型 |
readyState |
当前要读取文件的状态,3个字符串之一:EMPTY、LOADING、DONE |
DOMString |
result |
读取出来的文件内容 |
DOMString |
error |
包含错误信息的对象 |
FileError |
onloadstart |
开始读取文件时被调用 |
Function |
onprogress |
正在读取文件过程中被调用,反馈读取进度(当前未支持) |
Function |
onload |
当读取安全完成时被调用 |
Function |
onabort |
当取消读取文件时被调用,如调用abort方法 |
Function |
onerror |
当读取失败时被调用 |
Function |
onloadend |
当请求完成后调用,成功或失败都会调用 |
Function |
FileReader对象的方法见下表:
方法 |
功能描述 |
abort() |
终止读取文件 |
readAsDataURL() |
读取文件内容,并将数据按照base64编码方式返回 |
readAsText() |
读取文件内容为文本文件 |
readAsBinaryString() |
读取文件内容为二进制字符串 |
readAsArrayBuffer() |
读取文件内容作为数组 |
⑴readAsDataURL()方法:
该方法将一个文件读取为base64编码的字符串。语法格式为:
reader.readAsDataURL(fileEntry);
其中,参数fileEntry指定要读取的文件所表示的FileEntry对象。示例:
function onReadSuccess(evt){
console.log(evt.target.result);
}
function onReadError(error){
console.log(evt.target.error.code);
}
function onGetTargetFileSuccess(fileEntry){
var reader=new FileReader();
reader.onload=onReadSuccess;
reader.onerror=onReadError;
reader.readAsDataURL(fileEntry);
}
⑵readAsText()方法:
该方法将一个文件读取为文本字符串。语法格式为:
reader.readAsText(fileEntry[,encoding]);
其中,参数fileEntry指定要读取的文件所表示的FileEntry对象;参数encoding指定文件内容的编码格式,默认为UTF8。
iOS不支持encoding参数,必须使用UTF8格式,不支持readAsDataURL()方法。
⑶readAsBinaryString()方法:
该方法可以将文档读取为二进制字符串,因为JavaScript无法处理二进制数据,因此一般都会将这个二进制字符串上传到服务器处理。语法格式:
reader.readAsBinaryString(fileEntry);
⑷readAsArrayBuffer()方法:
该方法可以将文档读取为数组,语法格式:
reader.readAsArrayBuffer(fileEntry);
数组的内容是8位无符号整数,因此可以转换为强类型数组进行处理,例如读取图片作为WebGL贴图使用。示例:
var reader=new FileReader();
reader.onloadend=function(evt){
console.log(new Uint8Array(evt.target.result));
}
reader.readAsArrayBuffer(file);
6)修改文件内容:
使用FileWriter类可以修改文件的内容。首先使用FileEntry.createWriter()方法返回一个FileWriter实例,然后就可以应用该类的方法和属性。FileWriter类的属性见下表:
属性 |
功能描述 |
数据类型 |
readyState |
其值为以下3个字符串之一:INIT、WRITING、DONE |
DOMString |
fileName |
要写入的文件的文件名 |
DOMString |
length |
要写入内容的长度 |
long |
position |
当前的位置指针 |
long |
error |
包含错误信息的对象 |
FileError |
onwritestart |
当开始写时被调用 |
Function |
onprogress |
正在写文件时被调用,反馈写入进度(当前未支持) |
Function |
onwrite |
当请求成功完成后被调用 |
Function |
onabort |
当终止写文件时被调用,如调用abort方法 |
Function |
onerror |
当发生错误时被调用 |
Function |
onwriteend |
当请求完成后调用,成功或失败都会调用 |
Function |
FileWriter对象可调用的方法见下表:
方法 |
功能描述 |
abort() |
终止写文件 |
seek() |
移动文件指针到指定位置 |
truncate() |
按照指定长度截断文件 |
write() |
向文件中写数据 |
⑴使用seek方法的示例代码:
function onSuccess(write){
writer.seek(writer.length); //将文件指针快速指向文件尾
}
function onError(error){
alert(error.code);
}
entry.createWriter(onSuccess,onError);
⑵使用truncate方法的示例代码:
function onSuccess(write){
writer.truncate(10); //从指针10处截断
}
function onError(error){
alert(error.code);
}
entry.createWriter(onSuccess,onError);
⑶使用write方法的示例代码:
function onSuccess(write){
writer.onwrite=function(evt){
console.log("成功写入");
};
writer.write("some sample text");
}
function onError(error){
console.log(error.code);
}
entry.createWriter(onSuccess,onError);
⑷向文件追加数据的示例代码:
function onSuccess(write){
writer.onwrite=function(evt){
console.log("成功写入");
};
writer.seek(writer.length); //将文件指针快速指向文件结尾
writer.write("appended text"); //然后写入
}
function onError(error){
console.log(error.code);
}
entry.createWriter(onSuccess,onError);
7)文件切割:
使用slice()方法可以根据内容索引位置切割文件,并将这两个索引位置之间的数据作为一个新的File对象返回。语法格式:
oFileEntry.slice(start,end);
其中,参数start是起始索引,负值表示文档末尾;参数end是结束索引,负值表示文档末尾。两个参数都是相对于当前切割索引位置而言,示例:
var slice1=file.slice(100,400); //当前切割索引位置是100
var slice2=slice1.slice(20,35); //等同于file.slice(120,135);
8)出错处理:
当文件操作发生错误时,会调用回调函数,并传递一个FileError对象作为参数,该对象可以使用属性code返回出错代码,属性值可以是下面的常量之一:
常量 |
值 |
描述 |
FileError.NOT_FOUND_ERR |
1 |
指定的文件或目录不存在 |
FileError.SECURITY_ERR |
2 |
没有访问权限 |
FileError.ABORT_ERR |
3 |
用户终止了操作 |
FileError.NOT_READABLE_ERR |
4 |
指定的文件或目录不能被读取 |
FileError.ENCODING_ERR |
5 |
路径或者URL不正确 |
FileError.NO_MODIFICATION_ALLOWED_ERR |
6 |
指定的文件或者目录不能被修改 |
FileError.INVALID_STATE_ERR |
7 |
操作必须依赖一个对象状态,但在操作中对象状态发生了改变 |
FileError.SYNTAX_ERR |
8 |
语法错误 |
FileError.INVALID_MODIFICATION_ERR |
9 |
对文件系统的修改不合法,如试图将一个目录移动到它的子目录中 |
FileError.QUOTA_EXCEEDED_ERR |
10 |
当要存储的内容超出应用程序存储容量最大限定值时 |
FileError.TYPE_MISMATCH_ERR |
11 |
当你设法获取一个文件或目录的引用,却发现文件系统类型不对,如获取DirectoryEntry得到FileEntry |
FileError.PATH_EXISTS_ERR |
12 |
不能创建指定的目录或文件,因为它们已经存在 |
11.文件的上传和下载:
使用PhoneGap的文件传输插件可以实现文件的上传和下载,使用前需要安装:
cordova plugin add org.apache.cordova.file-transfer
安装了插件就可以使用相关API。文件传输插件有FileTransfer类,可以实现文件上传和下载的管理,使用方法:
var ft=new FileTransfer();
config.xml文件中配置:
<feature name="FileTransfer"><param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer" /></feature>
AndroidManifest.xml中配置:
<uses-permission android:name="android.peimission.WRITE_EXTERNAL_STORAGE" />
1)文件的上传和接收:
使用FileTransfer.upload()方法可以上传文件到服务器,它使用HTTP multi-part POST请求向服务端上传文件,并且支持HTTP以及HTTPS协议。语法格式:
oFileTransfer.upload(fileURI,serverURI,onSuccess,onError,options,trustAllHosts);
其中,参数fileURI指定要上传的文件的URI地址;参数serverURI指定服务器目标地址;参数onSuccess定义一个回调函数,上传成功执行后就调用这个函数,并传递一个FileUploadResult对象作为参数。FileUploadResult对象包含如下属性:
属性 |
功能 |
数据类型 |
bytesSend |
上传文件时向服务器所发送的字节数 |
Number |
responseCode |
服务器端返回的HTTP响应代码 |
DOMString |
response |
服务器端返回的HTTP响应 |
DOMString |
参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileTransferError对象作为参数。FileTransferError对象包含以下几个属性:
·code属性:其值可以是下面的常量之一。
属性 |
功能 |
FileTransferError.FILE_NOT_FOUND_ERR |
表示上传的文件不存在 |
FileTransferError.INVALID_URL_ERR |
表示服务器目标地址不正确 |
FileTransferError.CONNECTION_ERR |
表示连接错误 |
FileTransferError.ABORT_ERR |
表示操作被中断 |
·source属性:表示出错源文件的URI地址
·target属性:表示目标URI
·http_status属性:表示HTTP状态码
参数options是一个FileUploadOptions对象,用于设置上传的功能项。FileUploadOptions对象可以定义如下属性:
属性 |
功能描述 |
数据类型 |
fileKey |
FileTransfer类模拟HTML表单的文件控件来进行上传操作,所以要模拟一个文件控件name属性,fileKey就用来指定name属性值,默认为file |
DOMString |
fileName |
指定文件上传到服务器后所使用的文件名,如果未指定,默认值为image.jpg |
DOMString |
mimeType |
指定上传文件所使用的MINE类型,如果没有指定,默认值为image/jpeg |
DOMString |
params |
指定通过HTTP请求发送到服务器的一系列“键/值”对所组成的集合,等同于使用HTML表单控件来上传信息时与文件同时上传的其他表单控件 |
Object |
chunkedMode |
指定是否采取分块上传模式,默认值为true |
Boolean |
headers |
定义一组HTTP报头 |
Object |
参数trustAllHosts可选,默认值false,如果设为true则表示接受所有类型的安全证书。因为Android不能接受自签名的证书,当测试程序时此功能有用,不推荐在最终产品中设置该参数为true。
2)文件下载:
使用FileTransfer.download()方法可以从远端下载文件,语法格式:
oFileTransfer,download(fileURI,target,onSuccess,onError,trustAllHosts,options);
其中,参数fileURI指定要下载的文件的URI地址,地址必须使用encodeURI()编码;参数target指定文件下载到本地保存的位置及文件名;参数onSuccess定义一个回调函数,成功执行后就调用这个函数,并传递一个FileEntry对象作为参数;参数onError定义一个回调函数,当该方法执行出现错误后就调用这个回调函数,并传递一个FileTransferError对象作为参数;参数trustAllHosts可选,默认值为false,如果设为true表示接受所有类型的安全证书;参数options是一个Object,仅可以定义headers属性,该属性可以设置一组HTTP请求报头用于验证,例如基本验证报头。示例:
var fileTransfer=new FileTransfer();
var uri=encodeURI("http://some.server.com/download.php");
fileTransfer.download(uri,filePath,
function(entry){
console.log("download complete:"+entry.fullPath);
},
function(err){
console.log("download error source:"+err.source);
console.log("download error target:"+err.target);
console.log("download error code:"+err.code);
}
);
3)中断操作:
使用FileTransfer.abort()可以中断正在进行的上传或下载操作,语法格式为:
oFileTransfer.abort();
当执行该方法后,FileTransfer.download()方法或FileTransfer.upload()方法就会触发失败回调函数,并且回调函数的参数FileTransferError对象的code属性值是常量FileTransferError.ABORT_ERR。
12.建立网络应用程序:
要开发网络应用,就必须首先侦测网络连接,不但要侦测网络是否处于连接状态,还要侦测网络连接的类型,比较典型的连接类型包括WIFI、2G、3G、4G和以太网。一旦连接确定后,就可以有针对性地开发网络应用,常用的操作就是下载数据和上传数据。
使用PhoneGap网络连接插件可以获得网络连接信息,使用前需要安装插件:
cordova plugin add org.apache.cordova.network-information
config.xml文件中配置:
<feature name="Device"><param name="android-package" value="org.apache.cordova.networkinformation.NetworkManager" /></feature>
AndroidManifest.xml中配置:
<uses-permission android:name="android.peimission.ACCESS_NETWORK_STATE" />
1)侦测网络连接:
使用online和offline事件来获取程序是否在线信息,而后可以作出相应的操作:
online |
当程序在线时触发该事件 |
offline |
当程序离线时触发该事件 |
当网络在线时触发online事件,当程序离线时触发offline事件。
document.addEventListener("online",onCallbackFunction,false);
document.addEventListener("offline",onCallbackFunction,false);
2)判定连接状态:
使用连接插件的Connection类的type属性可以判断当前设备的网络连接类型。W3C的Network Information API规范规定了navigator.connection类可以返回Connection的一个实例,也就是可以使用下面的方法访问type的属性:
navigator.connection.type
返回值对应下面的几个常量,分别表示不同类型:
Connection.UNKNOWN | Connection.ETHERNET | Connection.Wi-Fi | Connection.NONE |
Connection.CELL_2G | Connection.CELL_3G | Connection.CELL_4G |
13.地理位置定位:
当用户启动使用位置定位的应用程序时,应用程序会收集获取用户的位置信息,不同设备获取位置信息的方式也不同。个人计算机的IP地址、个人计算机周围WIFI热点的IP地址、手机蜂窝电话的无线基站的相关数据都是可以获取的。应用程序获取这些数据后把这些数据发送给默认的位置定位服务提供商,由它来计算用户的位置,最后用户的位置信息就在网站上被计算出来。
许多手机也有GPS功能,返回的是一个经纬度数据,也可以将这个数据发送给位置定位服务提供者;还有一种AGPS功能,可以利用手机基站资讯配合传统GPS卫星,让定位速度更快。当用户到了室内,或者搭乘地铁时,GPS就无法使用了,因为无法搜索到GPS卫星信号。
新的浏览器都支持W3C的Geolocation,通过内置的Geolocation API可以非常方便地查询用户的地理位置,并且可在程序中使用。PhoneGap为不支持W3C的Geolocation的设备提供插件:
cordova plugin add org.apache.cordova.geolocation
一旦安装了插件,就可以使用其API,用window.navigator对象来访问地理位置信息。
config.xml文件中配置:
<feature name="Geolocation"><param name="android-package" value="org.apache.cordova.geolocation.GeoBroker" /></feature>
1)获取Geolocation对象:
使用window.navigator.geolocation可以获取Geolocation对象,不支持地理位置定位的应用程序并不包含这一对象,因此在使用前应检测是否支持该功能。检测代码:
if(window.navigator.geolocation){
//应用程序支持地理位置定位,然后可以进行下一步操作
}else{
alert('你的应用程序不支持地理位置定位!');
}
在 访问Geolocation对象的API时,应用程序会弹出提示,询问用户是否允许网站访问你的位置信息,只有在得到用户许可后才会继续,否则将被停止。当用户拒绝时,使用Geolocation API也能够捕获到用户拒绝服务的行为。
要在程序中应用Geolocation,还必须授予必要的权限,AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
2)获取当前地理位置:
在获得用户许可后,就可以使用Geolocation.getCurrentPosition()方法来获取用户的位置信息,语法格式为:
oGeolocation.getCurrentPosition(successCallback[,errorCallback[,options]]);
其中,参数successCallback是一个回调函数,当成功获取位置信息后就执行该函数,回调函数包含Position对象为函数的参数,其中包含了用户的位置信息;参数errorCallback也是一个回调函数,当用户拒绝时,或者获取位置信息出错时就执行该函数,函数包含一个PositionError对象为参数,其中包含出错信息;参数options定义配置项。示例:
function onDeviceReady(){
if(window.navigator.geolocation){
var geolocation=window.navigator.geolocation;
geolocation.getCurrentPosition(getPositionSuccess,getPositionError);
}else{
alert('你的应用程序不支持地理位置定位!');
}
}
3)处理位置信息:
当成功获取位置信息后会返回一个Position对象,作为回调函数的参数传进来,该对象包含了用户的位置信息。该对象包含一个coords属性,该属性的返回值是一个Coordinates对象,包含了地理位置坐标。
Coordinates对象的属性有:
latitude |
获取纬度 |
longitude |
获取经度 |
altitude |
获取海拔高度 |
accuracy |
获取纬度和经度的精确度,误差单位为米 |
altitudeAccuracy |
获取海拔高度的精确度,误差单位为米 |
heading |
获取移动设备运动的方向,但为度,参照北向顺时针,范围0~360 |
speed |
获取移动设备移动的速度 |
Position对象也包括一个timestamp属性,可以返回获取位置信息所花费的时间。示例:
function getPositionSuccess(position){
var lat=position.coords.latitude; //读取经度
var lon=position.coords.longitude; //读取纬度
alert("你所在的位置:经度"+lat+", 纬度"+lon);
}
4)出错处理:
当用户拒绝时,或者获取位置信息出错时,就可以执行Geolocation.getCurrentPosition()方法的出错回调函数,出错回调函数声明了一个PositionError对象作为该函数的参数,该对象包含了出错信息。出错代码可以使用code属性获取,用3个常量表示出错原因:
PERMISSION_DENIED |
表示用户拒绝了位置服务,或者浏览器设置为不允许使用 |
POSITION_UNAVAILABLE |
表示位置不可知 |
TIMEOUT |
表示获取信息超时 |
示例:
function getPositionError(err){
switch(err.code){
case PositionError.TIMEOUT:
alert("连接超时,请重试");
break;
case PositionError.PERMISSION_DENIED:
alert("你拒绝了使用位置共享服务");
break;
case PositionError.POSITION_UNAVAILABLE:
alert("无法提供位置服务");
break;
}
alert('code:'+err.code+'\n'+'message:'+err.message+'\n');
}
5)配置项:
Geolocation.getCurrentPosition()方法的第3个参数是一个对象,定义了获取位置时的一些配置。该对象定义了3个属性:
·enableHightAccuracy:告知应用程序是否获取高精度结果,默认值为true。当该属性为true时,应用程序尝试启用高精度设备。
·maximumAge:定义一个毫秒数,也就是缓存位置的时间,如果缓存的时间小于该属性的值就使用缓存位置,否则使用最新的位置。设置为0,永远使用最新位置,是默认值。
·timeout:定义最大超时,默认无穷大。如果获取位置信息时超出设定的这个时长,将会触发错误,捕获错误的函数将被调用,并且错误码指向TIMEOUT。
示例:
var geolocation=window.navigator.geolocation;
geolocation.getCurrentPosition(getPositionSuccess,getPositionError,
{enableHighAccuracy:false,timeout:5000});
6)持续追踪位置:
对于使用移动设备的用户来说,位置并不是固定的,使用Geolocation.watchPosition()方法可以跟踪设备的位置。每一次位置的变化,就获取一次设备的位置,都会执行successCallback回调函数;如果出现错误,就会执行用于处理错误的errorCallback回调函数。语法格式:
var watchID=oGeolocation.watchPosition(successCallback[,errorCallback[,options]];
其中参数的功能与Geolocation.getCurrentPosition()方法相同,但该方法可以返回一个监控id,但不需要再进行跟踪时,可以使用clearWatch()方法根据该id停止追踪。语法格式:
Geolocation.clearWatch(watchId);
14. 重力感应器:
重力感应,是指对地球的重力方向的感知。由于重力就是地球自身产生的加速度,因此重力感应器也被称为重力加速计。目前设备广泛采用的加速计是三轴加速计,分为X轴、Y轴和Z轴,这三个轴所构成的立体空间足以侦测用户在设备上的各种动作。使用重力感应器需要安装插件:
cordova plugin add org.apache.cordova.device-motion
一旦安装了插件,就可以使用其API,用window.navigator对象来访问。使用PhoneGap插件的Accelerometer类提供的方法可以检测设备重力感应器返回的数据,它可以动态捕获设备当前加速度的偏移量,即三维空间中x、y、z三个方向轴的加速度偏移量,并由此来触发事件。
config.xml文件中配置:
<feature name="Accelerometer"><param name="android-package" value="org.apache.cordova.devicemotion.AccelListener" /></feature>
1)获取当前的加速度偏移量:
accelerometer.getCurrentAcceleration()方法获取当前加速度偏移量,有两个参数,分别是成功后的回调函数和出错后的回调函数。一般情况下,该方法都应该在PhoneGap完成加载后调用。示例:
function onSuccess(acceleration){
alert('Acceleration X: '+acceleration.x+'\n'+'Acceleration Y: '+acceleration.y+'\n'+
'Acceleration Z: '+acceleration.z+'\n'+'Timestamp: '++acceleration.timestamp+'\n');
}
function onError(){
alert('onError!');
};
//PhoneGap完成加载
function onDeviceReady(){
navigator.accelerometer.getCurrentAcceleration(onSuccess,onError);
}
网页中要使用<body onload="onLoaded()">,而在onLoaded()函数中加入deviceready事件监听器。
2)acceleration对象属性:
监听方法会返回一个acceleration对象,该对象包含一个特殊时间点捕获的加速度偏移量数据,包含以下几个属性:
属性 |
功能描述 |
x |
x轴的偏移量(Number类型) |
y |
y轴的偏移量(Number类型) |
z |
z轴的偏移量(Number类型) |
timestamp |
以ms为单位的时间戳,表示捕捉到的时间 |
属性已经考虑了重力加速度的影响,PhoneGap使用的重力加速度值为9.81.当设备水平静止放置时,3个属性值是0、0、9.81;当设备横着垂直静止放置时为9.81、0、0;当设备竖着垂直放置时为0、9.81、0。每个方向都可以有负值,如果设备水平静止放置但屏幕向下,z=-9.81。
不同版本的PhoneGap返回的值可能不一样,一些版本会返回0~1之间的数字。
实际应用时,通常以这三个轴(或任意两个轴)所构成的角度来计算设备倾斜的角度,从而计算出重力加速度的值。正常使用时,重力感应器在任意轴上都不会检测到远大于1g的值,如果摇动设备,重力感应器便会在一个或多个轴上检测到很大的力;如果投掷或坠落,重力感应器便会在一个或多个轴上检测到很小的力。
3)以特定时间间隔获取加速度偏移量:
accelerometer.watchAcceleration()方法可以监控加速度改变,它每隔一定的时间获取一次加速度。每获取一次加速度,都会执行onSuccess回调函数,或者出现错误就会执行onError回调函数。时间间隔可以使用第三个参数设定,第三个参数是一个对象,该对象包含一个属性ferquency,用于以ms为单位指定间隔时间。
该方法返回一个id,可以与accelerometer.clearAcceleration()方法一起使用来终止加速度监控。示例:
var watchID=null;
document.addEventListener('deviceready',onDeviceReady,false);
function onDeviceReady(){
var options={frequency:3000); //每隔3秒获取一次加速度
watchID=navigator.accelerometer.watchAcceleration(onSuccess,onError,options);
}
//可以定义一个操作来调用该函数以结束监控
function stopWatch(){
if(watchID){
navigator.accelerometer.clearAcceleration(watchID);
watchID=null;
}
}
function onSuccess(acceleration){
alert('Acceleration X: '+acceleration.x+'\n'+'Acceleration Y: '+acceleration.y+'\n'+
'Acceleration Z: '+acceleration.z+'\n'+'Timestamp: '++acceleration.timestamp+'\n');
}
function onError(){
alert('onError!');
};
在间隔请求时,PhoneGap将会调用成功回调函数并且传入加速度的结果,但间隔必须最小40ms,最大1000ms。如果请求一个3秒的间隔时间,PhoneGap将会从设备上请求以1秒为间隔获取加速度,但按照请求的3秒时间来调用成功回调函数。
示例:检测握持状态
function checkOrientation(acceleration){
var violence=9.81;
if(Math.abs(acceleration.x)>Math.abs(acceleration.y)){
document.getElementById("tip").value="横屏";
}else{
document.getElementById("tip").value="竖屏";
}
}
15.电子罗盘:
很多手机有电子罗盘传感器,也称为电子指南针,根据地球的磁场来确定方向。PhoneGap使用电子罗盘要安装插件:
cordova plugin add org.apache.cordova.device-orientation
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator对象访问。有3种方法:
·compass.getCurrentHeading():获取当前的朝向
·compass.watchHanding:设置监控,以特定时间间隔获取朝向
·commpass.clearWatch:清除监控设置
语法格式为:
navigator.compass.getCurrentHeading(compassSuccess,compassError,compassOptions);
var wchID=navigator.compass.watchHeading(compassSuccess,compassError,[compassOptions]);
navigator.compass.clearHeading(wchID);
这三种方法与运动传感器的3种方法使用完全一致,只是返回一个compassHeading对象,该对象包含了朝向信息。
config.xml文件中配置:
<feature name="Compass"><param name="android-package" value="org.apache.cordova.deviceorientation.CompassListener" /></feature>
AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
1)成功回调函数:
function onSuccess(compassHeading){
//处理代码
}
成功回调函数会返回一个compassHeading对象,该对象包含一个捕获的朝向数据,它包含几个属性:
magneticHeading |
当前朝向,是一个0~359.99的数字 |
trueHeading |
相对于北极点的朝向,是一个0~359.99的数字,负值表示不能确定 |
headingAccuracy |
表示当前朝向与trueHeading之间的偏差 |
timestamp |
以ms为单位的时间戳,表示捕捉到的时间 |
Android环境下,不支持trueHeading,与magneticHeading返回相同的值,而headingAccuracy总是返回0。
2)失败回调函数:
监控失败的回调函数有一个参数error:
function onError(error){
//处理代码
}
Error中有一个code属性,该属性值可以是如下常量之一,表示出错原因:
·CompassError.COMPASS_INTERNAL_ERR:表示内部错误
·CompassError.COMPASS_NOT_SUPPORTED:表示不支持
16.管理手机通讯录:
使用PhoneGap的API管理手机内置的通讯录数据库来创建、删除、更新联系人,也可以查询联系人。通讯录插件需要安装:
cordova plugin add org.apache.cordova.contacts
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator对象访问。
PhoneGap将一个联系人使用一个Contact对象表示,该对象包含联系人的各种信息字段,如姓名、地址、电话等,每个信息字段就是Contact对象的一个属性。
config.xml文件中配置:
<feature name="Contacts"><param name="android-package" value="org.apache.cordova.contacts.ContactManager" /></feature>
AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
1)联系人信息字段:
Contact对象包含了一些属性用于描述该联系人的信息,通过更改或者读取这些属性就可以管理联系人。属性见下表:
属性 |
功能描述 |
数据类型 |
id |
标识该联系人的全局唯一id标识 |
DOMString |
displayname |
联系人名称(昵称) |
DOMString |
name |
包含联系人个人全名的一个对象 |
ContactName |
nickname |
联系人昵称 |
DOMString |
phoneNumber |
包含联系人全部联系电话号码的数组 |
ContactField[] |
emails |
包含联系人全部E-mail地址的数组 |
ContactField[] |
address |
包含联系人全部联系地址的数组 |
ContactAddresses[] |
ims |
包含联系人全部IM地址的数组 |
ContactField[] |
organizations |
包含联系人所属全部组织的数组 |
ContactOrganization[] |
revision |
联系人数据最后一次更新的时间 |
DOMString |
birthday |
联系人生日 |
Date |
gender |
联系人性别 |
DOMString |
note |
联系人的说明 |
DOMString |
photos |
联系人头像的数组,可以定义多个头像 |
ContactField[] |
categories |
放置联系人所属类别的数组,一个联系人可分属多个分组 |
ContactField[] |
urls |
放置与联系人相关网址的数组 |
ContactField[] |
timezone |
联系人所属时区 |
DOMString |
并不是所有平台都支持以上所列的字段,而且随平台版本也有差别。
使用Contact对象公开的属性和方法,可以处理联系人信息,一个Contact对象代表一个联系人。Contact对象可以从设备通讯录数据库中被建立、存储或者删除,同样可以使用contacts. find方法从数据库中检索出Contact对象。一旦获得了对Contact对象的引用,就可以使用Contact公开的属性和方法处理该联系人。
2)联系人信息字段所使用的复杂数据类型:
联系人信息某些字段使用的数据类型是一些复杂数据类型,是一些对象,包括ContactField、ContactName、ContactAddress和ContactOrganization。
⑴ContactField:
该对象表示在Contact对象中使用的通用字段,一些属性,如email、phone、url,使用ContactField对象存储。该对象包含的属性见下表:
属性 |
功能描述 |
数据类型 |
type |
说明字段类型的字符串 |
DOMString |
value |
字段的值,如电话号码或者E-mail地址 |
DOMString |
pref |
如果自定义字段包含用户偏好设置,这个字段用设为true |
Boolean |
大多数情况下,一个ContactField对象中type属性的值并不能预先确定,比如电话号码可能有home、work、iphone类型值。对通讯录头像,type字段指示图片的格式,URL指示value字段中是一个指向图片的URL地址,而base64则指示value字段内包含经base64编码的图片数据。Android和iOS都不支持pref属性,总返回false。
⑵ContactName:
是通讯录中存储联系人姓名的对象,该对象可以使用的属性见下表:
属性 |
功能描述 |
数据类型 |
formatted |
联系人全名 |
DOMString |
familyName |
联系人的姓氏 |
DOMString |
givenName |
联系人的名字 |
DOMString |
middleName |
联系人的中间名 |
DOMString |
honorificPrefix |
联系人称呼前缀,如Mr. |
DOMString |
honorificSuffix |
联系人的名字后缀,如Esq.和PhD. |
DOMString |
Android可以读取formatted字段,将返回后面5个字段的连接字符串作为结果,但不会存储该属性的值。
⑶ContactAddress:
表示Contact对象的一个address,每个Contact对象可以包含多个ContactAddress,每个ContactAddress可以使用下述属性描述:
属性 |
功能描述 |
数据类型 |
pref |
如果ContactAddress是用户偏好设置,那么就设置为true |
Boolean |
type |
字段类型,例如home |
DOMString |
formatted |
全地址格式显示 |
DOMString |
streeAddress |
全街道地址显示 |
DOMString |
locality |
城市或区域 |
DOMString |
region |
地区或国家 |
DOMString |
postalCode |
邮政编码 |
DOMString |
country |
国家名称 |
DOMString |
iOS不支持formatted属性。
⑷ContactOrganization:
该对象用于存储联系人所属组织的属性,一个联系人对象可以在数组中存储一个或多个ContactOrganization对象。该对象可以使用的属性见下表:
属性 |
功能描述 |
数据类型 |
pref |
如果ContactAddress是用户偏好设置,那么就设置为true |
Boolean |
name |
字段类型,例如home |
DOMString |
name |
组织名称 |
DOMString |
department |
联系人工作的部门 |
DOMString |
title |
联系人在组织内的头衔 |
DOMString |
Android不支持title属性。
3)创建一个新的联系人:
使用contacts.create()方法可以创建一个新的联系人,该方法同时返回一个新的Contact对象。语法格式为:
var contact=navigator.service.contacts.create([properties]);
其中,参数properties是可选的,指定一个Object,该对象包含有描述该联系人的信息。如果省略该参数,那么可以在返回Contact对象后使用属性添加这些信息。示例:
var ocontact=navigator.contacts.create("displayName":"张三","gender":"男");
但是,该方法不会立即更新设备上的通讯录数据库,需要调用Contact.save()方法才能更新,save()方法包含onSuccess、onError两个回调函数为参数。
4)查询联系人:
使用contacts.find()方法可以查询设备通讯录数据库,返回一个或多个Contact对象。一个Contact对象表示一个联系人,其字段包含指定的联系人信息字段。返回的Contact对象会作为参数传递给回调函数contactSuccess。语法格式为:
navigator.contacts.find(contactFields,contactSuccess,contactError,contactFindOptions);;
其中,参数contactFields定义搜索限定词,也就是联系人的信息字段,在返回的Contact对象中仅包含这些指定的信息字段;参数contactSuccess定义一个回调函数,当从通讯录数据库中成功返回Contact对象时调用该函数,并将Contact对象数组作为参数传递给该回调函数;参数cantactError定义一个回调函数,当发生错误时调用此函数;参数contactFindOptions定义过滤通讯录的搜索选项,这是一个Object,包含很多属性,每个属性定义一些过滤特征。
示例:
function onSuccess(contacts){
alert('共有'+contacts.length+'联系人符合查询条件');
};
function onError(){
alert('查询操作出错!');
}
var options=new ContactFindOptions();
options.filter="Bob";
var fields=["displayName","name"]; //结果中包含这两个信息字段
navigator.contacts.find(fields,onSuccess,onError,options);
必须在参数contactFields中指定通讯录中的信息字段以作为搜索限定词,只有在contactFields参数中指定的信息字段才会传递给回调函数,这些信息字段将作为Contact对象的属性出现。该参数是一个由信息字段字符串作为元素构成的数组,一个0长度的contactFields参数将返回一个只包含id属性的Contact对象数组。在没有符合条件的结果时,iOS返回数组属性为null,其他平台则返回一个空数组。
可以使用参数contactFindOptions中的filter属性指定一个字符串作为查询通讯录数据时的搜索过滤器,如果在任何指定的信息字段中找到能符合过滤器要求的内容,则这个Contact对象会被返回。filter属性的值不区分大小写,匹配部分值的规则应用到contactFields参数的每个字段。如果使用了这个参数,例如不区分大小匹配部分值这些规则可以用到contactFields参数中所指定的每个字段上。
contactFindOption是用于对contacts.find的返回结果进行过滤操作,是一个Object,包括属性见下表:
属性 |
功能描述 |
数据类型 |
filter |
用于搜索通讯录的搜索字符串,默认值为空字符串 |
DOMString |
multiple |
确定查找操作是否可以返回多条通讯录的内容,默认值为ture |
Boolean |
updatedSince |
返回自指定日期之后更新内容的通讯录,默认为空字符串 |
Date |
Android平台不支持updatedSince属性。
5)克隆联系人:
使用Contact.clone()方法可以克隆一个Contact对象,返回Contact对象的一个副本。这个克隆是一个深度克隆,字段及其值完全相同,只是id属性被设置为null。该方法没有参数,示例:
var clone=oContact.clone();
clone.name.givenName="John";
console.log("原有名字="+oContact.name.givenName);
console.log("副本名字="+clone.name.givenName);
6)删除联系人:
使用Contact.remove()方法可以从通讯录数据库中删除某个联系人。该方法的语法格式为:
oContact.remove(onSuccess,onError);
如果删除操作成功,就会调用回调函数onSuccess,这个回调函数没有参数。如果删除操作没有成功,就会调用出错回调函数onError,并将ContactError对象作为参数传递给回调函数。
示例:
function onSuccess(){
alert("删除操作成功");
}
function onError(contactError){
alert("删除操作失败="+contactError.code);
};
oContact.remove(onSuccess,onError);
7)保存联系人:
使用Contact.save()方法可以将一个新联系人存储到通讯录数据库中,如果通讯录数据库中包含有与当前Contact相同id的记录,那么将执行更新操作。语法格式为:
oContact.save(onSuccess,onError);
如果操作成功,就会调用回调函数onSuccess,这个回调函数没有参数。如果操作没有成功,就会调用出错回调函数onError,并将CantactError对象作为参数传递给回调函数。示例:
document.addEventListener("deviceready",onDeviceReady,false);
function onDeviceReady(){
var oContact=navigator.service.contacts.create();
oContact.displayName="李四";
oContact.gender="男";
var name=new ContactName();
name.givenName="元霸";
name.familyName="李";
oContact.name=name;
oContact.save(onSuccess,onError);
}
function onSuccess(contacts){
alert("成功");
}
function onError(contactError){
alert("失败:"+contactError.code);
}
8)出错处理:
当通讯录操作发生错误时,会调用错误处理函数,并传递一个ContactError对象作为参数,该对象可以使用属性code返回出错代码,属性值是下面的常量之一:
ContactError.UNKNOWN_ERROR、ContactError.INVALID_ARGUMENT_ERROR、
ContactError.NOT_FOUND_ERROR、ContactError.TIMEOUT_ERROR、
ContactError.PENDING_OPERATION_ERROR、ContactError.IO_ERROR、
ContactError.NOT_SUPPORTED_ERROR、ContactError.PERMISSION_DENIED_ERROR
17.使用Capture对象采集图片、音频和视频:
要使用Capture媒体捕捉,需要安装插件:
cordova plugin add org.apache.cordova.media-capture
这个插件还依赖于文件系统插件,也需要同时安装。一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator对象访问。capture对象可以从设备照相机获取图片,capture对象由navigator.device.capture属性获取:
var capture=navigator.device.capture;
使用capture对象不但可以从照相机捕捉画面,还可以录制语音和视频。
config.xml文件中配置:
<feature name="Capture"><param name="android-package" value="org.apache.cordova.mediacapture.Capture" /></feature>
AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO" />
因为这些操作一般都需要进行文件系统操作或使用SD卡,所以一般需要在前面加上相关设置:
config.xml文件中配置:
<feature name="File"><param name="android-package" value="org.apache.cordova.file.FileUtils" /></feature>
AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
1)使用Capture对象从照相机捕捉图片:
⑴检测支持的格式:
使用capture对象的supportedImageModes属性可以检测设备支持的照相图片大小及格式,该属性的返回值是一个由ConfigurationData对象组成的数组。ConfigurationData对象封装了一个设备所支持的多媒体采集参数的集合,包含了MIME类型、采集尺寸信息。MIME类型采用了RFC2046所规定的标准,如video/3gpp、image/jpeg、audio/amr。
ConfigurationData对象包含的属性:
属性 |
功能描述 |
数据类型 |
type |
用小写ASCII编码字符串表示的MIME类型 |
DOMString |
height |
图像高度或者视频的高度,以像素为单位,音频的值为0 |
Number |
width |
图像高度或者视频的宽度,以像素为单位,音频的值为0 |
Number |
示例:
var modes=capture.supportedImageModes;
for(var i in modes){
console.log(modes[i].type+":"+modes[i].height);
}
⑵捕捉照片:
使用capture.captureImage()方法可以启用照相程序捕捉图片,并且返回采集到的图像文件。语法格式:
navigator.device.capture.captureImage(captureSuccess,captureError[,captureOptions]);
这个方法用异步的方式启动设备的照相程序以采集图片,并允许设备使用者一次捕捉多张图片。当用户退出照相程序或者采集数达到上限时,采集动作会自动结束。可以通过指定参数CaptureImageOptions的limit属性来修改最大录制数。如果没有设置此参数,那么默认值为1。
当采集操作完成后,该方法会调用回调函数captureSuccess,该函数的参数为MediaFile对象数组;如果在采集到一个图片之前就结束了操作,那么回调函数captureError将被调用,该函数的参数为CaptureError对象,返回的错误代码为CaptureError.CAPTURE_NO_MEDIA _FILES。
参数captureOptions是一个Object,CaptureImageOptions类型,包含的属性有:
属性 |
功能描述 |
limit |
指定在一个会话期间能够捕捉的最多图片数量,默认为1 |
mode |
指定图形模式,值必须与ConfigurationData的type属性值匹配 |
Android平台不支持参数mode,只能保存为jpeg格式(image/jpeg),但图片大小可以通过用户进行改变;iOS对2个属性都不支持。
⑶处理捕捉的照片:
当捕捉成功后会调用指定的captureSuccess回调函数,该回调函数有一个参数mediaFiles,它是一组MediaFile。示例代码:
function captureSuccess(mediaFiles){
var len=mediaFiles.length; //获取mediaFiles元素数量
for(var i=0;i<len;i++){ //遍历mediaFiles
//使用mediaFiles[i]获取每个MediaFile
}
}
MediaFile封装了一个被采集的多媒体文件的信息,包含的属性有:
属性 |
功能描述 |
数据类型 |
name |
文件的名字,不包含路径 |
DOMString |
fullPath |
文件的全路径名 |
DOMString |
type |
文件的MIME类型 |
DOMString |
lastModifiesDate |
文件的最后修改时间 |
Date |
size |
文件大小,以byte为单位 |
Number |
除此之外,使用MediaFile.getFormatData()方法还可以获取被采集的媒体文件的格式信息。语法格式为:
mediaFile.getFormatData (MediaFileDataSuccessCB successCallback[,MediaFileDataErrorCB errorCallback]);
该方法使用异步方式获得媒体文件的格式,如果成功则调用回调函数successCallback,该回调函数的参数为MediaFileData对象;如果失败,则调用回调函数errorCallback。
MediaFileData对象封装了一个媒体文件的格式信息,包含以下属性:
属性 |
功能描述 |
数据类型 |
codecs |
音频及视频内容的实际格式 |
DOMString |
bitrate |
内容的平均比特率,对图形文件为0 |
Number |
height |
图形或视频以像素为单位的高度,音频剪辑的值为0 |
Number |
width |
图形或视频以像素为单位的宽度,音频剪辑的值为0 |
Number |
duration |
视频或音频剪辑的时长,以s为单位,图形文件的值为0 |
Number |
Android不支持codecs和bitrate属性,iOS不支持codecs属性。
示例:
function captureSuccess(mediaFiles){
var len=mediaFiles.length; //获取mediaFiles元素数量
for(var i=0;i<len;i++){ //遍历mediaFiles
console.log("图片文件URL:"+mediaFiles[i].fullPath);
mediaFiles[i].getFormatData(function(mode){
console.log("图片文件大小:"+mode.width+"x"+mode.height);
}
};
var img=document.createElement('img');
img.setAttribute('src',mediaFiles[i].fullPath);
img.setAttribute('width',100);
img.setAttribute('height',200);
img.style.margin="20px";
document.getElementByTagName('body')[0].appendChild(img);
}
}
function captureError(err){
if(CaptureError.CAPTURE_NO_MEDIA_FILES==err.code){
alert("已经取消拍照!");
}else{
alert("captureError: "+err.code);
}
}
function onDeviceReady(){
navigator.device.capture.captureImage(captureSuccess,captureError,{limit:3});
}
⑷出错处理:
当捕捉失败后就会调用指定的失败回调函数,并传递一个CaptureError对象作为参数,该对象可以使用属性code返回出错代码,属性值可以是下面的常量之一:
常量 |
描述 |
CaptureError.CAPTURE_INTERNAL_ERR |
表示照相机或者麦克风捕捉图片或声音失败 |
CaptureError.CAPTURE_APPLICATION_BUSY |
表示照相机或者麦克风应用程序当前正被其他程序使用 |
CaptureError.CAPTURE_INVALID_ARGUMENT |
表示不正确的API调用,可能是缺失参数或参数不正确 |
CaptureError.CAPTURE_NO_MEDIA_FILES |
表示用户在捕捉之前退出了照相机或者麦克风应用程序 |
CaptureError.CAPTURE_NOT_SUPPORTED |
表示当前的请求不被支持 |
2)录制音频:
capture对象功能很强,还可以用来录制语音和视频。
⑴使用属性检测支持的格式:
capture对象有3个属性用于检测格式:
属性 |
功能描述 |
supportedAudioModes |
返回设备支持的录音格式 |
supportedImageModes |
返回设备支持的照相图片大小及格式 |
supportedVideoModes |
返回设备支持录像的分辨率格式 |
使用capture对象的supportedAudioModes属性可以检测设备支持的录音音频格式,使用capture对象的supportedVideoModes属性可以检测设备支持的录像的分辨率及格式。
这三个属性返回的都是ConfigurationData对象,该对象封装了一个设备所支持的多媒体参数集合,包含了MIME类型、采集尺寸(对视频、图像)信息。MIME类型采用了RFC2046所规定的标准,比如:video/3gpp、image/jpeg、audio/amr。
ConfigurationData对象包含的属性:
属性 |
功能描述 |
数据类型 |
type |
用小写ASCII编码字符串表示的MIME类型 |
DOMString |
height |
图形或视频以像素为单位的高度,音频剪辑的值为0 |
Number |
width |
图形或视频以像素为单位的宽度,音频剪辑的值为0 |
Number |
但目前的平台并不支持height和width属性。
⑵录音:
使用capture.captureAudio()方法可以录音,并最终返回采集到的音频剪辑文件。语法:
navigator.device.capture.captureAudio(captureSuccess,captureError[,captureOptions]);
该方法使用异步的方式通过设备默认的音频录制程序采集音频,并允许设备使用者可以一次采集多个文件。当用户退出音频录制程序或者录制数达到上限时,采集动作会自动结束。可以通过指定参数CaptureAudioOptions的limit属性来修改最大录制数,默认值为1。
当采集操作完成后,会自动调用回调函数captureSuccess,该函数的参数为MediaFile对象数组。每个MediaFile对象都表明了一个被采集到的媒体文件。如果在采集到一个音频剪辑之前用户就结束了操作,那么回调函数captureError将被调用,返回的错误代码可以通过error. code属性访问。示例:
function captureSuccess(mediaFiles){
var len=mediaFiles.length;
for(var i=0;i<len;i++){
console.log("音频文件URI:"+mediaFiles[i].fullPath);
mediaFiles[i].getFormatData(function(mode){
console.log("音频文件属性:["+mode.codecs+"]["
+mode.bitrate+"]["+mode.duration+"]");
});
var audio=document.createElement('audio');
audio.setAttribute('src',mediaFiles[i].fullPath);
audio.setAttribute('control','controls');
audio.style.margin="10px";
document.getElementByTagName('body')[0].appendChild(audio);
}
}
function captureError(err){
if(CaptureError.CAPTURE_NO_MEDIA_FILES==err.code){
alert("已经取消录制!");
}else{
alert("captureError:"+err.code);
}
}
function onDeviceReadyt(){
navigator.device.capture.captureAudio(captureSuccess,captureError,{limit:3});
}
⑶参数CaptureAudioOptions:
参数captureOptions封装音频采集的配置选项,有几个属性:
属性 |
功能描述 |
limit |
指定在一个会话期间能够录制的最多音频剪辑数量,默认为1 |
duration |
指定一个音频剪辑的最长时间,以s为单位 |
mode |
指定音频模式,值必须与capture.supportedAudioModes返回值中的type属性值匹配 |
Android平台不支持duration和mode,录音编码格式使用自适应多速率格式AMR,MIME类型为audio/amr;iOS对3个属性都不支持。
3)录制视频:
使用capture.captureVideo()方法可以开启默认的录像应用程序,并且返回采集到的视频剪辑文件的相关信息。语法格式:
navigator.device.capture.captureVideo(captureSuccess,captureError[,captureOptions]);
该方法用异步的方式启动设备的视频录像程序以采集视频,并允许设备使用者一次捕捉多个视频片段。当用户退出视频录制程序或者录制数达到上限时,采集动作会自动结束。可以通过指定参数captureOptions的limit属性来修改最大录制数。如果没有设置此参数,那么默认值为1。
参数captureOptions封装视频采集的配置选项,有几个属性:
属性 |
功能描述 |
limit |
指定在一个会话期间能够录制的最多视频剪辑数量,默认为1 |
duration |
指定一个视频剪辑的最长时间,以s为单位 |
mode |
指定视频模式,值必须与capture.supportedVideoModes返回值中的type属性值匹配 |
Android平台不支持duration和mode,iOS对3个属性都不支持。
示例:
function captureSuccess(mediaFiles){
var len=mediaFiles.length;
for(var i=0;i<len;i++){
console.log("视频文件URI:"+mediaFiles[i].fullPath);
mediaFiles[i].getFormatData(function(mode){
console.log("视频文件属性:["+mode.codecs+"]["
+mode.bitrate+"]["+mode.duration+"]");
});
var video=document.createElement('video');
video.setAttribute('src',mediaFiles[i].fullPath);
video.setAttribute('control','controls');
video.setAttribute('width',240);
video.setAttribute('height',180);
video.style.margin="10px";
document.getElementByTagName('body')[0].appendChild(video);
}
}
function captureError(err){
if(CaptureError.CAPTURE_NO_MEDIA_FILES==err.code){
alert("已经取消录制!");
}else{
alert("captureError:"+err.code);
}
}
function onDeviceReadyt(){
navigator.device.capture.captureVideo(captureSuccess,captureError,{limit:3});
}
18.摄像头的Camera对象的使用:
PhoneGap有一个camera类,使用该类可以从照相机或相册库获取图片,使用前需要安装插件:
cordova plugin add org.apache.cordova.camera
为了使用插件,需要在config.xml文件中进行相关配置:
<feature name="Camera"><param name="android-package" value="org.apache.cordova.camera.CameraLauncher" /></feature>
因为这些操作一般都需要使用SD卡,所以一般需要在AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator.camera对象访问,返回一个Camera类的实例,然后使用camera.getPicture()方法可以从设备照相机获取中频,并且可以从设备上的相册库中获取照片,图片会以base64编码的字符串或者以本地图片路径URI方式返回。语法格式:
navigator.camera.getPicture(onSuccess,onError[,cameraOptions]);
其中,参数onSuccess是执行成功后的回调函数;参数onError是执行失败后的回调函数;参数cameraOptions可选,是一个Object类型,用于定义捕捉选项,该参数可以定义的其中一个名为sourceType属性来确定是从照相机还是相册库获取图像。
如果设置sourceType属性值为默认值Camera.PictureSourceType.CAMERA,可以打开设备默认的camera驱动程序使用户可以拍照,一旦拍照结束,则会关闭设备默认的camera;如果设置sourceType属性值为Camera.PictureSourceType.PHOTOLIBRARY或者Camera. PictureSourceType.SAVEDPHOTOALBUM,则会显示选择图片对话框,用户可以从指定的相册中选择图片。
1)处理图片数据:
当成功获取图片数据后,就会触发onSuccess函数,返回值将被作为参数发送到onSuccess函数。根据用户指定的cameraOptions,返回值为下面几种形式:
·按照base64编码的图片数据
·代表本地存储系统中图片文件位置的路径字符串,例如file:///mnt/sdcard/Android/data/ cn.dwenzhao.helloworld/cache/123456.jpg。
·代表图片内置的URI,Android使用content://前缀
一旦获取到图片数据,将可以对编码过的图片数据或者文件URI进行操作,如使用img元素渲染图片、存储为本地数据、发送数据到服务器端。示例:
navigator.camera.getPicture(onSuccess,onError,{quelity:50,destinationType:Camera.DestinationType.DATA_URL});
function onSuccess(imageData){
var image=document.getElementById('myImage');
image.src="data:image/jpeg;base64."+imageData;
}
或者将从照相机捕捉到的数据保存为文件:
navigator.camera.getPicture(onSuccess,onError,{quelity:50,destinationType:Camera.DestinationType.FILE_URL});
function onSuccess(imageURL){
var image=document.getElementById('myImage');
image.src=imageURL;
}
注意,一些设备上的camera分辨率比较高,如果使用高分辨率拍照,很可能因为使用大图片而导致无法顺利对图片编码,因此推荐使用FILE_URL作为destinationType的值。
2)定义捕捉选项:
参数cameraOptions有一些属性可定义,默认值如下:
{quality:75,destinationType:Camera.DestinationType.DATA_URL,
sourceType:Camera.PictureSourceType.CAMERA,allowEdit:true,
encodingType:Camera.EncodingType.JPEG,targetWidth:100,targetHeight:100,
popoverOptions:CameraPopoverOptions,saveToPhotoAlbum:dalse}
属性quality定义保存图片的质量,取值返回为[0,100],100表示质量高
属性destinationType定义选择返回的数据的格式,取值可以是3种:
·Camera.DestinationType.DATA_URL,表示返回图片作为base64编码字符串
·Camera.DestinationType.FILE_URL,表示返回图片作为文件URL
·Camera.DestinationType.NATIVE_URL,表示返回图片的内置URI,不推荐使用
属性sourceType设置图片来源,可以有3种:
·Camera.PictureSourceType.PHOTOLIBRARY,表示从图片库
·Camera.PictureSourceType.CAMERA,表示从照相机
·Camera.PictureSourceType.SAVEDPHOTOALBUM,表示从保存的相册库
属性allowEdit是一个逻辑值,用于设置在选择图片进行操作之前是否允许对其进行简单的编辑
属性encodingType用于设置返回文件的类型,有以下几个常量:
Camera.EncodingType={JPEG:0,PNG:1);
属性targetWidth用于定义缩放图片的宽度,以像素为单位,必须与targetHeight配合使用,纵横比不会改变
属性targetHeight用于定义缩放图片的高度,以像素为单位,必须与targetWidth配合使用,纵横比不会改变
属性mediaType用于设置从设备图片库中选择媒体文件的类型,仅适用于PictureSourceType为PHOTOLIBRARY或SAVEDPHOTOALBUM的情况下,有几个常量:
Camera.MediaType={PICTURE:0,VIDEO:1,ALLMEDIA:2);
属性correctOrientation用于决定是否旋转图片到正确的设备方向
属性saveToPhotoAlbum用于决定是否在捕捉图片后存放到相册
属性popoverOptions仅用于iOS,用来指定iPad弹出的popover对话框的位置
属性cameraDirection用于指定使用前面摄像头(Camera.Direction.FRONT)还是用背面的摄像头(Camera.Direction.BACK),默认使用后摄像头
Android系统下,会忽略allowEdit参数,Camera.PictureSourceType.PHOTOLIBRARY和Camera. PictureSourceType.SAVEDPHOTOALBUM会显示同一个相册,且将不能识别cameraDirection设置,任何值都会使用背面摄像头。
3)出错处理:
Camera操作一旦出错会调用失败回调函数,并传递一个参数,该参数是一个字符串,包含出错的提示信息。示例:
function onError(message){
alert('操作失败:'+message);
}
4)处理图片:
Camera操作从照相机捕捉到的图片保存到一个缓存目录,因此如果想长期保存图片或者在备份时图片也能备份,必须使用File API移动图片文件到合适的目录。示例:
function onPhotoURISuccess(imageURI){
console.log(imageURI);
var gotFileEntry=function(fileEntry){
console.log("图片文件临时目录路径:"+fileEntry.fullPath);
var copyFileSuccess=function(file){
console.log("图片文件持久目录路径:"+file.fullPath);
var myImage=document.getElementById('myImage');
myImage.style.display='block';
myImage.src=file.fullPath;
};
var gotFileSystem=function(fileSystem){
fileEntry.copyTo(fileSystem.root,null,copyFileSuccess,fillError);
};
window.requestFileSystem(LocalFileSystem.PERSISTENT,0,gotFileSystem,fileError);
};
function fileError(err){
alert("fileError: "+err.code);
}
window.resolveLocalFileSystemURI(imageURI,gotFileEntry,fileError);
}
function capturePhoto(){
navigator.camera.getPicture(onPhotoURISuccess,onPhotoURIError,
{quality:50,destinationType:Camera.DestinationType.FILE_URI});
}
function onPhotoURIError(){
alert('操作失败:"+message);
}
19.使用Media类控制音频播放:
使用PhoneGap媒体控制插件可以控制音频的播放,使用前需要安装:
cordova plugin add org.apache.cordova.media
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator.camera对象访问。
为了使用Media插件,需要在config.xml文件中进行相关配置:
<feature name="Media"><param name="android-package" value="org.apache.cordova.media.AudioHandler" /></feature>
还需要在AndroidManifest.xml中添加授权:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
为了使用Media类实现录音功能和对音频的播放控制,要先创建一个Media实例,语法格式:
var media=new Media(src[,mediaSuccess[,mediaError[,mediaStatus]]]);
其中,参数src指定要播放的音频文件,考虑到兼容性,通常应是一个MP3或AAC编码文件;参数mediaSuccess可选,指定一个回调函数,当Media对象播放完成,或者录制结束,或者停止播放时就会调用该函数;参数mediaError可选,指定一个回调函数,当Media对象的操作出现错误时调用该函数。iOS系统还可以定义mediaStatus参数。
Media类的方法见下表:
常量 |
描述 |
media.getCurrentPosition |
返回当前的播放位置 |
media.getDuration |
返回当前音频的长度 |
media.play |
开始播放或继续以前暂停的播放 |
media.pause |
暂停播放 |
media.release |
释放占用的操作系统的音频资源 |
media.seekTo |
移动播放头 |
media.setVolume |
设置音量 |
media.startRecord |
开始录制音频 |
media.stopRecord |
停止录音 |
media.stop |
停止播放 |
示例:
var oMedia=null;
var mediaTimer=null;
function playAudio(src){
oMedia=new Media(src,onMediaSuccess,onMediaError);
oMedia.play();
if(mediaTimer==null){
mediaTimer=setInterval(function(){
oMedia.getCurrentPosition(
function(position){
if(position>=0){
document.getElementById('audio_position').innerHTML=
position+"sec/"+oMedia.getDuration()+"sec";
}
},
function(err){
document.getElementById('audio_position').innerHTML="Error:"+err;
}
};
},1000);
}
}
function pauseAudio(){
if(oMedia){
oMedia.pause();
}
clearInterval(mediaTimer);
mediaTimer=null;
}
function onMediaSuccess(){
console.log("正在播放......");
}
function onMediaError(err){
alert('code:'+err.code+'\n'+'message:'+err.message);
}
1)使用方法控制音频:
Media类定义了一些方法用于控制音频的播放和获取播放信息:
⑴media.getCurrentPosition()方法:
该方法获取当前的播放位置,如果成功,就调用回调函数mediaSuccess,并将位置信息作为参数传递给该函数,参数是一个数字,以秒为单位;也可以定义可选的参数mediaError,当操作错误时就会调用该函数,语法格式:
media.getCurrentPosition(mediaSuccess[,mediaError])
示例代码:
var oMedia=new Media(src,onSuccess,onError);
//每秒更新一次位置
var mediaTime=setInterval(function(){
oMedia.getCurrentPosition(
//获取当前位置
function(position){
if(position>0){
console.log((position)+" sec");
}
},
//出错处理
function(e){
console.log("Error getting pos="+e);
}
);
},1000);
⑵media.getDuration方法:
该方法返回当前音频的长度,以秒为单位,如果长度未知,则返回-1。该方法没有参数。语法格式:
media.getDuration();
⑶media.seekTo方法:
移动音频的播放头到指定位置:
media.seekTo(ms);
参数ms指定播放头的位置,以毫秒为单位。
⑷media.play、media.pause和media.stop方法:
分别表示播放、暂停和停止。暂停播放后,还可以使用media.play方法在暂停的位置恢复播放。
⑸media.release方法:
释放占用的操作系统的音频资源,该方法对Android系统非常重要。
⑹media.startRecord和media.stopRecord方法:
分别用来开始录制和停止录制。示例:
function recordAudio(){
var src="myrecording.mp3";
var oMedia=new Media(src,
function(){
console.log("录制完成");
),
function(err){
console.log("录制过程出现错误:"+err.code);
});
//开始录制
oMedia.startRecord();
//10秒后停止录制
setTimeout(function(){
oMedia.stopRecord();
},10000);
}
在iOS平台上,方法名为startAudioRecord和stopAudioRecord,并且要录制的文件必须已经存在。
⑺media.setVolume方法:
设置音量:
media.setVolume(volume);
参数volume指定音量,可选值为0.0~1.0,1.0表示最大音量。
2)MediaError对象:
出错回调函数的参数是一个MediaError对象,包含code和message两个属性,分别为出错码和出错描述信息字符串。其中的出错码是以下常量之一:
常量 |
值 |
描述 |
MediaError.MEDIA_ERR_ABORTED |
1 |
播放中断 |
MediaError.MEDIA_ERR_NETWORK |
2 |
网络错误 |
MediaError.MEDIA_ERR_DECODE |
3 |
解码错误 |
MediaError.MEDIA_ERR_NONE_SUPPORTED |
4 |
不支持的格式 |
20.Splash屏幕:
当应用程序启动初始,通常会首先显示一个Splash屏幕。开发人员可以利用该屏幕显示与程序有关的重要信息,如程序名称、版本、Logo等。PhoneGap提供了Splashscreen插件来为应用程序指定Splash屏幕,并且管理Splash屏幕的显示和隐藏,使用前需要安装插件:
cordova plugin add org.apache.cordova.splashscreen
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator对象访问。
为了使用插件,需要在config.xml文件中进行相关配置:
<feature name="SplashScreen"><param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" /></feature>
1)Android系统对屏幕的处理:
Android把所有的屏幕大小分为4种尺寸,小small、普通normal、大large、超大extra large。应用程序可以为这4种尺寸分别提供不同的自定义屏幕布局,并分别提供不同的资源,系统将根据屏幕实际尺寸选择对应布局和资源进行渲染。
Android根据密度大小将屏幕分为4种,ldpi(low)、mdpi(medium)、hdpi(high)、xhdpi(extra high)。一般情况下,ldpi是120dpi,mdpi是160dpi,hdpi是240dpi,xhdpi是320dpi。
密度与屏幕分辨率有一个基本的对应关系:
|
ldpi |
mdpi |
hdpi |
xhdpi |
小屏幕 |
QVGA(240x320) |
|
480x640 |
|
一般 |
WQVGA400(240x400) |
HVGA(320x480) |
WVGA800(480x800) |
640x960 |
大屏幕 |
WVGA800(480x800) |
WVGA800(480x800) |
|
|
超大 |
1024x600 |
WXGA(1280x800) |
1536x1152 |
2048x1536 |
设备独立像素dp(Density-independent pixel),是应用程序可以用来定义UI组件的虚拟像素单元,通过与密度无关的方式来描述布局尺寸和位置,一个dp相当于一个160dpi屏幕上的物理像素,也就是此时1dp=1px。
在程序运行时,系统根据屏幕的实际密度透明的处理任何需要缩放的设备独立像素单元,设备独立像素转换成屏幕实际像素的换算为:
pixels=dps*(density/160)
例如,在240dpi屏幕上,1dp=1.5px。为确保UI组件在不同屏幕都能合适展示,建议使用dp来定义应用程序UI。
2)实现Splash屏幕:
要实现PhoneGap的Splash屏幕,需要2个步骤:
⑴复制Splash屏幕图片到Android工程的res/drawable目录
⑵在主类的onCreate()方法中添加下面的两行代码:
super.setIntegerProperty("splashscreen",R.drawable.splash);
super.loadUrl(Config.getStartUrl(),10000);
其中,第1行用来设置图片被显示为Splash屏幕,第2行代码用来设置Splash屏幕停留的时间,时间参数以毫秒为单位。
Splash屏幕图片这里被命名为splash.png,如果使用其他名字,需要更改这里的代码。例如,如果存在res/drawable/filename.png或res/drawable.9.png,那么就要使用:
super.setIntegerProperty("splashscreen",R.drawable.filename);
不能同时存在filename.png和drawable.9.png。
3)实现高度兼容:
Android系统千差万别,屏幕大小各不相同,必然导致Splash屏幕拉伸变形,导致效果差。创建Splash屏幕时,必须考虑Android系统对屏幕处理的特点,为不同屏幕大小提供充足的兼容性。
在Android2.1之前的版本中,只有一个res\drawable,而Android2.1版本中有res\drawable -mdpi、res\drawable-ldpi、res\drawable-hdpi三个,Android2.2开始增加res\drawable-xhdpi。善用这几个目录就可以实现高度的兼容性,可以分别创建不同分辨率的图片,全都使用一个名字,程序会自动选择合适的图片作为Splash屏幕加载。适用的图片幅面大小为:
·xlarge(xhdpi):最小960x720dp(1920x1440px)
·large(hdpi):最小640x480dp(960x720px)
·medium(mdpi):最小470x320dp(470x320px,推荐480x320px)
·small(ldpi):最小426x320dp(315x240px,推荐320x240px)
在res\drawable下可以放置480x320px的图片。
4)使用9切片缩放图片:
在使用Splash屏幕图片时,虽然考虑了多种屏幕,但还是有一些非标的屏幕层出不穷,为了防止图片拉伸变形,推荐使用9切片缩放图片,具有更大的灵活性,以适应不同屏幕的缩放而不会导致由于图片拉伸产生的拙劣效果。
9切片缩放scale9Grid用来有效地缩放网格类型的图形对象,也被称为九宫格缩放。当对图形对象做任何缩放转换时,都将正常缩放整个显示对象。通常,缩放显示对象时,引起的扭曲在整个显示对象上是均匀分布的,所以各部分的伸展量是相同的。但有时更希望能控制显示对象的某些部分伸展,而某些部分保持不变,比如有圆角的矩形按钮。使用9切片缩放,规则是,中心矩形中的内容既进行水平缩放又进行垂直缩放;四个转角矩形中的任何内容不伸展也不压缩;上中矩形和下中矩形将进行水平缩放,但不进行垂直缩放;左中矩形和右中矩形将进行垂直缩放,但不进行水平缩放;拉伸所有填充(包括位图、视频和渐变)以适应其形状;如果旋转显示对象,则所有后续缩放都是正常的。
Android SDK自带制作9切片缩放的工具,能够对PNG图片处理,为用户生成一个“*.9.png”图片。Android SDK路径tools下,有draw9patch.bat批处理程序,运行后可以启动一个编辑环境。把png文件拖放到这个工具的窗口中,然后就可以进行编辑了。
注意图片左侧和顶部的黑线条,可以定义九宫切片,选中底部的Show patches复选框可以查看9切片具体要缩放的区域,右侧预览区域可以观察最终的拉伸效果。
对Splash屏幕,一般都是一个Logo位于中心位置,这样Logo就不会发生变形了。完成后以“*.9.png”文件名保存到Android工程res\drawable目录下,一次为每个分辨率的Splash屏幕创建图片,并分别放置到合适的位置。在不同屏幕的模拟器上可以测试效果。
5)管理Splash屏幕:
用户使用Splash屏幕的情况下有以下状态。
⑴经过一定时间后关闭
⑵通过Splash屏幕之外的代码控制它不显示时关闭,Splashscreen有2种方法分别用来使应用程序显示和隐藏Splash屏幕。
·show()方法:用来呈现应用程序的Splash屏幕图片,语法格式:
navigator.splashscreen.show();
·hide()方法:用来隐藏应用程序的Splash屏幕图片,语法格式:
navigator.splashscreen.hide();
6)实现全屏:
有时需要把Activity设置成全屏,使用PhoneGap可以轻松实现,在res/xml/config.xml配置文件中添加设置:
<preference name="fullscreen" value="true" />
这个元素直接位于根目录widget下。
但使用这个配置在某些情况下还是会导致不是全屏,推荐在主类的onCreate()方法中添加3行代码:
getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
getWindow().setFlags(android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN,android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN);
第1行代码来清除配置文件中的设置,第2行代码用来设置程序无标题,第3行代码用来设置全屏显示。
21.应用程序的国际化和区域化:
为了方便地将软件翻译成不同语言的版本,需要一套翻译规范和通用工具,这些需求促使了软件开发的国际化机制出现。国际化Internationalization简称I18N,区域化Localization简称L10N,Translation简称T9N。
1)区域化标示:
区域化一般由一个标识符来指定,这个标识符也被称为自然语言代码,由主代码和随后的子代码组成:
code=primary-code["_"subcode]
主代码由ISO639规定,子代码由ISO3166规定,一些范例:
en--英语,en_US--美国英语,en_cockney--伦敦英语
2)实现国际化和区域化:
PhoneGap提供了国际化和区域化插件,使用前需要安装:
cordova plugin add org.apache.cordova.globalization
一旦安装了插件,就可以使用插件的API,它们都可以使用window.navigator对象访问。
为了使用插件,需要在config.xml文件中进行相关配置:
<feature name="Globalization"><param name="android-package" value="org.apache.cordova.globalization.Globalization" /></feature>
PhoneGap国际化和区域化插件有Globalization类,包含用于区域化的信息,有一些方法来实现不同的功能。Globalization对象是navigator对象的子对象,可以使用下面的方法获得一个实例:
var globalization=navigator.globalization;
⑴globalization.getPreferredLanguage()方法:
该方法用来获取系统当前使用的语言,语法格式为:
navigator.globalization.getPreferredLanguage(successCB,errorCB);
成功回调函数successCB包含一个参数,该参数是一个Object类型,它有一个value属性,属性值包含有语言标示符字符串。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.UNKNOWN_ERROR。示例:
navigator.globalization.getPreferredLanguage(
function(language){alert(language.value);},function(){alert('Error getting language\n');});
⑵globalization.getLocaleName()方法:
该方法用来获取系统当前区域化设置的标识符,语法格式为:
navigator.globalization.getLocaleName(successCB,errorCB);
成功回调函数successCB包含一个参数,该参数是一个Object类型,它有一个value属性,属性值包含有区域化标示字符串。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.UNKNOWN_ERROR。示例:
navigator.globalization.getLocaleName(
function(locale){alert(local.value);},function(){alert('操作出错!\n');});
⑶globalization.dateToString()方法:
根据系统的区域化和时区设置格式化一个Date对象为日期字符串,语法格式为:
navigator.globalization.dateToString(date,successCB,errorCB[,options]);
参数date定义要格式化的Date对象,它应该是一个Date类型。成功回调函数successCB包含一个参数,该参数是一个Object类型,它有一个value属性,属性值包含有格式化的日期字符串。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.FORMATTING_ERROR。参数options是可选的,它是一个Object类型,可以定义几个属性,默认值是{formatLength:'short',selecter:'date and time'},formatLength的值可以定义为short、medium、long、full,分别表示短日期、中日期、长日期、完整日期,这些值还取决于具体的区域化设置,有些区域化设置可能仅有长日期。selector的值可以定义为date、time或date and time,分别表示格式化结果为日期、时间、日期和时间。示例:
navigator.globalization.dateToString(new Date(),function(date){alert(date.value);},
function(){alert('操作出错!');};{formatLength:'short',selector:'date and time'});
⑷globalization.stringToDate()方法:
根据系统的偏好设置和日历设置,并根据系统所在时区转换一个字符串为Date对象,要转换的字符串通常是一个表示日期的字符串,语法格式为:
navigator.globalization.stringToDate(dateString,successCB,errorCB[,options]);
参数dateString是要转换的字符串,是一个String类型。成功回调函数successCB包含一个参数,该参数是一个Object类型。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.PARSING_ERROR。参数options是可选的,它是一个Object类型,可以定义几个属性,默认值是{formatLength:'short',selecter:'date and time'},formatLength的值可以定义为short、medium、long、full,分别表示短日期、中日期、长日期、完整日期,这些值还取决于具体的区域化设置,有些区域化设置可能仅有长日期。selector的值可以定义为date、time或date and time,分别表示格式化结果为日期、时间、日期和时间。
成功回调函数successCB的参数包含的属性有:
属性 |
功能表达 |
year{Number} |
年(4位数字表示法) |
month{Number} |
月(0~11) |
day{Number} |
日(1~31) |
hour{Number} |
时(0~23) |
minute{Number} |
分(0~59) |
second{Number} |
秒(0~59) |
millisecond{Number} |
毫秒(0~999),不是所有平台都实现此属性 |
示例:
navigator.globalization.stringToDate('11/25/2013',
function(date){alert('month:'+date.month+' day:'+date.day+'year:'+date.year+'\n');},
function(){alert('操作出错!');};{selector:'date'});
注意,date.month的值总是比月份值小1,即1月份date.month的值为0。
⑸globalization.getDatePattern()方法:
该方法可以根据系统的偏好设置返回一个模式,用于格式化和解析日期,语法格式为:
navigator.globalization.getDatePattern(successCB,errorCB[,options]);
成功回调函数successCB包含一个参数,该参数是一个Object类型。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.PATTERN_ERROR。参数options是可选的,它是一个Object类型,可以定义几个属性,默认值是{formatLength:'short',selecter:'date and time'},formatLength的值可以定义为short、medium、long、full,分别表示短日期、中日期、长日期、完整日期,这些值还取决于具体的区域化设置,有些区域化设置可能仅有长日期。selector的值可以定义为date、time或date and time,分别表示格式化结果为日期、时间、日期和时间。
成功回调函数successCB的参数包含的属性有:
属性 |
功能表达 |
pattern{String} |
一个模式字符串,用于格式化和解析日期,该模式字符串符合Unicode Technical Standard#35 http://unicode.org/report/tr35/tr35-4.html |
timezone{String} |
时区名的缩写 |
utc_offset{Number} |
系统时间与UTC之间的时差,以秒为单位 |
dst_offset{Number} |
系统夏时制时间与非夏时制时间之间的时差,以秒为单位 |
示例:
navigator.globalization.getDatePattern(
function(date){alert('pattern:'+date.pattern+'\n'+'timezone:'+date.timezone+'\n'+'utc_offset:'+date.utc_offset+'\n');},
function(){alert('操作出错!');};{formatLength:'short',selector:'date and time'});
⑹globalization.getDateNames()方法:
该方法可以根据系统的偏好设置和日历来获取当前的月份或星期值,取决于参数options的值,语法格式为:
navigator.globalization.getDateNames(successCB,errorCB[,options]);
成功回调函数successCB包含一个参数,该参数是一个Object类型。它有一个value属性,属性值包含有一个字符串组成的数组,数组中的元素要么是一年中各个月份的字符串,要么是一周中各天的字符串,视options而定。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.UNKNOWN_ERROR。参数options是可选的,它是一个Object类型,可以定义几个属性,默认值是{type:'wide',item:'months'},type的值可以定义为narrow或wide,分别表示月份或星期的缩写和完整书写方式,item值可以定义为months或days,分别表示月份和星期。示例:
navigator.globalization.getDateNames(
function(names){alert(names.value.toString());},
function(){alert('操作出错!');};{type:'wide',item:'months'});
names.value的值是一个数组,用户也可以使用循环语句访问数组的所有元素:
for(var i=0;i<names.value.length;i++){
alert('month:'+names.value[i]);
}
⑺globalization.isDayLightSavingsTime()方法:
该方法可以根据系统的时区和日历来确定当前实行的是否是夏时制,语法格式为:
navigator.globalization.isDayLightSavingsTime(successCB,errorCB[,options]);
参数date指定要匹配的日期,应为一个Date类型。成功回调函数successCB包含一个参数,该参数是一个Object类型。它有一个dst属性,属性值包含有一个逻辑值,true表示正在实行夏时制,false表示没有实行夏时制。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.UNKNOWN_ERROR。示例:
navigator.globalization.isDayLightSavingsTime(new Date(),
function(date){if(date.dst) alert('正在实行夏时制!');else alert('没有实行夏时制!');},
function(){alert('操作错误!');});
⑻globalization.getFirstDayOfWeek()方法:
该方法可以根据系统的偏好设置和日历返回一周的第一天,语法格式为:
navigator.globalization.getFirstDayOfWeek(successCB,errorCB);
成功回调函数successCB包含一个参数,该参数是一个Object类型。它有一个value属性,属性值包含有一个数字值,用来表示星期,从1到7,1表示Sunday,也就是一周的第一天。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.UNKNOWN_ERROR。示例:
navigator.globalization.getFirstDayOfWeek(
function(day){alert(day.value);},
function(){alert('操作错误!');});
⑼globalization.numberToString()方法:
根据系统的偏好设置转换一个数字为字符串,语法格式为:
navigator.globalization.numberToString(number,successCB,errorCB[,options]);
参数number是要转换的数字,这是一个Number类型。成功回调函数successCB包含一个参数,该参数是一个Object类型。它有一个value属性,属性值包含有格式化好的数字字符串。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.FORMATTING_ERROR。参数options可选,它是一个Object类型,可以定义一个属性,默认值是{type:'decimal'},type的值可以定义为decimal、percent、currency,分别表示浮点数、百分比数和货币。示例:
navigator.globalization.numberToString(3.1415926,
function(number){alert(number.value);},
function(){alert('操作错误!');},{type:'currency'});
⑽globalization.stringToNumber()方法:
根据系统的偏好设置转换一个字符串为数字,语法格式为:
navigator.globalization.stringToNumber(string,successCB,errorCB[,options]);
参数string是要转换的字符串,这是一个String类型。成功回调函数successCB包含一个参数,该参数是一个Object类型。它有一个value属性,属性值包含一个数字值。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.PARSING_ERROR。参数options可选,它是一个Object类型,可以定义一个属性,默认值是{type:'decimal'},type的值可以定义为decimal、percent、currency,分别表示浮点数、百分比数和货币。示例:
navigator.globalization.stringToNumber('1234.56',
function(number){if(typeof(number.value)=='number') alert(number.value);},
function(){alert('操作错误!');},{type:'decimal'});
如果要转换一个货币,那么就要把type属性值设为currency。参数String的值还要取决于区域化设置,$1234.56只有在English(United States)下才能成功转换,否则就会调用失败回调函数。
⑾globalization.getNumberPattern()方法:
该方法可以根据系统的偏好设置返回一个模式用于格式化数字,语法格式为:
navigator.globalization.getNumberPattern(successCB,errorCB[,options]);
成功回调函数successCB包含一个参数,该参数是一个Object类型。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.PATTERN_ERROR。参数options可选,它是一个Object类型,可以定义一个属性,默认值是{type:'decimal'},type的值可以定义为decimal、percent、currency,分别表示浮点数、百分比数和货币。
成功回调函数successCB的参数包含的属性有:
属性 |
功能表达 |
pattern{String} |
一个模式字符串,用于格式化和解析日期,该模式字符串符合Unicode Technical Standard#35 http://unicode.org/report/tr35/tr35-4.html |
symbol{String} |
一个符号,用于格式化和解析百分比等数字 |
fraction{Number} |
小数的位数 |
rounding{Number} |
用于四舍五入的数字 |
positive{String} |
表示正数的符号 |
negative{String} |
表示负数的符号 |
decimal{String} |
表示小数点的符号 |
grouping{String} |
表示分组的符号 |
示例:
navigator.globalization.getNumberPattern(
function(pattern){alert('pattern:'+pattern.pattern+'\n'
+'symbol:'+pattern.symbol+'\n'+'fraction:'+pattern.fraction+'\n'
+'rounding:'+pattern.rounding+'\n'+'positive:'+pattern.positive+'\n'
+'negative:'+pattern.negative+'\n'+'decimal:'+pattern.decimal+'\n'
+'grouping:'+pattern.grouping+'\n');},
function(){alert('操作错误!');},{type:'decimal'});
⑿globalization.getCurrencyPattern()方法:
该方法可以根据系统的偏好设置和指定的货币标示符返回一个模式用于格式化货币,语法格式为:
navigator.globalization.getCurrencyPattern(currencyCode,successCB,errorCB);
参数currencyCode是一个货币标示符字符串,例如USD,ISO4217规定了各国货币的符号字符串。成功回调函数successCB包含一个参数,该参数是一个Object类型。如果操作发生错误,那么失败回调函数errorCB被执行,失败回调函数包含一个参数,该参数是一个GlobalizationError对象,包含了导致错误的原因,该错误的预期错误码是常量GlobalizationError.FORMATTING_ERROR。
成功回调函数successCB的参数包含的属性有:
属性 |
功能表达 |
pattern{String} |
一个模式字符串,用于格式化和解析日期,该模式字符串符合Unicode Technical Standard#35 http://unicode.org/report/tr35/tr35-4.html |
code{String} |
货币标示符字符串 |
fraction{Number} |
小数的位数 |
rounding{Number} |
用于四舍五入的数字 |
decimal{String} |
表示小数点的符号 |
grouping{String} |
表示分组的符号 |
示例:
navigator.globalization.getNumberPattern(
function(pattern){alert('pattern:'+pattern.pattern+'\n'
+'code:'+pattern.code+'\n'+'fraction:'+pattern.fraction+'\n'
+'rounding:'+pattern.rounding+'\n'+'decimal:'+pattern.decimal+'\n'
+'grouping:'+pattern.grouping+'\n');},
function(){alert('操作错误!');});
3)出错处理:
当全局化和区域化操作发生错误时,会调用失败处理函数,并传递一个GlobalizationError对象作为参数,该对象可以使用属性message返回一个字符串,对出错原因做一个简单描述。也可以使用属性code返回出错代码,属性可以是下面到的常量之一:
常量 |
值 |
描述 |
GlobalizationError.UNKNOWN_ERROR |
0 |
未知错误 |
GlobalizationError.FORMATTING_ERROR |
1 |
格式化错误 |
GlobalizationError.PARSING_ERROR |
2 |
解析错误 |
GlobalizationError.PATTERN_ERROR |
3 |
模式错误 |
22.自定义插件:
PhoneGap提供了编程接口,可以让用户编写自定义插件。PhoneGap插件使用Java语言编写,熟悉Android系统及Java语言的,就可以自己编写插件来扩充PhoneGap功能。
1)创建PhoneGap插件:
⑴首先使用Eclipse创建一个Android Application Project工程,因为是创建一个插件库,不需要图标和Activity,在设置界面取消这两个复选框。
⑵菜单Project--Properties进入工程属性对话框,选择Android,将CordovaLib添加到工程中,这是PhoneGap类库,需要使用;在src目录中新增一个Java Class文件,填入包名,超类指定为org.apache.cordovaPlugin。
⑶自建的类必须继承自超类cordovaPlugin,并且必须覆盖execute()方法,语法格式为:
execute(String action,JSONArray args,CallbackContext callbackContext);
其中,参数action指定要调用的方法名,args指定方法调用时传进来的参数,callbackContext指定调用回调函数的上下文环境,用于实现JavaScript成功回调函数或者失败回调函数。
考虑到该方法还需要一些类的支持,应该导入这些类,最终该类的组成为:
pachage cn.dwenzhao.plugins;
import org.apache.cordova.*;
import org.json.JSONArray;
import org.json.JSONExcecption;
import org.json.JSONObject;
public class FirstPlugin extends CordovaPlugin{
@Override
public boolean execute(String action,JSONArray args,CallbackContext callbackContext) throws JSONException{
if("sayHello".equals(action)){
//如此传进来的方法名与指定的方法名相同,就执行这里的代码
//成功就执行callbackContext.success(param),触发成功回调函数
//失败就执行callbackContext.error(param),触发失败回调函数
//如果不需要回调函数,就没必要调用这两个方法
return true;
}
return false;
}
}
此插件定义了sayHello方法,该方法可以获取用户输入的名称,在前面加“Hello.”后再返回给调用者。其中的if语句中的代码为:
if("sayHello".equals(action)){
String message=args.getString(0);
if(message!=null && message.length()>0){
callbackContext.success("Hello:"+message+"1");
}else{
callbackContext.error"输入值为空!");
}
return true;
}
⑷导出为一个可执行文件包。在Eclipse中选择要导出的类FirstPlugin,选择菜单File--Export会弹出导出对话框,在其中选择Java > JAR file,选择要生成的jar包的位置及名字,并取消右侧所有复选框,但选择下面的Export generated class files and resources复选框。
2)使用插件:
⑴在工程中导入插件。因为插件是一个Java类,一般有两种方式,一种是将Java源程序放置到当前工程中,另一种是使用已经编译好的类库(jar文件)。将jar文件复制到工程目录的platforms\android\libs目录下。
使用已经编译好的插件可能导致版本兼容性问题,如果要公布该插件供其他用户使用,最好公布源代码,让用户自己添加到工程中来使用。
⑵在res/xml/config.xml配置文件中使用feature添加对插件的引用。feature节点表明是一个插件,属性name指定插件的服务名,其中的子节点param定义该插件。示例:
<feature name="MyFirstPlugin">
<param name="android-package" value="cn.dwenzhao.plugins.FirstPlugin" />
</feature>
⑶然后编写JavaScript程序来注册和连接。
在工程内的platforms\android\assets\www\plugins\目录下新增一个firstplugin.js文件,代码:
cordova.define("cn.dwenzhao.plugins.FirstPlugin",function(request,exports,module){
var exec=request('cordova/exec');
var cordova=request('cordova');
function MyFirstPlugin(){};
MyFirstPlugin.prototype.sayHello=function(name,successCallback,failureCallback){
exec(successCallbak,failureCallback,'MyFirstPlugin','sayHello',[name]);
}
module.exports=new MyFirstPlugin();
}
主要是应用exec()方法,参数分别为成功回调函数、失败回调函数、注册的插件服务名、方法名以及传进来的参数,语法格式:
exec(successFunction,failureFunction.servicename,action,[args]);
如果有多个参数,args形成一个数组[arg1,arg2,arg3];如果不需要为方法指定回调函数,就将响应参数赋值为null,示例:
exec(null,null.'MyFirstPlugin','sayHello',[arg1,arg2]);
⑷将插件中公开的成员放在插件列表中,默认使用platforms\android\assets\www\目录下的cordova_plugins.js文件来定义使用的插件列表。这个文件中主要有两个属性声明:
module.exports=[{}];
module.exports.metadata={};
module.exports属性的值是一个数组,每个数组元素就是一个插件定义,每个插件定义是一个对象,其中有属性定义,例如添加如下的插件定义:
module.exports=[{"file":"plugins/firstplugin.js",
"id"::cn.dwenzhao.plugins.FirstPlugin",
"clobbers":["MyFirstPlugin"]
}];
其中,file属性表示注册和连接JavaScript文件的位置;id属性表示唯一的标识;clobbers表示可以引用的接口。
而module.exports.metadata属性则定义元数据,主要就是版本号:
module.exports.metadata={"cn.dwenzhao.plugin.FirstPlugin":"1.0"}
⑸如果需要授权执行某些特定的操作,还需要编辑AndroidManifest.xml文件,提供授权声明。
⑹编写网页,调用插件中的方法,代码为:
function clickHandler(){
inputName=document.getElementById("inputName");
window.MyFirstPlugin.sayHello(inputName.value,onSuccess,onError);
}
一般都会将插件的类及其公开的方法封装在一个单独的js文件中,但也可以直接在网页中执行cordova.exec()方法:
function clickHandler(){
inputName=document.getElementById("inputName");
cordova.exec(onSuccess,onError,'MyFirstPlugin','sayHello',[inputName.value]);
}
使用封装的方法更利用代码的维护。
3)线程使用:
在WebView中运行的JavaScript代码不是运行在UI线程,而是运行在WebCore线程,execute()方法也是运行在WebCore线程。如果需要与UI交互,可以使用下面的代码:
@Override
public boolean execute(String action,JSONArray args,final CallbackContext callbackContext) throws JSONException{
if("sayHello".equals(action)){
String message=args.getString(0);
cordova.getActivity().runOnUiThread(new Runnable(){
public void run(){
......
callbackContext.success();
}
});
return true;
}
return false;
}
如果用户不需要运行在UI进程,而且也不需要阻塞WebCore线程,则可以使用:
@Override
public boolean execute(String action,JSONArray args,final CallbackContext callbackContext) throws JSONException{
if("sayHello".equals(action)){
String message=args.getString(0);
cordova.getThreadPool().execute(new Runnable(){
public void run(){
......
callbackContext.success();
}
});
return true;
}
return false;
}
4)关于输入参数:
自定义插件必须继承自超类CordovaPlugin,并且必须覆盖超类的execute()方法,该方法有3种重构形式,主要就是输入参数args的数据类型不同,这个输入参数就是在JavaScript程序中调用的方法被封装后传进来的值。
⑴第1种重构形式:
public boolean execute(String action,JSONArray args,CallbackContext callbackContext) throws JSONException()
参数args是一个JSONArray,可以使用JSONArray类定义的方法获取其中包含的数据,有多个getXXX()方法,每个方法都是根据索引号来获取其中的数据,不同的方法返回的数据类型不同:
Object get(int index);
boolean getBoolean(int index);
double getDouble(int index);
int getInt(int index);
JSONArray getJSONArray(int index);
JSONObject getJSONObject(int index);
long getLong(int index);
String getString(int index);
有时候必须检查传进来参数的数据类型,需要使用遍历的方法。JSONArray定义有length()方法可以获取其长度,然后就可以遍历JSONArray,示例代码:
int len=args.length();
for(int i=0;i<len;i++){
Class returnedType=args.get(i).getClass();
//......
}
有可能嵌套了JSONArray,这时就必须获取这个嵌套的JSONArray,然后遍历。
⑵第2种重构形式:
public boolean execute(String action,String args,CallbackContext callbackContext) throws JSONException()
参数args是一个字符串String,但这个字符串是JSON格式的字符串,用户必须解析这个JSON字符串获取其中的数据。一般是在方法体你使用下面的方法构造一个JSONArray,然后使用前面的方法获取数据:
JSONArray args=new JSONArray(rawArgs);
⑶第3种重构形式:
public boolean execute(String action,CordovaArgs args,CallbackContext callbackContext) throws JSONException()
参数args是一个CordovaArgs类型,可以使用下面的方法来根据索引获取其中包含的数据,不同的方法返回的数据类型不同:
Object get(int index);
boolean getBoolean(int index);
double getDouble(int index);
int getInt(int index);
JSONArray getJSONArray(int index);
JSONObject getJSONObject(int index);
long getLong(int index);
String getString(int index);
byte[] getArrayBuffer(int index);
推荐使用第1中重构形式。
5)关于回调函数的参数:
在JavaScript程序中调用插件方法时,成功回调函数和失败回调函数的参数可以有多种形式,主要取决于使用Java程序创建插件时在方法体内调用callbackContext.success()方法和callbackContext.error()方法的参数:
callbackContext.success()
callbackContext.success(String message)
callbackContext.success(JSONObject message)
callbackContext.success(JSONArray message)
callbackContext.success(byte[] message)
callbackContext.success(int message)
callbackContext.error(String message)
callbackContext.error(int message)
callbackContext.error(JSONObject message)
几种重构的不同在于参数message的数据类型。
6)关于插件返回值的方法:
callbackContext.success()和callbackContext.error()方法都可以有返回值,并且它们都会调用callbackContext.sendPluginResult()方法来返回值,只是构造的参数不同。PhoneGap源代码实现:
public void success(JSONObject message){
sendPluginResult(new PluginResult(PluginResult.Status.OK,message));
}
public void error(JSONObject message){
sendPluginResult(new PluginResult(PluginResult.Status.ERROR,message));
}
实际上也可以直接调用callbackContext.sendPluginResult()方法,该方法可以返回更多标示类型的PluginResult对象,语法格式为:
callbackContext.sendPluginResult(PluginResult pluginResult);
它只有一个参数,表示插件返回的结果。PluginResult的Status属性值可以是以下常量:
PluginResult.Status.NO_RESULT
PluginResult.Status.OK
PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION
PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION
PluginResult.Status.INSTANTIATION_EXCEPTION
PluginResult.Status.MALFORMED_URL_EXCEPTION
PluginResult.Status.IO_EXCEPTION
PluginResult.Status.INVALID_ACTION
PluginResult.Status.JSON_EXCEPTION
PluginResult.Status.ERROR