PhoneGap 2.0 开发17. Camera API简介
PhoneGap Camera API提供给应⽤用处理照⽚片的能
⼒力,可以直接从摄像头采集或者从设备的相册获取
照⽚片。
当提取照⽚片时,API可以返回指向设备⽂文件系统上
的image⽂文件URI,或者以base64编码字符串的⽅方式
返回image⽂文件内容。
Camera API只提供了⼀一个⽅方法:
navigator.camera.getPicture。但是getPicture的
cameraOptions参数提供了⾮非常丰富的配置选项!
18. 访问照⽚片(拍照,相⽚片库)
navigator.camera.getPicture( onCameraSuccess,
onCameraError, [ cameraOptions ] );
• 说明:
• 同样需要传⼊入两个函数:onCameraSuccess,
onCameraError。成功得到照⽚片的时候调⽤用
onCameraSuccess函数;⽤用户取消或者获取照⽚片失败的
时候会调⽤用onCameraError函数。
• cameraOptions是⼀一个可选的配置选项。(后⾯面会详细
介绍)
20. getPicture代码⽰示例
<!DOCTYPE html>
<html>
<head>
<title>Example Camera</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
<script type="text/javascript" charset="utf-8">
function onBodyLoad() {
alert("onBodyLoad");
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
navigator.notification.alert("onDeviceReady");
}
function takePhoto() {
//alert("takePhoto");
navigator.camera.getPicture(onCameraSuccess, onCameraError,
{ quality: 50, destinationType: Camera.DestinationType.FILE_URI });
// navigator.camera.getPicture(onCameraSuccess, onCameraError);
}
function onCameraSuccess(imageURL) {
navigator.notification.alert("onCameraSuccess: " + imageURL);
}
function onCameraError() {
navigator.notification.alert("onCameraError");
}
</script>
</head>
<body onload="onBodyLoad()">
<h1>Example Camera-1</h1>
<p>
使⽤用 PhoneGap Camera API
<br />
<input type="button" value="拍张照⽚片" onclick="takePhoto();">
</p>
</body>
</html>
22. Camera API Demo 2 - 拍照并在⻚页⾯面显⽰示
和前⼀一个例⼦子的主要代码差异
function onCameraSuccess(imageURL) {
navigator.notification.alert("onCameraSuccess: " + imageURL);
//得到⽤用于显⽰示图⽚片的div的id
ic = document.getElementById('imageContainer');
//使⽤用从camera程序得到的URL写⼀一个img标签,并且输出到刚才得到的div。
ic.innerHTML = '<img src="' + imageURL + '" width="50%" />';
}
24. cameraOptions - quality
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
quality:保存相⽚片的质量。范围[0, 100](Number)
25. quality参数的使⽤用和注意事项
• 采⽤用多⾼高质量
• 保存为⽂文件时,采⽤用多⾼高的照⽚片质量?⽂文件⼤大⼩小,设
备内存,⺴⽹网络传输...... ⼀一般50%-100%。
• 使⽤用base64字符串返回时,采⽤用多⾼高的照⽚片质量?字
符串⻓长度,JS的处理能⼒力。⼀一般50%及以下。
• BlackBerry会忽略quality参数
26. cameraOptions - destinationType
{ quality : 75,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
destinationType: 返回的格式。在
navigator.camera.DestinationType中定义(Number)
Camera.DestinationType = {
DATA_URL : 0, // 以base64编码字符串格式返回照⽚片内容
FILE_URI : 1 // 返回image⽂文件的URI
};
28. cameraOptions - sourceType
{ quality : 75, 从相册选取的图⽚片
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
sourceType: 设置照⽚片源。在
navigator.camera.PictureSourceType中定义(Number)
Camera.PictureSourceType = {
PHOTOLIBRARY : 0,
CAMERA : 1,
SAVEDPHOTOALBUM : 2
};
30. cameraOptions - allowEdit
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
allowEdit: 选取前是否允许简单的编辑。(Boolean)
32. cameraOptions - encodingType
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
encodingType: 选择返回image⽂文件的编码。在
navigator.camera.EncodingType中定义(Number)
Camera.EncodingType = {
JPEG : 0, // 以JPEG格式编码image
PNG : 1 // 以PNG格式编码image
};
34. cameraOptions - targetWidth & targetHeight
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 1024,
targetHeight: 768,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
targetWidth: 设定照⽚片宽度,以像素为单位。(Number)
targetHeight: 设定照⽚片⾼高度,以像素为单位。(Number)
36. cameraOptions - mediaType
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType :
Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
mediaType: Camera.MediaType.PICTURE,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
mediaType: 设置从哪类媒体中选择。仅在
PictureSourceType为PHOTOLIBRARY或SAVEDPHOTOALBUM
时有效。在navigator.camera.MediaType中定义。
Camera.MediaType = {
PICTURE: 0, // 只能选择静态图⽚片。返回格式由destinationType字段确定。
VIDEO: 1, // 只能选择视频。以FILE_URI格式返回。
ALLMEDIA : 2 // 可以从所有的媒体类型中选择
37. cameraOptions - correctOrientation
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
correctOrientation: true,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
correctOrientation: 采集时针对设备⽅方向翻转图⽚片。(Boolean)
38. cameraOptions - saveToPhotoAlbum
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
correctOrientation: true,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
saveToPhotoAlbum: 抓取
后是否保存到设备相册。
(Boolean)
39. cameraOptions - popoverOptions
{ quality : 75,
destinationType : Camera.DestinationType.DATA_URL,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
correctOrientation: true,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false };
popoverOptions: 指定在iPad上popover的位置。(Boolean)
仅适⽤用于iOS平台。
40. 平台相关的注意事项
• Android
• 忽略allowEdit参数
• Camera.PictureSourceType.PHOTOLIBRARY和
Camera.PictureSourceType.SAVEDPHOTOALBUM显⽰示同样的
相册。
• iOS
• 在某些设备上设置quality⼩小于50以避免内存错误。
• 当设置使⽤用destinationType.FILE_URI时,照⽚片被保存到应⽤用
的临时⺫⽬目录。开发者可以使⽤用navigator.fileMgr API删除这些
⽂文件以进⾏行空间管理。(参⻅见iOS⽂文件指南)
• 或者使⽤用camera.cleanup
41. 平台相关的注意事项(续)
• BlackBerry
• 忽略quality参数
• 忽略sourceType参数
• 忽略allowEdit参数
• 忽略correctOrientation参数
• 应⽤用必须具有injection权限以在拍照后关闭本地Camera应⽤用
• 不⽀支持Camera.MediaType
• Windows Phone 7
• 忽略allowEdit参数
• 忽略correctOrientation参数
45. What we will learn?
• 图⽚片,视频,⾳音频采集的基本⽅方法
• 采集选项的指定:次数,时⻓长...
• 采集⽂文件数组的遍历和⽂文件属性
• 获取采集⽂文件的格式相关信息
46. Capture API简介
• PhoneGap Capture API允许应⽤用程序使⽤用移动设备
上合适的内置应⽤用进⾏行audio,video和image的采
集。
• 设备默认的camera应⽤用被⽤用来采集image和
video,同样设备默认的voice recorder应⽤用被⽤用来
采集⾳音频剪辑。
• PhoneGap Capture API的实现基于W3C Media
Capture API规范。但是PhoneGap对于规范并没有
提供完全的⽀支持,有⼀一些选项还没有实现。
47. Camera vs. Capture
Q: Camera和Capture都可以采集图⽚片,功能为什么会重
叠呢?
A:
1.Camera API的实现在PhoneGap采纳W3C Capture API之
前,PhoneGap保留Camera API是为了和现有的应⽤用保持
向下兼容。
2.虽然两个API都可以采集image,但是以不同的⽅方式进⾏行
操作。Camera API只能采集图⽚片,但是既⽀支持从camera
拍照,⼜又可以从相册获取;Capture API只能直接从
camera拍照,并且⽀支持从⼀一个单独的API调⽤用进⾏行多个
采集。
48. 使⽤用Capture API
• 采集⼀一个或多个audio⽂文件:
navigator.device.capture.captureAudio(onCaptureSuccess
, onCaptureError, captureOptions);
• 采集⼀一个或多个image⽂文件:
navigator.device.capture.captureImage(onCaptureSuccess
, onCaptureError, captureOptions);
• 采集⼀一个或多个video⽂文件:
navigator.device.capture.captureVideo(onCaptureSuccess
, onCaptureError, captureOptions);
53. Capture API 代码实例讲解
function doCapture() {
//清空前⾯面的结果
res.innerHTML = "采集初始化...";
//从⻚页⾯面读取数量,时⻓长等参数
var numItems = document.getElementById("numItems").value;
var capDur = document.getElementById("duration").value;
//搞定采集类型
var captureType = document.getElementById("captureType").selectedIndex;
switch(captureType) {
case 0:
//⾳音频采集
navigator.device.capture.captureAudio(onCaptureSuccess, onCaptureError, {
duration : capDur,
limit : numItems
});
break;
case 1:
//图⽚片采集
navigator.device.capture.captureImage(onCaptureSuccess, onCaptureError, {
limit : numItems
});
break;
case 2:
//视频采集
navigator.device.capture.captureVideo(onCaptureSuccess, onCaptureError, {
duration : capDur,
limit : numItems
});
break;
}
}
55. captureOptions对象 - 属性
var captureOptions = {duration: 5, limit: 3};
• duration:时⻓长
• limit:采集次数限制
• mode:模式
不同采集类型的可⽤用选项
Capture选项
Capture类型 Duration Limit Mode
Audio X X X
Image X X
Video X X X
59. onCaptureSuccess的处理过程
function onCaptureSuccess(fileList) {
var i, len, htmlStr;
len = fileList.length;
//确保采集成功。如果成功的话,length应该 > 0
if(len > 0) {
htmlStr = "<p>Results:</p><ol>";
for( i = 0, len; i < len; i += 1) {
alert(fileList[i].fullPath);
htmlStr += '<li><a href="' + fileList[i].fullPath + '">' +
fileList[i].name + '</a></li>';
}
htmlStr += "</ol>";
//这是result内容
res.innerHTML = htmlStr;
}
}
采集结果是⼀一个MediaFile数组,遍历以获得所有采集结果。
60. MediaType对象
• 对象属性
• name: ⽂文件名(⽆无路径信息)(DOMString)
• fullPaht: ⽂文件全路径,包括⽂文件名(DOMString)
• type: mime type(DOMString)
• lastModifiedDate: 最后修改的⽇日期和时间(Date)
• size: ⽂文件⼤大⼩小(以字节计)(Number)
• ⽅方法
• MediaFile.getFormatData: 获得媒体⽂文件的格式信息。
62. MediaFileData对象
• 封装了有关媒体⽂文件的格式信息
• 属性:
• codecs: ⾳音视频⽂文件的真实格式。(DOMString)
• bitrate: 内容的平均⽐比特率。如果是图⽚片的话,这个属
性值为0。(Number)
• height: 图⽚片或视频的⾼高度(像素)。如果是⾳音频剪辑的
话,这个属性值为0。(Number)
• width: 图⽚片或视频的宽度(像素)。 如果是⾳音频剪辑的
话,这个属性值为0。(Number)
• duration: ⾳音视频⽂文件的时⻓长(秒)。如果是图⽚片的话这
个值为0。
63. onCaptureError的处理
function onCaptureError(e) {
var msgText;
//采集失败的话,清空前⾯面⽣生成的内容。
res.innerHTML = "";
//根据API返回的错误码构建⼀一个消息字符串
switch(e.code) {
case CaptureError.CAPTURE_INTERNAL_ERR:
msgText = "内部错误, 摄像头或者⻨麦克⻛风采集图⽚片或⾳音频失败。";
break;
case CaptureError.CAPTURE_APPLICATION_BUSY:
msgText = "摄像头应⽤用或者录⾳音机程序正在被其他采集请求使⽤用。";
break;
case CaptureError.CAPTURE_INVALID_ARGUMENT:
msgText = "传递给API的参数⽆无效。";
break;
case CaptureError.CAPTURE_NO_MEDIA_FILES:
msgText = "⽤用户可能取消了采集过程。";
break;
case CaptureError.CAPTURE_NOT_SUPPORTED:
msgText = "该设备不⽀支持请求的操作。";
break;
default:
//针对其他错误⽣生成⼀一个常规回复
msgText = "未知错误 (" + e.code + ")";
}
//使⽤用alert通知⽤用户
navigator.notification.alert(msgText, null, "采集出错了!");
}
错误码定义及其含义
65. What we will learn?
• 罗盘原理及地磁轴和实际南北极的差别
• 通过API获得设备朝向
• 设置朝向变更⾃自动通知
• 使⽤用jQuery图⽚片旋转扩展和 Compass API 开发⼀一个
HTML5的指南针应⽤用
66. Compass API简介
• Compass API 允许PhoneGap应⽤用通过⼀一个⼤大致对应
于地球表⾯面的⼆二维平⾯面来获得设备的朝向。⼤大多数
的智能⼿手机都装有⼀一个物理的罗盘传感器(芯⽚片),
API就是简单的对芯⽚片进⾏行⼀一个查询,然后返回⼀一个0
到360度的⼀一个⾓角度来表⽰示设备所指的⽅方向。
• ⾓角度和⽅方向
• 0度 - 正北(N)
• 90度 - 正东(E)
• 180度 - 正南(S)
• 270度 - 正⻄西(W)
67. Compass API简介(续)
• Compass API的⼯工作⽅方式和Accelerometer类似,既
可以⼿手动查询设备的朝向,也可以设定⼀一个watch
让API以⼀一个指定的频率在设备朝向变化超过设定
的最⼩小的阀值时向应⽤用报告朝向。
• 注意:不是所有的智能机都具有物理罗盘。
iPhone 3GS及以后都有,BlackBerry知道7 OS设备
才有。
69. 获得设备朝向
• 查询设备朝向的API⽅方法:
navigator.compass.getCurrentHeading(
onSuccess, onError);
function getHeading() {
//alert("getHeading");
if(pgr == true) {
if(hasCompass == true) {
//清空当前的朝向内容,
//输出提⽰示信息,以防读取数据耗时较⻓长
hc.innerHTML = "正在从罗盘获取当前朝向...";
//得到当前朝向
navigator.compass.getCurrentHeading(onHeadingSuccess,
onHeadingError);
} else {
alert("没有找到罗盘。");
}
} else {
alert("请稍侯,PhoneGap 尚未就绪。");
}
}
70. onHeadingSuccess
• 查询设备朝向成功时调⽤用
function onHeadingSuccess(heading) {
var d = new Date(heading.timestamp);
hc.innerHTML = "<b>Magnetic Heading:</b> " + heading.magneticHeading
+ "<br /><b>True Heading:</b> " + heading.trueHeading + "<br /><b>Heading
Accuracy:</b> " + heading.headingAccuracy + "<br /><b>Timestamp:</b> " +
d.toLocaleString();
}
71. onHeadingError
• 查询设备朝向失败时调⽤用
function onHeadingError(compassError) {
//alert("onHeadingFailure");
if(compassError.code == CompassError.COMPASS_NOT_SUPPORTED) {
hc.innerHTML = "Compass not available."
alert("Compass not supported.");
hasCompass == false;
} else
if(compassError.code == CompassError.COMPASS_INTERNAL_ERR) {
alert("Compass Internal Error");
} else {
alert("Unknown heading error!");
}
}
72. 设置观察者
• 设置罗盘朝向观测的API⽅方法:
navigator.compass.watchHeading(onHeading
Success, onHeadingError, watchOptions);
function onDeviceReady() {
alert("onDeviceReady");
//设置观察者
//每秒四次读取罗盘数据 (250 milliseconds, .25 seconds)
var watchOptions = {
frequency : 250
};
watchID = navigator.compass.watchHeading(onHeadingSuccess,
onHeadingError, watchOptions);
}
74. onHeadingSuccess
• 读取罗盘数据成功时回调
function onHeadingSuccess(heading) {
//alert("onHeadingSuccess");
var hv = Math.round(heading.magneticHeading);
hi.innerHTML = "<b>Heading:</b>" + hv + " degrees";
$("#compass").rotate(-hv);
}
75. compassHeading对象
• 读取罗盘数据成功时传⼊入的数据对象
• magneticHeading:地磁轴的⽅方向,0-355.99度。
• trueHeading:地球转轴(地理南北极连线)的真正⽅方
向。【地磁轴和实际的南北极并不⼀一致,相交约11.5
度】
• headingAccuracy:报告的度数和实际度数之差。
• timestamp:获得数据时的时间戳。
76. onHeadingError
• 读取罗盘数据出错时回调
function onHeadingError(compassError) {
//alert("onHeadingFailure");
//出错时移除观察者。
navigator.compass.clearWatch(watchID);
//从⻚页⾯面上清空朝向数据。
hi.innerHTML = "";
//错误提醒。
if(compassError.code == CompassError.COMPASS_NOT_SUPPORTED) {
alert("不⽀支持罗盘功能。");
} else if(compassError.code == CompassError.COMPASS_INTERNAL_ERR)
{
alert("罗盘内部错误!");
} else {
alert("未知的朝向错误!");
}
}
77. watchOptions
• 查询设备观测的API⽅方法:
navigator.compass.watchHeading(onHeading
Success, onHeadingError, watchOptions);
function onDeviceReady() {
alert("onDeviceReady");
//设置观察者
//每秒四次读取罗盘数据 (250 milliseconds, .25 seconds)
var watchOptions = {
frequency : 250
};
watchID = navigator.compass.watchHeading(onHeadingSuccess,
onHeadingError, watchOptions);
}
82. Connection 代码⽰示例
function onDeviceReady() {
navigator.notification.alert("PhoneGap 就绪!");
//Add the online event listener
document.addEventListener("online", isOnline, false);
//Add the offline event listener
document.addEventListener("offline", isOffline, false);
}
function isOnline() {
//alert("isOnline");
var d = new Date();
$('#networkInfo').prepend("在线 (" + getConnectionTypeStr() + ")<br />");
}
function isOffline() {
//alert("isOffline");
var d = new Date();
$('#networkInfo').prepend("离线<br />");
}
function getConnectionTypeStr() {
//得到⺴⽹网络状态
var networkState = navigator.network.connection.type;
alert(networkState);
//返回表⽰示⺴⽹网络状态的字符串
//return states[networkState];
return networkState;
}
85. Contacts API简介
• PhoneGap Contacts API 为应⽤用提供了⼀一个到设备
联系⼈人数据库的访问接⼝口,可以被⽤用来从设备的
本地“联系⼈人”应⽤用创建,定位,编辑,拷⻉贝以及
删除联系⼈人记录。
• PhoneGap的Contacts API是W3C Contacts API 规范
的⼀一个实现。
87. 创建⼀一个联系⼈人
• 返回⼀一个新的Contact对象
function addContact() {
alert("Adding " + contactInfo.FullName + " to contacts application");
var contact = navigator.contacts.create();
contact.displayName = contactInfo.FullName;
contact.nickname = contactInfo.FullName;
var tmpName = new ContactName();
tmpName.givenName = contactInfo.FirstName;
tmpName.familyName = contactInfo.LastName;
tmpName.formatted = contactInfo.FullName;
contact.name = tmpName;
var phoneNums = [2];
phoneNums[0] = new ContactField('work', contactInfo.OfficePhone, false);
phoneNums[1] = new ContactField('mobile', contactInfo.MobilePhone, true);
contact.phoneNumbers = phoneNums;
var emailAddresses = [1];
emailAddresses[0] = new ContactField('home', contactInfo.EmailAddress, true);
contact.emails = emailAddresses;
// 保存到设备
contact.save(onContactSaveSuccess, onContactSaveError);
}
88. Contact对象
• id: A globally unique identifier. (DOMString)
• displayName: The name of this Contact, suitable for display to end-users.
(DOMString)
• name: An object containing all components of a persons name. (ContactName)
• nickname: A casual name to address the contact by. (DOMString)
• phoneNumbers: An array of all the contact's phone numbers. (ContactField[])
• emails: An array of all the contact's email addresses. (ContactField[])
• addresses: An array of all the contact's addresses. (ContactAddress[])
• ims: An array of all the contact's IM addresses. (ContactField[])
• organizations: An array of all the contact's organizations. (ContactOrganization[])
• birthday: The birthday of the contact. (Date)
• note: A note about the contact. (DOMString)
• photos: An array of the contact's photos. (ContactField[])
• categories: An array of all the contacts user defined categories. (ContactField[])
• urls: An array of web pages associated to the contact. (ContactField[])
89. 成功和失败的回调函数
function onContactSaveSuccess() {
alert(contactInfo.FullName + " 已经成功保存到设备联系⼈人数据库。");
}
function onContactSaveError(e) {
var msgText;
switch(e.code) {
case ContactError.UNKNOWN_ERROR:
msgText = "An Unknown Error was reported while saving the contact.";
break;
case ContactError.INVALID_ARGUMENT_ERROR:
msgText = "An invalid argument was used with the Contact API.";
break;
case ContactError.TIMEOUT_ERROR:
msgText = "Timeout Error.";
break;
case ContactError.PENDING_OPERATION_ERROR:
msgText = "Pending Operation Error.";
break;
case ContactError.IO_ERROR:
msgText = "IO Error.";
break;
case ContactError.NOT_SUPPORTED_ERROR:
msgText = "Not Supported Error.";
break;
case ContactError.PERMISSION_DENIED_ERROR:
msgText = "Permission Denied Error.";
91. 搜索联系⼈人 navigator.contacts.find(contactFields, contactSuccess,
contactError, contactFindOptions);
function searchContacts() {
alert("searchContacts");
$('#contacts').html('<p>Search Results</p>');
var searchStr = document.getElementById("editSearch").value;
var searchScope = document.getElementById("searchScope").selectedIndex;
var contactFields = [];
switch(searchScope) {
case 1:
contactFields = ['displayName', 'name', 'nickname'];
break;
case 2:
contactFields = ['streetAddress', 'locality', 'region', 'postalCode', 'country'];
break;
case 3:
contactFields = ['note'];
break;
default:
contactFields = ['*'];
}
//Populate the search options object
var searchOptions = {
filter : searchStr,
multiple : true,
};
//Execute the search
navigator.contacts.find(contactFields, onContactSearchSuccess, onContactSearchError,
searchOptions);
92. onContactSearchSuccess
function onContactSearchSuccess(contacts) {
var i, len, theList;
contactList = contacts;
len = contacts.length;
if(len > 0) {
theList = '<ul data-role="listview">';
for( i = 0, len; i < len; i += 1) {
if(contacts[i].displayName == null) {
theList += '<li><a onclick="showContact(' + i + ');">' +
contacts[i].name.familyName + ", " + contacts[i].name.givenName + '</a></li>';
} else {
theList += '<li><a onclick="showContact(' + i + ');">' +
contacts[i].displayName + '</a></li>';
}
}
theList += '</ul>';
$('#contacts').replaceWith(theList);
$.mobile.changePage("#contactList", "slide", false, true);
} else {
navigator.notification.alert('Search returned 0 results', null, 'Contact
Search');
}
}
96. Device API简介
PhoneGap Device 对象允许应⽤用访问关于应⽤用和运
⾏行⼀一个PhoneGap应⽤用的设备的有限数量的信息。
device.name: 根据平台的不同,有可能是设备⼚厂商
分配的名称或者是⼿手机⽤用户设置的名称.
device.cordova:构建应⽤用的PhoneGap的版本号;
device.platform: 移动设备平台的的名称;
device.uuid: universally unique identifier
device.version: 操作系统版本号
97. Device API Demo
function onDeviceReady() {
//得到要操作的DOM元素
var element =
document.getElementById("deviceInfo");
//替换成使⽤用设备信息
element.innerHTML =
"<b>device.name: " + device.name + br +
"<b>device.cordova:</b> " +
device.cordova + br +
"<b>device.platform:</b> " +
device.platform + br +
"<b>device.uuid:</b> " + device.uuid
+ br +
"<b>device.version:</b> " +
device.version + br;
}
99. Events API简介
PhoneGap Events API 可以让应⽤用程序为发⽣生在⽀支持
的smartphone设备上的不同的事件注册事件监听
器。
• deviceready 事件
• Application status 事件
• Network 事件
• Button 事件
101. deviceready Event
function onBodyLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady() {
navigator.notification.alert("PhoneGap就绪!");
}
document.addEventListener(“eventName”,
functionName, useCapture);
eventName: 事件名字符串
functionName:触发时调⽤用的⽅方法
useCapture:⼀一般是false
102. Application Stauts 事件
• foreground & background
• pause event & resume event
• 事件处理:数据库,⺴⽹网络,媒体播放...
function onDeviceReady() {
document.addEventListener("pause", processPause, false);
document.addEventListener("resume", processResume, false);
}
function processPause() {
pi.innerHTML = "Application paused.";
startTime = new Date();
}
function processResume() {
if(firstTime == true) {
firstTime = false;
pi.innerHTML = "Skipping first Resume.";
} else {
endTime = new Date();
timeDiff = (endTime - startTime) / 1000;
103. Network Status 事件
• online event
• offline event
function onDeviceReady() {
alert("onDeviceReady");
document.addEventListener("online", isOnline, false);
document.addEventListener("offline", isOffline, false);
}
function isOnline() {
var d = new Date();
$('#networkInfo').prepend("Online: " + d.toLocaleString() + "<br />");
}
function isOffline() {
var d = new Date();
$('#networkInfo').prepend("Offline: " + d.toLocaleString() + "<br />");
}
105. Button Event DemoCode
if((pName == "Android") || (pName == "3.0.0.100")) {
eventCount += 2;
//Android & BlackBerry only events
document.addEventListener("backbutton", onBackButton, false);
document.addEventListener("menubutton", onMenuButton, false);
}
if(pName == "Android") {
eventCount += 1;
//Android only event
document.addEventListener("searchbutton", onSearchButton, false);
}
if(pName == "3.0.0.100") {
eventCount += 4;
//BlackBerry only events
document.addEventListener("startcallbutton", onStartCallButton, false);
document.addEventListener("endcallbutton", onEndCallButton, false);
document.addEventListener("volumedownbutton", onVolumeUpButton, false);
document.addEventListener("volumeupbutton", onVolumeDownButton, false);
}
//did we register any event listeners?
if(eventCount < 1) {
//0, must be running on an iOS device
alert("Must be running on an iOS device.nNo event listeners registered");
} else {
//Android or BlackBerry
alert("Registered " + eventCount + " event listeners.");
}
}
107. File API简介
PhoneGap File API 提供给应⽤用程序对移动设备上的
临时⽂文件或者持久化⽂文件系统进⾏行访问的⽅方法。包
括:
locate, read , write, copy, move以及remove。
PhoneGap File API 基于部分W3C File API 规范实
现:Directories and System specification。
只提供了开发者最常⽤用的功能,并没有完全实现
W3C规范。
110. Accessing the Device’s File System
function processDir(fileSystemType) {
alert("processDir: " + fileSystemType);
window.requestFileSystem(fileSystemType, 1024 * 1024,
onGetFileSystemSuccess, onFileError);
}
<p>
选择⽂文件系统:
<input type="button" value="临时⽂文件"
onclick="processDir(LocalFileSystem.TEMPORARY);">
<input type="button" value="持久存储"
onclick="processDir(LocalFileSystem.PERSISTENT);">
</p>
111. Reading Directory Entries
var theFileSystem;
function processDir(fileSystemType) {
alert("processDir: " + fileSystemType);
window.requestFileSystem(fileSystemType, 1024 *
1024, onGetFileSystemSuccess, onFileError);
}
function onGetFileSystemSuccess(fs) {
alert("onGetFileSystemSuccess: " + fs.name);
//保存返回的⽂文件系统句柄
theFileSystem = fs;
//创建⼀一个Directory Reader
var dr = fs.root.createReader();
// 读取根⺫⽬目录内容
dr.readEntries(onDirReaderSuccess, onFileError);
}
DirectoryReader
112. onDirReaderSuccess
function onDirReaderSuccess(dirEntries) {
FileEntry or DirectoryEntry数组
theEntries = dirEntries;
var i, fl, len;
len = theEntries.length;
if(len > 0) {
for( i = 0; i < len; i++) {
if(theEntries[i].isDirectory == true) {
fl += '<li><a href="#" onclick="processEntry(' + i + ');">⺫⽬目录: ' +
theEntries[i].name + '</a></li>';
} else {
fl += '<li><a href="#" onclick="processEntry(' + i + ');">⽂文件: ' +
theEntries[i].name + '</a></li>';
}
}
} else {
fl = "<p>No entries found</p>";
$('#dirEntries').html(fl);
}
}
113. Accessing FileEntry and DirectoryEntry Properties
• isFile
• isDirectory
• name
• fullPath
function processEntry(entryIndex) {
theEntry = theEntries[entryIndex];
//FileInfo variable
var fi = "";
fi += startP + '<b>Name</b>: ' + theEntry.name + endP;
fi += startP + '<b>Full Path</b>: ' + theEntry.fullPath + endP;
fi += startP + '<b>URI</b>: ' + theEntry.toURI() + endP;
if(theEntry.isFile == true) {
fi += startP + 'The entry is a file' + endP;
} else {
fi += startP + 'The entry is a directory' + endP;
}
115. Writing Files
function writeFile() {
//随机⽣生成⼀一个⽂文件名
var theFileName = createRandomString(8) + '.txt';
theFileSystem.root.getFile(theFileName, {
create : true
}, onGetFileSuccess, onFileError);
}
function onGetFileSuccess(theFile) {
theFile.createWriter(onCreateWriterSuccess, onFileError);
}
function onCreateWriterSuccess(writer) {
writer.onwritestart = function(e) {
console.log("Write start");
};
writer.onwriteend = function(e) {
console.log("Write end");
};
writer.onwrite = function(e) {
console.log("Write completed");
};
writer.onerror = function(e) {
console.log("Write error: " + e.toString() + br);
};
writer.write("File created by PHoneGap File API: ");
writer.write("This is another line of text ");
writer.write(createRandomStory(25));
}
116. Reading Files
function viewFile() {
theEntry.file(onFileReaderSuccess, onFileError);
}
function onFileReaderSuccess(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
$('#readInfo').append("加载完成" + br);
$('#fileContents').text(e.target.result);
};
reader.onloadstart = function(e) {
$('#readInfo').append("开始加载" + br);
};
reader.onloaderror = function(e) {
$('#readInfo').append("加载错误: " + e.target.error.code + br);
};
reader.readAsText(file);
}
117. Deleting Files or Directories
function removeFile() {
theEntry.remove(onRemoveFileSuccess, onFileError);
}
function onRemoveFileSuccess(entry) {
alert("Successfully removed " + entry.name);
}
118. Copying Files or Directories
theEntry.copyTo(parentEntry, newName,
onSuccessFunction,
onErrorFunction);
parentEntry: 要拷⻉贝的⽂文件或⺫⽬目录
newName: ⺫⽬目标
119. Moving Files or Directories
theEntry.copyTo(parentEntry, newName,
onSuccessFunction,
onErrorFunction);
120. Uploading Files to a Server
var ft = new FileTransfer();
ft.upload(fileURI, serverURL,
onUploadSuccess, onUploadError,
fileUploadOptions);
126. Get Current Position
使⽤用Position对象返回⼀一个设备的当前位置
navigator.geolocation.getCurrentPosition(
onGeolocationSuccess,
[onGeolocationError],
[geolocationOptions]);
参数:
• onGeolocationSuccess: 成功时使⽤用当前位置回调
• onGeolocationError: 可选,出错时调⽤用
• geolocationOptions: 可选,geolocation选项
说明:
geolocation.getCurrentPosition是⼀一个异步调⽤用的函数。将设备的当前位置
作为⼀一个Position参数返回给geolocationSuccess函数。出错的时候,使⽤用
⼀一个PositionError对象回调geolocationError回调函数。
127. onGeolocationSuccess
Position Coordinates
位置的地理坐标的⼀一系列属性的描述
包含Position坐标和时间戳,由 属性:
geolocation API⽣生成。 latitude: ⼗十进制的纬度(Number)
longitude: ⼗十进制表⽰示的精度(Number)
属性:
altitude: 地⾯面海拔(Number)
coords:地理位置坐标的集合 accuracy: 经纬度坐标的精度,以⽶米为单位(Number)
(Coordinates) altitudeAccuracy: 以⽶米为单位的海拔坐标;
heading: 顺时针计数的正北⽅方向⾓角度
timestamp:coords⽣生成的时间戳 speed: 设备当前的地⾯面速度。
(Date) 说明:
Coordinates对象有Cordova创建,附加到Position对象。
注意:对于Android,海拔精度⺫⽬目前还不⽀支持。
function onLocationSuccess(loc) {
alert("onLocationSuccess");
var d = new Date(loc.timestamp);
lc.innerHTML = '<b>当前位置</b><hr /><b>纬度</b>: ' + loc.coords.latitude + '<br /
><b>经度</b>: ' + loc.coords.longitude + '<br /><b>⾼高度</b>: ' + loc.coords.altitude +
'<br /><b>精度</b>: ' + loc.coords.accuracy + '<br /><b>海拔精确度</b>: ' +
loc.coords.altitudeAccuracy + '<br /><b>航向</b>: ' + loc.coords.heading + '<br /><b>速度
</b>: ' + loc.coords.speed + '<br /><b>时间戳</b>: ' + d.toLocaleString();
}
129. geolocationOptions
⾃自定义抓取位置的选项
{ maximumAge: 3000, timeout: 5000, enableHighAccuracy: true}
选项:
enableHighAccuracy: 要求设备返回最精确的结果。默认情况下,设备会尝试使⽤用基于⺴⽹网络的
⽅方法返回Position。设置这个参数为true来告诉框架使⽤用更精确地⽅方法,⽐比如卫星定位系统。
timeout: 允许geolocation.getCurrentPosition和geolocation.watchPosition的最⻓长时间。如果在
指定时间内,geolocationSuccess回调没有被调⽤用,则geolocationError会被调⽤用,带有⼀一个
PositionError.TIMEOUT的错误码。和watchPosition⽅方法结合使⽤用的话,会每timeout时间调⽤用⼀一
次geolocationError回调。
maximumAge:不超过指定时间毫秒数的位置缓存。
var locOptions = {
timeout : 5000,
enableHighAccuracy : true
};
//获得当前位置
navigator.geolocation.getCurrentPosition(onLocationSuccess,
onLocationError, locOptions);
131. Setting a Watch
var watchId = navigator.geolocation.watchPosition(
geolocationSuccess,
[geolocationError],
[geolocationOptions]);
观察设备当前位置的变化
参数:
• geolocationSuccess: 成功带着当前位置回调;
• geolocationError: 可选,出错时回调;
• geolocationOptions: 可选,geolocation选项
返回:
String:返回⼀一个watch id,是watch position interval观察位置间隔的引⽤用。应该和
geolocation.clearWatch⼀一起使⽤用来停⽌止观察位置变化。
说明:
geolocation.watchPosition是⼀一个异步函数。当检测到位置变化时会返回设备的当前
位置。当设备取得⼀一个新的位置,geolocationSuccess回调被调⽤用,带着⼀一个Position
对象作为参数。如果出错了,geolocationError回调被调⽤用,带着PositionError对象。
132. Code of setting and canceling a Watch
//Geolocation Options
var locOptions = {
maximumAge : 10000,
timeout : 5000,
enableHighAccuracy : true
};
//增加观察者
watchID = navigator.geolocation.watchPosition(onLocationSuccess,
onLocationError, locOptions);
function cancelWatch() {
navigator.geolocation.clearWatch(watchID);
watchID = null;
}
134. Media API简介
PhoneGap Media API提供了在设备上录⾳音和播放⾳音
频⽂文件的能⼒力。
提⽰示:当前Media API的实现并没有遵循W3C的媒体
捕捉的规范,只是提供了⼀一个实现供⼤大家⽅方便使
⽤用。未来的实现将会遵循W3C有关媒体捕捉的规
范,并且有可能会弃⽤用现在的API。也就是上⾯面列
出来的这个。
137. 创建⼀一个Media对象
var media = new Media(mediaFileURI, onMediaSuccess,
[mediaError], [mediaStatus];
注意:这⾥里的onMediaSuccess不会在new Media完成后执⾏行,⽽而是会在
每次播放或者录⾳音完成后调⽤用。
new Media完成后,可以对media判断时⻓长或者读设当前位置,但是这些
操作都不会得到任何值,除⾮非已经开始播放。
// var fileName = "http://192.168.1.103/~tom/dan.mp3";
var fileName = "/android_asset/www/eye.mp3";
theMedia = new Media(fileName, onMediaSuccess, onMediaError,
onMediaStatus);
138. File URI
• ⽂文件既可以是本地⽂文件系统⽂文件,
• 也可以是located在⽂文件服务器的⽂文件;
• 或者是项⺫⽬目中的⽂文件。
var fileName = "/android_asset/www/eye.mp3";
var fileName = "http://192.168.1.103/~tom/dan.mp3";
139. MediaError
出错时⼀一个MediaError对象被返回给mediaError回调函数。
属性:
code:下⾯面列出的⼀一个预定义的错误码;
message:详细描述错误的错误消息。
常量:
MediaError.MEDIA_ERR_ABORTED
MediaError.MEDIA_ERR_NETWORK
MediaError.MEDIA_ERR_DECODE
MediaError.MEDIA_ERR_NONE_SUPPORTED
function onMediaError(e) {
var msgText = "Media error: " + e.message + "(" + e.code + ")";
console.log(msgText);
navigator.notification.alert(msgText, null, "Media Error");
}
140. statusCode
• 0: Media.MEDIA_NONE
• 1: Media.MEDIA_STARTING
• 2: Media.MEDIA_RUNNING
• 3: Media.MEDIA_PAUSED
• 4: Media.MEDIA_STOPPED
function onMediaStatus(statusCode) {
console.log("Status: " + statusCode);
alert("Status: " + statusCode);
}
142. Current Position
返回声⾳音⽂文件内的当前位置
media.getCurrentPosition(mediaSuccess, [mediaError]);
参数
mediaSuccess:带着以秒为单位的当前位置进⾏行回调。
mediaError:可选,出错时调⽤用。 需要设置⼀一个定时器来获取当前位置
说明:media.getCurrentPosition函数是⼀一个返回Media对象底层声⾳音⽂文件的当前位置的异
步函数。同时更新Media对象的_position参数。
function updateUI() {
console.log("updateUI");
theMedia.getCurrentPosition(onGetPosition, onMediaError);
}
function onGetPosition(filePos) {
console.log("onGetPosition");
//We won't have any information about the file until it's
// actually played. Update the counter on the page
$('#pos').html('时间: ' + Math.floor(filePos) + ' , 共: ' +
theMedia.getDuration() + ' seconds');
}
146. Pause
theMedia.pause();
暂停语⾳音播放的同步函数。
Notes: 如果在当前没有播放的Media对象上调⽤用
pause,不会报错。
function doPause() {
if(theMedia) {
console.log("doPause");
//Pause media play
theMedia.pause();
window.clearInterval(theTimer);
}
}
147. Stop
theMedia.stop();
停⽌止播放声⾳音的同步⽂文件
Note: 和pause⼀一样,在没有正在播放的Media对象上调⽤用
stop,也不会报错。
function doStop() {
if(theMedia) {
console.log("doStop");
//停掉计时器
theTimer = null;
//停⽌止播放
theMedia.stop();
}
}
156. notification.alert
显
⽰示
⼀一
个
按
钮
显⽰示⼀一个⾃自定义的alert或者对话框。 对于这个功能⼤大
多数的Cordova的实现使⽤用⼀一个本地的对话框。然⽽而,有些
平台简单的使⽤用浏览器的alert功能,这些alert的可定制性就
稍微差⼀一些。
navigator.notification.alert(message_t
ext, callback_function, [“title”],
[“button_text”])
• message: 对话框消息(String)
• alertCallback:当对话框消息释放的时候调⽤用的回调⽅方
法(Function)
• title: 对话框标题(String)(可选,默认是:”Alert”)
• buttonName: 按钮名称(String)(可选,默认:”OK”)
157. alert sample
<div data-role="fieldcontain">
<label for="msgText">消息⽂文本:</label>
<input type="text" name="msgText" id="msgText" value="这是
⼀一条⽂文本消息!" />
<div data-role="controlgroup" data-type="horizontal">
<input type="button" value="Alert" onclick="doAlert();">
<input type="button" value="Confirm"
onclick="doConfirm();">
</div>
</div>
function doAlert() {
msgText = document.getElementById('msgText').value;
navigator.notification.alert(msgText, onDoAlert,
"Alert⽰示例", "Click Me!");
}
function onDoAlert() {
alert("Click Me Button!");
}
158. 显
notification.confirm
⽰示
⼀一
个
或
多
个
显⽰示⼀一个⾃自定义的确认对话框
按
钮
navigator.notification.confirm(message_text,
callback_confirm, [“title”], [“button_text_array”])
• message: 对话框消息(String)
• confirmCallback: 回调⽅方法,带着被按下按钮的索引(1,2,或3)(Function)
• title: 对话框标题(String)(可选,默认是:“Confirm”)
• buttonLabels:逗号分割的按钮标签字符串(String)(可选,默认是:“OK,
Cancel”)
• 说明
• notification.confirm函数显⽰示⼀一个⽐比浏览器的确认框更具定制化的本地对话框。
• confirmCallback
• 当⽤用户按下了确认框的按钮之⼀一时confirmCallback会被调⽤用。
• 这个回调函数带有⼀一个buttonIndex(数值)参数,是被按下按钮的索引。需要指出的是这
⾥里使⽤用的索引是以1开始的,所以这⾥里的值是1,2,3这样。
159. confirmation代码
function doConfirm() {
msgText =
document.getElementById('msgText').value;
navigator.notification.confirm(msgText,
onDoConfirm, "Confirmation⽰示例", "Yes, No, Maybe");
}
function onDoConfirm(btnNum) {
if(btnNum == "1") {
alert("Thanks for saying yes!");
} else {
alert("Too bad, you said no.");
}
}
164. Storage API简介
• ⼤大多数HTML5兼容的浏览器都提供给Web
Application从本地存储设施读写key/value键值对
的能⼒力,以及从本地SQL 数据库读写数据的能
⼒力。这两种能⼒力都不是HTML直接提供的,⽽而是通
过在浏览器内运⾏行⽀支持的JavaScript代码实现的。
• PhoneGap Storage API 是基于 W3C Web SQL
Database 规范以及 W3C Web Storage API 规范。有
些设备已经提供了这个规范的⼀一个实现。对于这
些设备,使⽤用其内置的⽀支持⽽而不是使⽤用Cordova的
实现来替代。对于不⽀支持存储的设备,Cordova的
实现是兼容W3C规范的。
166. localStorage - UI
<section id="config" data-role="page" >
<header data-role="header">
<h1>MT 配置</h1>
</header>
<div data-role="content">
<div data-role="fieldcontain">
<legend>
每⽇日清除旧的记录吗?
</legend>
<label for="purgeStatus">启⽤用清除</
label>
<input type="checkbox"
name="purgeStatus" id="purgeStatus" />
<label for="purgeInterval">清除间隔</
label>
<input type="number"
id="purgeInterval" name="purgeInterval" />
天
</div>
<input type="button" value="保存配置"
onclick="saveConfig();">
167. localStorage - setItem
function saveConfig() {
//将配置设置写⼊入localStorage
window.localStorage.setItem("purgeStatus",
document.getElementById("purgeStatus").checked);
window.localStorage.setItem("purgeInterval",
document.getElementById("purgeInterval").value);
//切换回主界⾯面
$.mobile.changePage("#main", "flip", false, false);
}
168. localStorage - getItem
purgeStatus =
window.localStorage.getItem("purgeStatus");
purgeInterval =
window.localStorage.getItem("purgeInterval");
if(purgeStatus == "true") {
$("#purgeStatus").attr("checked", true);
$("#purgeInterval").attr('value',
purgeInterval);
doPurge(purgeInterval);
}
173. openDatabase
var dbShell = window.openDatabase(database_name, database_version, database_displayname, database_size);
这个⽅方法将创建⼀一个新的 SQLite 数据库,并且返回⼀一个Database对
象。使⽤用这个Database对象来操作数据。
• 参数
• database_name:数据库名(写⼊入设备内存的数据库⽂文件名)
• database_version:数据库版本(应⽤用可以据此进⾏行升级操作)
• database_displayname:数据库显⽰示名
• database_size:分配给数据库的空间⼤大⼩小(字节)
//创建或者打开数据库
console.log("Opening database");
theDB = window.openDatabase("mtDB", "1.0", "Mileage Tracker", 3 * 1024 *
1024);
console.log("Checking theDB");
if(theDB) {
174. Database对象
包含允许⽤用户操作数据库的⽅方法
• ⽅方法
• transaction: 运⾏行⼀一个数据库事务;
• changeVersion: 允许脚本在更新schema的同时⾃自动地确认版本号并且更
改。
• 说明
• Database对象从window.openDatabase()的调⽤用返回。
function saveRecord() {
console.log("Entering saveRecord");
//这⾥里可以做⼀一些数据验证⼯工作,⽐比如⽇日期要有效,numMiles > 0
//保存记录
theDB.transaction(insertRecord, onTxError, onTxSuccess);
console.log("Leaving saveRecord");
}
176. executeSql
function insertRecord(tx) {
console.log("Entering insertRecord");
//创建⼀一个新的Date对象来持有⽤用户输⼊入的⽇日期
var tmpDate = new Date.fromString(document.getElementById("editDate").value);
console.log("Date: " + tmpDate.valueOf());
var tmpMiles = document.getElementById("editNumMiles").value;
console.log("Miles: " + tmpMiles);
var tmpNotes = document.getElementById("editNotes").value;
console.log("Notes: " + tmpNotes);
var sqlStr = 'INSERT INTO MILEAGE (tripDate, miles, notes) VALUES (?, ?, ?)';
console.log(sqlStr);
tx.executeSql(sqlStr, [tmpDate.valueOf(), tmpMiles, tmpNotes], onSqlSuccess,
onSqlError);
// 使⽤用jQuery重置表单的输⼊入值
var blankVal = {
value : ''
};
$("#editNumMiles").attr(blankVal);
$("#editNotes").attr(blankVal);
console.log("Leaving insertRecord");
}
177. SQLResultSet
当⼀一个SQLTransaction的executeSql⽅方法被调⽤用时,会带着
SQLResultSet对象调⽤用它的回调函数。
• 属性
• insertId:SQLResultSet对象的SQL语句插⼊入到数据库中的⾏行的⾏行编号。
• rowsAffected: 被SQL语句影响的数据库记录的⾏行数。如果该语句没有影响到
任何⾏行,rowsAffected会被设置为0。
• rows: 表⽰示返回的⾏行的SQLResultSetRowList。如果没有⾏行被返回,这个对
象为空。
• 说明:如果Insert语句成功执⾏行的话,insertId是插⼊入⾏行的编号。如果
这条SQL语句不是insert语句,insertId属性不会被设置。对于insert或
update语句⽽而⾔言,会返回受影响的记录数。最后⼀一个属性的类型是
SQLResultSetList,包含的是SQL的select语句返回的数据。
178. SQLResultSet - insert
function onSqlSuccess(tx, res) {
console.log("SQL: success");
if(res) {
console.log(res);
alert("insertId = " + res.insertId);
alert("rowsAffected = " + res.rowsAffected);
}
}
function onSqlError(tx, err) {
console.log("Entering onSqlError");
var msgText;
if(err) {
msgText = "SQL: " + err.message + " (" + err.code + ")";
} else {
msgText = "SQL: Unknown error";
}
console.error(msgText);
alert(msgText);
console.log("Leaving onSqlError");
}
180. SQLResultSetList - query
function onQuerySuccess(tx, results) {
console.log("Entering onQuerySuccess");
if(results.rows) {
console.log("Rows: " + results.rows);
var htmlStr = "";
var len = results.rows.length;
if(len > 0) {
for(var i = 0; i < len; i++) {
var theDate = new Date(results.rows.item(i).tripDate);
htmlStr += '<b>⽇日期:</b> ' + theDate.toDateString() + '<br />';
var numMiles = results.rows.item(i).miles;
if(numMiles > 1) {
htmlStr += '<b>英⾥里:</b> ' + numMiles + ' miles<br />';
} else {
htmlStr += '<b>英⾥里:</b> 1 mile<br />';
}
//检查是否有备注
var theNotes = results.rows.item(i).notes;
if(theNotes.length > 0) {
htmlStr += '<b>备注:</b> ' + theNotes + '<br />';
}
htmlStr += '<hr />';
}
181. SQLError
当操作数据库有错误发⽣生时抛出SQLError错误。
• 属性
• code:下⾯面列出来的预定义错误之⼀一
• message: 错误描述
• 常量
• SQLError.UNKNOWN_ERR,未知错误
• SQLError.DATABASE_ERR,数据库错误
• SQLError.VERSION_ERR,版本错误
• SQLError.TOO_LARGE_ERR,超⼤大
• SQLError.QUOTA_ERR,超限
• SQLError.SYNTAX_ERR,语法错误
• SQLError.CONSTRAIN_ERR,限制错误
• SQLError.TIMEOUT_ERR,超时错误
183. 扩展阅读
• PersistenceJS - persistencejs.org
• lawnchair - http://brian.io/lawnchair/
• DOM Storage - https://developer.mozilla.org/en-US/
docs/DOM/Storage