Compare commits

...

17 Commits

Author SHA1 Message Date
macdonst
1d79b6617b JavaScript cleanup to pass jsHint
I did my best to clean up the JavaScript so it would pass through jsHint more cleanly.  There still are issues but there are a lot fewer now.  This helped to make the JS code more consistent.
2011-05-21 02:31:24 +08:00
macdonst
6c3eefe6f9 Issue #85: window.openDatabase throws DOM Exception 18 on Android 3.1
Instead of checking the userAgent catch the exception.  If we do get an exception it will setup our version of Droid Db.
2011-05-21 02:13:03 +08:00
macdonst
2177cd0a39 Moving navigator.connection to navigator.device.connection
Android 2.2 introduces the navigation.connection interface but it does not work properly in WebView.  So in order to get the proper connection information we had to implement our own connection interface which is accessible at navigator.network.connection.
2011-05-18 03:26:31 +08:00
macdonst
6618015151 Fixing a number of issues in File API
Issue #82: The RandomAccessFile class in Android's version of Java does not write non-ASCII characters very well.  I've switched to using a FileOutputStream which seems to work just great.  Tested by myself and folks from Egypt and the Netherlands.

Issue #87: Fixed a problem where the file errors were being returned as evt.target.result.code.code.
2011-05-17 22:11:38 +08:00
macdonst
e99f75d59b Issue #85: window.openDatabase throws DOM Exception 18 on Android 3.1
The way were were detecting we were on an Android 3.0 device was not applicable for Android 3.1.  I've made and update so that any Android 3.X device will use our implementation of web sql databases instead of the built in one which thows a security error.
2011-05-16 23:14:24 +08:00
macdonst
ab8cfe01d0 Removing generated code from project
framework/gen/com/phonegap/R.java
2011-05-16 10:37:25 +08:00
macdonst
e84c59d23c Merge pull request #78 from kernelsandirs/master
Added Media.seekTo(int milliseconds);

Merging this code in now and making some notes to enhance the Media class.
2011-05-15 19:32:02 -07:00
macdonst
e81fc239a7 Setting defaults in Media Capture
Some tests of Media Capture were failing as the CaptureAudio/Image/VideoOptions objects did not have defaults set.
2011-05-14 01:10:18 +08:00
Bryce Curtis
839c577243 Need to use EclairClient for 3.x devices too. This fixes the HTML5 geolocation problem on Android 3.x. 2011-05-10 11:44:09 -05:00
macdonst
116169a4c5 Issue #79: FileWriter.seek() is broken in 0.9.5.
The FileEntry.createWriter() method passes in a FileEntry object instead of a File object. As a result the FileWriter.length was not being set properly so when you do a writer.seek(writer.length) it would go to 0, so your next write would overwrite your file.

In order to fix this issue the FileEntry.createWriter() method now makes a call to FileEntry.file() to get the correct file size.  The File object is now passed to the FileWriter constructor.
2011-05-07 00:41:57 +08:00
macdonst
346ed60f0d Android 2.2+ supports W3C Connection API
For Android version 2.2 or better the navigator.connection object already
exists. If this case we should immediately fire the onPhoneGapConnectionReady
event so we don't tie up the 'deviceready' event.
2011-05-06 04:22:38 +08:00
defrex
bde59adc04 Add docs and fixed to pass through the Google Closure Compiler without warnings 2011-05-04 16:00:03 -07:00
kernelsandirs
ffbc010d7b Added Media.seekTo(int milliseconds); 2011-05-04 11:51:26 -07:00
macdonst
bdadbbc339 Implement W3C Network Information API
Adding a new object to navigator called 'connection'.  Users can query the
connection object to find out what type of network, if any, the device is
connected to.  The connection object will be updated each time there is a
connectivity change on the device.
2011-05-04 22:23:16 +08:00
kernelsandirs
b94eedaf07 Added Media.seekTo(int milliseconds); 2011-05-03 21:27:08 -07:00
macdonst
58ecac335b Capture modifications:
Renaming supportedAudioFormats to supportedAudioModes.
Renaming supportedImageFormats to supportedImageModes.
Renaming supportedVideoFormats to supportedVideoModes.
Adding copywrite header to the Capture.java file.
2011-05-03 00:12:19 +08:00
macdonst
fd8bb2f671 Issue 72: Contact.Save: onSuccess callback is called when contact is not saved. 2011-04-29 02:08:25 +08:00
27 changed files with 993 additions and 732 deletions

View File

@@ -3,24 +3,25 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("accelerometer")) {
PhoneGap.addResource("accelerometer");
Acceleration = function(x, y, z) {
/** @constructor */
var Acceleration = function(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.timestamp = new Date().getTime();
}
};
/**
* This class provides access to device accelerometer data.
* @constructor
*/
Accelerometer = function() {
var Accelerometer = function() {
/**
* The last known acceleration. type=Acceleration()
@@ -31,7 +32,7 @@ Accelerometer = function() {
* List of accelerometer watch timers
*/
this.timers = {};
}
};
Accelerometer.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"];
@@ -122,4 +123,4 @@ PhoneGap.addConstructor(function() {
navigator.accelerometer = new Accelerometer();
}
});
};
}

View File

@@ -11,8 +11,9 @@ PhoneGap.addResource("app");
/**
* Constructor
* @constructor
*/
App = function() {};
var App = function() {};
/**
* Clear the resource cache.
@@ -23,7 +24,7 @@ App.prototype.clearCache = function() {
/**
* Load the url into the webview.
*
*
* @param url The URL to load
* @param props Properties that can be passed in to the activity:
* wait: int => wait msec before loading URL
@@ -33,7 +34,7 @@ App.prototype.clearCache = function() {
* loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
* errorUrl: URL => URL to load if there's an error loading specified URL with loadUrl(). Should be a local URL such as file:///android_asset/www/error.html");
* keepRunning: boolean => enable app to keep running in background
*
*
* Example:
* App app = new App();
* app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
@@ -59,7 +60,7 @@ App.prototype.clearHistory = function() {
/**
* Add a class that implements a service.
*
*
* @param serviceType
* @param className
*/
@@ -70,10 +71,10 @@ App.prototype.addService = function(serviceType, className) {
/**
* Override the default behavior of the Android back button.
* If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
*
*
* Note: The user should not have to call this method. Instead, when the user
* registers for the "backbutton" event, this is automatically done.
*
*
* @param override T=override, F=cancel override
*/
App.prototype.overrideBackbutton = function(override) {
@@ -90,4 +91,4 @@ App.prototype.exitApp = function() {
PhoneGap.addConstructor(function() {
navigator.app = window.app = new App();
});
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("camera")) {
@@ -14,7 +14,7 @@ PhoneGap.addResource("camera");
*
* @constructor
*/
Camera = function() {
var Camera = function() {
this.successCallback = null;
this.errorCallback = null;
this.options = null;
@@ -94,4 +94,4 @@ PhoneGap.addConstructor(function() {
navigator.camera = new Camera();
}
});
};
}

View File

@@ -6,11 +6,58 @@
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("capture")) {
PhoneGap.addResource("capture");
/**
* Represents a single file.
*
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*/
var MediaFile = function(name, fullPath, type, lastModifiedDate, size){
this.name = name || null;
this.fullPath = fullPath || null;
this.type = type || null;
this.lastModifiedDate = lastModifiedDate || null;
this.size = size || 0;
};
/**
* Launch device camera application for recording video(s).
*
* @param {Function} successCB
* @param {Function} errorCB
*/
MediaFile.prototype.getFormatData = function(successCallback, errorCallback){
PhoneGap.exec(successCallback, errorCallback, "Capture", "getFormatData", [this.fullPath, this.type]);
};
/**
* MediaFileData encapsulates format information of a media file.
*
* @param {DOMString} codecs
* @param {long} bitrate
* @param {long} height
* @param {long} width
* @param {float} duration
*/
var MediaFileData = function(codecs, bitrate, height, width, duration){
this.codecs = codecs || null;
this.bitrate = bitrate || 0;
this.height = height || 0;
this.width = width || 0;
this.duration = duration || 0;
};
/**
* The CaptureError interface encapsulates all errors in the Capture API.
*/
function CaptureError() {
this.code = null;
var CaptureError = function(){
this.code = null;
};
// Capture error codes
@@ -23,165 +70,122 @@ CaptureError.CAPTURE_NOT_SUPPORTED = 20;
/**
* The Capture interface exposes an interface to the camera and microphone of the hosting device.
*/
function Capture() {
this.supportedAudioFormats = [];
this.supportedImageFormats = [];
this.supportedVideoFormats = [];
var Capture = function(){
this.supportedAudioModes = [];
this.supportedImageModes = [];
this.supportedVideoModes = [];
};
/**
* Launch audio recorder application for recording audio clip(s).
*
*
* @param {Function} successCB
* @param {Function} errorCB
* @param {CaptureAudioOptions} options
*/
Capture.prototype.captureAudio = function(successCallback, errorCallback, options) {
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureAudio", [options]);
Capture.prototype.captureAudio = function(successCallback, errorCallback, options){
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureAudio", [options]);
};
/**
* Launch camera application for taking image(s).
*
*
* @param {Function} successCB
* @param {Function} errorCB
* @param {CaptureImageOptions} options
*/
Capture.prototype.captureImage = function(successCallback, errorCallback, options) {
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureImage", [options]);
Capture.prototype.captureImage = function(successCallback, errorCallback, options){
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureImage", [options]);
};
/**
* Launch camera application for taking image(s).
*
*
* @param {Function} successCB
* @param {Function} errorCB
* @param {CaptureImageOptions} options
*/
Capture.prototype._castMediaFile = function(pluginResult) {
var mediaFiles = [];
var i;
for (i=0; i<pluginResult.message.length; i++) {
var mediaFile = new MediaFile();
mediaFile.name = pluginResult.message[i].name;
mediaFile.fullPath = pluginResult.message[i].fullPath;
mediaFile.type = pluginResult.message[i].type;
mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate;
mediaFile.size = pluginResult.message[i].size;
mediaFiles.push(mediaFile);
}
pluginResult.message = mediaFiles;
return pluginResult;
Capture.prototype._castMediaFile = function(pluginResult){
var mediaFiles = [];
var i;
for (i = 0; i < pluginResult.message.length; i++) {
var mediaFile = new MediaFile();
mediaFile.name = pluginResult.message[i].name;
mediaFile.fullPath = pluginResult.message[i].fullPath;
mediaFile.type = pluginResult.message[i].type;
mediaFile.lastModifiedDate = pluginResult.message[i].lastModifiedDate;
mediaFile.size = pluginResult.message[i].size;
mediaFiles.push(mediaFile);
}
pluginResult.message = mediaFiles;
return pluginResult;
};
/**
* Launch device camera application for recording video(s).
*
*
* @param {Function} successCB
* @param {Function} errorCB
* @param {CaptureVideoOptions} options
*/
Capture.prototype.captureVideo = function(successCallback, errorCallback, options) {
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureVideo", [options]);
Capture.prototype.captureVideo = function(successCallback, errorCallback, options){
PhoneGap.exec(successCallback, errorCallback, "Capture", "captureVideo", [options]);
};
/**
* Encapsulates a set of parameters that the capture device supports.
*/
function ConfigurationData() {
// The ASCII-encoded string in lower case representing the media type.
this.type;
// The height attribute represents height of the image or video in pixels.
// In the case of a sound clip this attribute has value 0.
this.height = 0;
// The width attribute represents width of the image or video in pixels.
// In the case of a sound clip this attribute has value 0
this.width = 0;
var ConfigurationData = function(){
// The ASCII-encoded string in lower case representing the media type.
this.type = null;
// The height attribute represents height of the image or video in pixels.
// In the case of a sound clip this attribute has value 0.
this.height = 0;
// The width attribute represents width of the image or video in pixels.
// In the case of a sound clip this attribute has value 0
this.width = 0;
};
/**
* Encapsulates all image capture operation configuration options.
*/
function CaptureImageOptions() {
// Upper limit of images user can take. Value must be equal or greater than 1.
this.limit = 1;
// The selected image mode. Must match with one of the elements in supportedImageModes array.
this.mode;
var CaptureImageOptions = function(){
// Upper limit of images user can take. Value must be equal or greater than 1.
this.limit = 1;
// The selected image mode. Must match with one of the elements in supportedImageModes array.
this.mode = null;
};
/**
* Encapsulates all video capture operation configuration options.
*/
function CaptureVideoOptions() {
// Upper limit of videos user can record. Value must be equal or greater than 1.
this.limit;
// Maximum duration of a single video clip in seconds.
this.duration;
// The selected video mode. Must match with one of the elements in supportedVideoModes array.
this.mode;
var CaptureVideoOptions = function(){
// Upper limit of videos user can record. Value must be equal or greater than 1.
this.limit = 1;
// Maximum duration of a single video clip in seconds.
this.duration = 0;
// The selected video mode. Must match with one of the elements in supportedVideoModes array.
this.mode = null;
};
/**
* Encapsulates all audio capture operation configuration options.
*/
function CaptureAudioOptions() {
// Upper limit of sound clips user can record. Value must be equal or greater than 1.
this.limit;
// Maximum duration of a single sound clip in seconds.
this.duration;
// The selected audio mode. Must match with one of the elements in supportedAudioModes array.
this.mode;
var CaptureAudioOptions = function(){
// Upper limit of sound clips user can record. Value must be equal or greater than 1.
this.limit = 1;
// Maximum duration of a single sound clip in seconds.
this.duration = 0;
// The selected audio mode. Must match with one of the elements in supportedAudioModes array.
this.mode = null;
};
/**
* Represents a single file.
*
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*/
function MediaFile(name, fullPath, type, lastModifiedDate, size) {
this.name = name || null;
this.fullPath = fullPath || null;
this.type = type || null;
this.lastModifiedDate = lastModifiedDate || null;
this.size = size || 0;
}
/**
* Launch device camera application for recording video(s).
*
* @param {Function} successCB
* @param {Function} errorCB
*/
MediaFile.prototype.getFormatData = function(successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "Capture", "getFormatData", [this.fullPath, this.type]);
};
/**
* MediaFileData encapsulates format information of a media file.
*
* @param {DOMString} codecs
* @param {long} bitrate
* @param {long} height
* @param {long} width
* @param {float} duration
*/
function MediaFileData(codecs, bitrate, height, width, duration) {
this.codecs = codecs || null;
this.bitrate = bitrate || 0;
this.height = height || 0;
this.width = width || 0;
this.duration = duration || 0;
}
PhoneGap.addConstructor(function() {
if (typeof navigator.device === "undefined") {
navigator.device = window.device = new Device();
}
if (typeof navigator.device.capture === "undefined") {
navigator.device.capture = window.device.capture = new Capture();
}
PhoneGap.addConstructor(function(){
if (typeof navigator.device === "undefined") {
navigator.device = window.device = new Device();
}
if (typeof navigator.device.capture === "undefined") {
navigator.device.capture = window.device.capture = new Capture();
}
});
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("compass")) {
@@ -13,7 +13,7 @@ PhoneGap.addResource("compass");
* This class provides access to device Compass data.
* @constructor
*/
Compass = function() {
var Compass = function() {
/**
* The last known Compass position.
*/
@@ -116,4 +116,4 @@ PhoneGap.addConstructor(function() {
navigator.compass = new Compass();
}
});
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("contact")) {
@@ -11,22 +11,23 @@ PhoneGap.addResource("contact");
/**
* Contains information about a single contact.
* @constructor
* @param {DOMString} id unique identifier
* @param {DOMString} displayName
* @param {ContactName} name
* @param {DOMString} nickname
* @param {ContactField[]} phoneNumbers array of phone numbers
* @param {ContactField[]} emails array of email addresses
* @param {ContactAddress[]} addresses array of addresses
* @param {ContactField[]} ims instant messaging user ids
* @param {ContactOrganization[]} organizations
* @param {Array.<ContactField>} phoneNumbers array of phone numbers
* @param {Array.<ContactField>} emails array of email addresses
* @param {Array.<ContactAddress>} addresses array of addresses
* @param {Array.<ContactField>} ims instant messaging user ids
* @param {Array.<ContactOrganization>} organizations
* @param {DOMString} revision date contact was last updated
* @param {DOMString} birthday contact's birthday
* @param {DOMString} gender contact's gender
* @param {DOMString} note user notes about contact
* @param {ContactField[]} photos
* @param {ContactField[]} categories
* @param {ContactField[]} urls contact's web sites
* @param {Array.<ContactField>} photos
* @param {Array.<ContactField>} categories
* @param {Array.<ContactField>} urls contact's web sites
* @param {DOMString} timezone the contacts time zone
*/
var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
@@ -53,7 +54,8 @@ var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, a
/**
* ContactError.
* An error code assigned by an implementation when an error has occurred
* An error code assigned by an implementation when an error has occurreds
* @constructor
*/
var ContactError = function() {
this.code=null;
@@ -152,6 +154,7 @@ Contact.prototype.save = function(successCB, errorCB) {
/**
* Contact name.
* @constructor
* @param formatted
* @param familyName
* @param givenName
@@ -170,6 +173,7 @@ var ContactName = function(formatted, familyName, givenName, middle, prefix, suf
/**
* Generic contact field.
* @constructor
* @param {DOMString} id unique identifier, should only be set by native code
* @param type
* @param value
@@ -184,6 +188,7 @@ var ContactField = function(type, value, pref) {
/**
* Contact address.
* @constructor
* @param {DOMString} id unique identifier, should only be set by native code
* @param formatted
* @param streetAddress
@@ -204,6 +209,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
/**
* Contact organization.
* @constructor
* @param {DOMString} id unique identifier, should only be set by native code
* @param name
* @param dept
@@ -222,6 +228,7 @@ var ContactOrganization = function(name, dept, title) {
/**
* Represents a group of Contacts.
* @constructor
*/
var Contacts = function() {
this.inProgress = false;
@@ -258,10 +265,10 @@ Contacts.prototype.create = function(properties) {
};
/**
* This function returns and array of contacts. It is required as we need to convert raw
* JSON objects into concrete Contact objects. Currently this method is called after
* This function returns and array of contacts. It is required as we need to convert raw
* JSON objects into concrete Contact objects. Currently this method is called after
* navigator.service.contacts.find but before the find methods success call back.
*
*
* @param jsonArray an array of JSON Objects that need to be converted to Contact objects.
* @returns an array of Contact objects
*/
@@ -277,6 +284,7 @@ Contacts.prototype.cast = function(pluginResult) {
/**
* ContactFindOptions.
* @constructor
* @param filter used to match contacts against
* @param multiple boolean used to determine if more than one contact should be returned
* @param updatedSince return only contact records that have been updated on or after the given time
@@ -298,4 +306,4 @@ PhoneGap.addConstructor(function() {
navigator.service.contacts = new Contacts();
}
});
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
// TODO: Needs to be commented
@@ -11,6 +11,9 @@
if (!PhoneGap.hasResource("crypto")) {
PhoneGap.addResource("crypto");
/**
* @constructor
*/
var Crypto = function() {
};
@@ -37,4 +40,4 @@ PhoneGap.addConstructor(function() {
navigator.Crypto = new Crypto();
}
});
};
}

View File

@@ -14,7 +14,7 @@ PhoneGap.addResource("device");
* phone, etc.
* @constructor
*/
Device = function() {
var Device = function() {
this.available = PhoneGap.available;
this.platform = null;
this.version = null;
@@ -72,7 +72,7 @@ Device.prototype.getInfo = function(successCallback, errorCallback) {
*/
Device.prototype.overrideBackButton = function() {
console.log("Device.overrideBackButton() is deprecated. Use App.overrideBackbutton(true).");
app.overrideBackbutton(true);
navigator.app.overrideBackbutton(true);
};
/*
@@ -83,7 +83,7 @@ Device.prototype.overrideBackButton = function() {
*/
Device.prototype.resetBackButton = function() {
console.log("Device.resetBackButton() is deprecated. Use App.overrideBackbutton(false).");
app.overrideBackbutton(false);
navigator.app.overrideBackbutton(false);
};
/*
@@ -94,7 +94,7 @@ Device.prototype.resetBackButton = function() {
*/
Device.prototype.exitApp = function() {
console.log("Device.exitApp() is deprecated. Use App.exitApp().");
app.exitApp();
navigator.app.exitApp();
};
PhoneGap.addConstructor(function() {
@@ -102,4 +102,4 @@ PhoneGap.addConstructor(function() {
navigator.device = window.device = new Device();
}
});
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("file")) {
@@ -11,10 +11,11 @@ PhoneGap.addResource("file");
/**
* This class provides some useful information about a file.
* This is the fields returned when navigator.fileMgr.getFileProperties()
* This is the fields returned when navigator.fileMgr.getFileProperties()
* is called.
* @constructor
*/
FileProperties = function(filePath) {
var FileProperties = function(filePath) {
this.filePath = filePath;
this.size = 0;
this.lastModifiedDate = null;
@@ -22,14 +23,15 @@ FileProperties = function(filePath) {
/**
* Represents a single file.
*
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*
* @constructor
* @param name {DOMString} name of the file, without path information
* @param fullPath {DOMString} the full path of the file, including the name
* @param type {DOMString} mime type
* @param lastModifiedDate {Date} last modified date
* @param size {Number} size of the file in bytes
*/
File = function(name, fullPath, type, lastModifiedDate, size) {
var File = function(name, fullPath, type, lastModifiedDate, size) {
this.name = name || null;
this.fullPath = fullPath || null;
this.type = type || null;
@@ -37,7 +39,8 @@ File = function(name, fullPath, type, lastModifiedDate, size) {
this.size = size || 0;
};
FileError = function() {
/** @constructor */
var FileError = function() {
this.code = null;
};
@@ -62,7 +65,8 @@ FileError.PATH_EXISTS_ERR = 12;
// File manager
//-----------------------------------------------------------------------------
FileMgr = function() {
/** @constructor */
var FileMgr = function() {
};
FileMgr.prototype.getFileProperties = function(filePath) {
@@ -126,8 +130,9 @@ PhoneGap.addConstructor(function() {
* For Android:
* The root directory is the root of the file system.
* To read from the SD card, the file name is "sdcard/my_file.txt"
* @constructor
*/
FileReader = function() {
var FileReader = function() {
this.fileName = "";
this.readyState = 0;
@@ -164,7 +169,7 @@ FileReader.prototype.abort = function() {
var error = new FileError();
error.code = error.ABORT_ERR;
this.error = error;
// If error callback
if (typeof this.onerror === "function") {
this.onerror({"type":"error", "target":this});
@@ -244,9 +249,7 @@ FileReader.prototype.readAsText = function(file, encoding) {
}
// Save error
var fileError = new FileError();
fileError.code = e;
me.error = fileError;
me.error = e;
// If onerror callback
if (typeof me.onerror === "function") {
@@ -328,9 +331,7 @@ FileReader.prototype.readAsDataURL = function(file) {
}
// Save error
var fileError = new FileError();
fileError.code = e;
me.error = fileError;
me.error = e;
// If onerror callback
if (typeof me.onerror === "function") {
@@ -378,11 +379,12 @@ FileReader.prototype.readAsArrayBuffer = function(file) {
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
*
*
* @constructor
* @param file {File} File object containing file properties
* @param append if true write to the end of the file, otherwise overwrite the file
*/
FileWriter = function(file) {
var FileWriter = function(file) {
this.fileName = "";
this.length = 0;
if (file) {
@@ -420,13 +422,13 @@ FileWriter.prototype.abort = function() {
// check for invalid state
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
throw FileError.INVALID_STATE_ERR;
}
}
// set error
var error = new FileError(), evt;
error.code = error.ABORT_ERR;
this.error = error;
// If error callback
if (typeof this.onerror === "function") {
this.onerror({"type":"error", "target":this});
@@ -435,7 +437,7 @@ FileWriter.prototype.abort = function() {
if (typeof this.onabort === "function") {
this.oneabort({"type":"abort", "target":this});
}
this.readyState = FileWriter.DONE;
// If write end callback
@@ -446,7 +448,7 @@ FileWriter.prototype.abort = function() {
/**
* Writes data to the file
*
*
* @param text to be written
*/
FileWriter.prototype.write = function(text) {
@@ -476,10 +478,10 @@ FileWriter.prototype.write = function(text) {
return;
}
// So if the user wants to keep appending to the file
me.length = Math.max(me.length, me.position + r);
// position always increases by bytes written because file would be extended
me.position += r;
// The length of the file is now where we are done writing.
me.length = me.position;
// If onwrite callback
if (typeof me.onwrite === "function") {
@@ -505,9 +507,7 @@ FileWriter.prototype.write = function(text) {
}
// Save error
var fileError = new FileError();
fileError.code = e;
me.error = fileError;
me.error = e;
// If onerror callback
if (typeof me.onerror === "function") {
@@ -526,13 +526,13 @@ FileWriter.prototype.write = function(text) {
};
/**
/**
* Moves the file pointer to the location specified.
*
* If the offset is a negative number the position of the file
* pointer is rewound. If the offset is greater than the file
* size the position is set to the end of the file.
*
*
* If the offset is a negative number the position of the file
* pointer is rewound. If the offset is greater than the file
* size the position is set to the end of the file.
*
* @param offset is the location to move the file pointer to.
*/
FileWriter.prototype.seek = function(offset) {
@@ -544,12 +544,12 @@ FileWriter.prototype.seek = function(offset) {
if (!offset) {
return;
}
// See back from end of file.
if (offset < 0) {
this.position = Math.max(offset + this.length, 0);
}
// Offset is bigger then file size so set position
// Offset is bigger then file size so set position
// to the end of the file.
else if (offset > this.length) {
this.position = this.length;
@@ -558,12 +558,12 @@ FileWriter.prototype.seek = function(offset) {
// to start writing.
else {
this.position = offset;
}
}
};
/**
/**
* Truncates the file to the size specified.
*
*
* @param size to chop the file at.
*/
FileWriter.prototype.truncate = function(size) {
@@ -620,9 +620,7 @@ FileWriter.prototype.truncate = function(size) {
}
// Save error
var fileError = new FileError();
fileError.code = e;
me.error = fileError;
me.error = e;
// If onerror callback
if (typeof me.onerror === "function") {
@@ -640,169 +638,69 @@ FileWriter.prototype.truncate = function(size) {
);
};
LocalFileSystem = function() {
};
// File error codes
LocalFileSystem.TEMPORARY = 0;
LocalFileSystem.PERSISTENT = 1;
LocalFileSystem.RESOURCE = 2;
LocalFileSystem.APPLICATION = 3;
/**
* Requests a filesystem in which to store application data.
*
* @param {int} type of file system being requested
* @param {Function} successCallback is called with the new FileSystem
* @param {Function} errorCallback is called with a FileError
*/
LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) {
if (type < 0 || type > 3) {
if (typeof errorCallback == "function") {
errorCallback({
"code": FileError.SYNTAX_ERR
});
}
}
else {
PhoneGap.exec(successCallback, errorCallback, "File", "requestFileSystem", [type, size]);
}
};
/**
*
* @param {DOMString} uri referring to a local file in a filesystem
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "resolveLocalFileSystemURI", [uri]);
};
/**
* This function returns and array of contacts. It is required as we need to convert raw
* JSON objects into concrete Contact objects. Currently this method is called after
* navigator.service.contacts.find but before the find methods success call back.
*
* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects.
* @returns an entry
*/
LocalFileSystem.prototype._castFS = function(pluginResult) {
var entry = null;
entry = new DirectoryEntry();
entry.isDirectory = pluginResult.message.root.isDirectory;
entry.isFile = pluginResult.message.root.isFile;
entry.name = pluginResult.message.root.name;
entry.fullPath = pluginResult.message.root.fullPath;
pluginResult.message.root = entry;
return pluginResult;
}
LocalFileSystem.prototype._castEntry = function(pluginResult) {
var entry = null;
if (pluginResult.message.isDirectory) {
console.log("This is a dir");
entry = new DirectoryEntry();
}
else if (pluginResult.message.isFile) {
console.log("This is a file");
entry = new FileEntry();
}
entry.isDirectory = pluginResult.message.isDirectory;
entry.isFile = pluginResult.message.isFile;
entry.name = pluginResult.message.name;
entry.fullPath = pluginResult.message.fullPath;
pluginResult.message = entry;
return pluginResult;
}
LocalFileSystem.prototype._castEntries = function(pluginResult) {
var entries = pluginResult.message;
var retVal = [];
for (i=0; i<entries.length; i++) {
retVal.push(window.localFileSystem._createEntry(entries[i]));
}
pluginResult.message = retVal;
return pluginResult;
}
LocalFileSystem.prototype._createEntry = function(castMe) {
var entry = null;
if (castMe.isDirectory) {
console.log("This is a dir");
entry = new DirectoryEntry();
}
else if (castMe.isFile) {
console.log("This is a file");
entry = new FileEntry();
}
entry.isDirectory = castMe.isDirectory;
entry.isFile = castMe.isFile;
entry.name = castMe.name;
entry.fullPath = castMe.fullPath;
return entry;
}
LocalFileSystem.prototype._castDate = function(pluginResult) {
if (pluginResult.message.modificationTime) {
var modTime = new Date(pluginResult.message.modificationTime);
pluginResult.message.modificationTime = modTime;
}
else if (pluginResult.message.lastModifiedDate) {
var file = new File();
file.size = pluginResult.message.size;
file.type = pluginResult.message.type;
file.name = pluginResult.message.name;
file.fullPath = pluginResult.message.fullPath;
file.lastModifedDate = new Date(pluginResult.message.lastModifiedDate);
pluginResult.message = file;
}
return pluginResult;
}
/**
* Information about the state of the file or directory
*
*
* @constructor
* {Date} modificationTime (readonly)
*/
Metadata = function() {
var Metadata = function() {
this.modificationTime=null;
};
/**
* Supplies arguments to methods that lookup or create files and directories
*
* @param {boolean} create file or directory if it doesn't exist
*
* @constructor
* @param {boolean} create file or directory if it doesn't exist
* @param {boolean} exclusive if true the command will fail if the file or directory exists
*/
Flags = function(create, exclusive) {
var Flags = function(create, exclusive) {
this.create = create || false;
this.exclusive = exclusive || false;
};
/**
* An interface representing a file system
*
*
* @constructor
* {DOMString} name the unique name of the file system (readonly)
* {DirectoryEntry} root directory of the file system (readonly)
*/
FileSystem = function() {
var FileSystem = function() {
this.name = null;
this.root = null;
};
/**
* An interface that lists the files and directories in a directory.
* @constructor
*/
var DirectoryReader = function(fullPath){
this.fullPath = fullPath || null;
};
/**
* Returns a list of entries from a directory.
*
* @param {Function} successCallback is called with a list of entries
* @param {Function} errorCallback is called with a FileError
*/
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "readEntries", [this.fullPath]);
};
/**
* An interface representing a directory on the file system.
*
*
* @constructor
* {boolean} isFile always false (readonly)
* {boolean} isDirectory always true (readonly)
* {DOMString} name of the directory, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the directory (readonly)
* {FileSystem} filesystem on which the directory resides (readonly)
*/
DirectoryEntry = function() {
var DirectoryEntry = function() {
this.isFile = false;
this.isDirectory = true;
this.name = null;
@@ -812,7 +710,7 @@ DirectoryEntry = function() {
/**
* Copies a directory to a new location
*
*
* @param {DirectoryEntry} parent the directory to which to copy the entry
* @param {DOMString} newName the new name of the entry, defaults to the current name
* @param {Function} successCallback is called with the new entry
@@ -824,7 +722,7 @@ DirectoryEntry.prototype.copyTo = function(parent, newName, successCallback, err
/**
* Looks up the metadata of the entry
*
*
* @param {Function} successCallback is called with a Metadata object
* @param {Function} errorCallback is called with a FileError
*/
@@ -834,7 +732,7 @@ DirectoryEntry.prototype.getMetadata = function(successCallback, errorCallback)
/**
* Gets the parent of the entry
*
*
* @param {Function} successCallback is called with a parent entry
* @param {Function} errorCallback is called with a FileError
*/
@@ -844,7 +742,7 @@ DirectoryEntry.prototype.getParent = function(successCallback, errorCallback) {
/**
* Moves a directory to a new location
*
*
* @param {DirectoryEntry} parent the directory to which to move the entry
* @param {DOMString} newName the new name of the entry, defaults to the current name
* @param {Function} successCallback is called with the new entry
@@ -856,7 +754,7 @@ DirectoryEntry.prototype.moveTo = function(parent, newName, successCallback, err
/**
* Removes the entry
*
*
* @param {Function} successCallback is called with no parameters
* @param {Function} errorCallback is called with a FileError
*/
@@ -866,7 +764,7 @@ DirectoryEntry.prototype.remove = function(successCallback, errorCallback) {
/**
* Returns a URI that can be used to identify this entry.
*
*
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
* @return uri
*/
@@ -883,7 +781,7 @@ DirectoryEntry.prototype.createReader = function(successCallback, errorCallback)
/**
* Creates or looks up a directory
*
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
* @param {Flags} options to create or excluively create the directory
* @param {Function} successCallback is called with the new entry
@@ -895,7 +793,7 @@ DirectoryEntry.prototype.getDirectory = function(path, options, successCallback,
/**
* Creates or looks up a file
*
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
* @param {Flags} options to create or excluively create the file
* @param {Function} successCallback is called with the new entry
@@ -907,7 +805,7 @@ DirectoryEntry.prototype.getFile = function(path, options, successCallback, erro
/**
* Deletes a directory and all of it's contents
*
*
* @param {Function} successCallback is called with no parameters
* @param {Function} errorCallback is called with a FileError
*/
@@ -915,33 +813,17 @@ DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCall
PhoneGap.exec(successCallback, errorCallback, "File", "removeRecursively", [this.fullPath]);
};
/**
* An interface that lists the files and directories in a directory.
*/
DirectoryReader = function(fullPath){
this.fullPath = fullPath || null;
};
/**
* Returns a list of entries from a directory.
*
* @param {Function} successCallback is called with a list of entries
* @param {Function} errorCallback is called with a FileError
*/
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "readEntries", [this.fullPath]);
}
/**
* An interface representing a directory on the file system.
*
*
* @constructor
* {boolean} isFile always true (readonly)
* {boolean} isDirectory always false (readonly)
* {DOMString} name of the file, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the file (readonly)
* {FileSystem} filesystem on which the directory resides (readonly)
*/
FileEntry = function() {
var FileEntry = function() {
this.isFile = true;
this.isDirectory = false;
this.name = null;
@@ -951,7 +833,7 @@ FileEntry = function() {
/**
* Copies a file to a new location
*
*
* @param {DirectoryEntry} parent the directory to which to copy the entry
* @param {DOMString} newName the new name of the entry, defaults to the current name
* @param {Function} successCallback is called with the new entry
@@ -963,7 +845,7 @@ FileEntry.prototype.copyTo = function(parent, newName, successCallback, errorCal
/**
* Looks up the metadata of the entry
*
*
* @param {Function} successCallback is called with a Metadata object
* @param {Function} errorCallback is called with a FileError
*/
@@ -973,7 +855,7 @@ FileEntry.prototype.getMetadata = function(successCallback, errorCallback) {
/**
* Gets the parent of the entry
*
*
* @param {Function} successCallback is called with a parent entry
* @param {Function} errorCallback is called with a FileError
*/
@@ -983,7 +865,7 @@ FileEntry.prototype.getParent = function(successCallback, errorCallback) {
/**
* Moves a directory to a new location
*
*
* @param {DirectoryEntry} parent the directory to which to move the entry
* @param {DOMString} newName the new name of the entry, defaults to the current name
* @param {Function} successCallback is called with the new entry
@@ -995,7 +877,7 @@ FileEntry.prototype.moveTo = function(parent, newName, successCallback, errorCal
/**
* Removes the entry
*
*
* @param {Function} successCallback is called with no parameters
* @param {Function} errorCallback is called with a FileError
*/
@@ -1005,7 +887,7 @@ FileEntry.prototype.remove = function(successCallback, errorCallback) {
/**
* Returns a URI that can be used to identify this entry.
*
*
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
* @return uri
*/
@@ -1015,29 +897,31 @@ FileEntry.prototype.toURI = function(mimeType) {
/**
* Creates a new FileWriter associated with the file that this FileEntry represents.
*
*
* @param {Function} successCallback is called with the new FileWriter
* @param {Function} errorCallback is called with a FileError
*/
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
var writer = new FileWriter(this.fullPath);
if (writer.fileName == null || writer.fileName == "") {
if (typeof errorCallback == "function") {
errorCallback({
"code": FileError.INVALID_STATE_ERR
});
}
}
if (typeof successCallback == "function") {
successCallback(writer);
}
this.file(function(filePointer) {
var writer = new FileWriter(filePointer);
if (writer.fileName === null || writer.fileName === "") {
if (typeof errorCallback == "function") {
errorCallback({
"code": FileError.INVALID_STATE_ERR
});
}
}
if (typeof successCallback == "function") {
successCallback(writer);
}
}, errorCallback);
};
/**
* Returns a File that represents the current state of the file that this FileEntry represents.
*
*
* @param {Function} successCallback is called with the new File object
* @param {Function} errorCallback is called with a FileError
*/
@@ -1045,6 +929,127 @@ FileEntry.prototype.file = function(successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "getFileMetadata", [this.fullPath]);
};
/** @constructor */
var LocalFileSystem = function() {
};
// File error codes
LocalFileSystem.TEMPORARY = 0;
LocalFileSystem.PERSISTENT = 1;
LocalFileSystem.RESOURCE = 2;
LocalFileSystem.APPLICATION = 3;
/**
* Requests a filesystem in which to store application data.
*
* @param {int} type of file system being requested
* @param {Function} successCallback is called with the new FileSystem
* @param {Function} errorCallback is called with a FileError
*/
LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) {
if (type < 0 || type > 3) {
if (typeof errorCallback == "function") {
errorCallback({
"code": FileError.SYNTAX_ERR
});
}
}
else {
PhoneGap.exec(successCallback, errorCallback, "File", "requestFileSystem", [type, size]);
}
};
/**
*
* @param {DOMString} uri referring to a local file in a filesystem
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, "File", "resolveLocalFileSystemURI", [uri]);
};
/**
* This function returns and array of contacts. It is required as we need to convert raw
* JSON objects into concrete Contact objects. Currently this method is called after
* navigator.service.contacts.find but before the find methods success call back.
*
* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects.
* @returns an entry
*/
LocalFileSystem.prototype._castFS = function(pluginResult) {
var entry = null;
entry = new DirectoryEntry();
entry.isDirectory = pluginResult.message.root.isDirectory;
entry.isFile = pluginResult.message.root.isFile;
entry.name = pluginResult.message.root.name;
entry.fullPath = pluginResult.message.root.fullPath;
pluginResult.message.root = entry;
return pluginResult;
};
LocalFileSystem.prototype._castEntry = function(pluginResult) {
var entry = null;
if (pluginResult.message.isDirectory) {
console.log("This is a dir");
entry = new DirectoryEntry();
}
else if (pluginResult.message.isFile) {
console.log("This is a file");
entry = new FileEntry();
}
entry.isDirectory = pluginResult.message.isDirectory;
entry.isFile = pluginResult.message.isFile;
entry.name = pluginResult.message.name;
entry.fullPath = pluginResult.message.fullPath;
pluginResult.message = entry;
return pluginResult;
};
LocalFileSystem.prototype._castEntries = function(pluginResult) {
var entries = pluginResult.message;
var retVal = [];
for (var i=0; i<entries.length; i++) {
retVal.push(window.localFileSystem._createEntry(entries[i]));
}
pluginResult.message = retVal;
return pluginResult;
};
LocalFileSystem.prototype._createEntry = function(castMe) {
var entry = null;
if (castMe.isDirectory) {
console.log("This is a dir");
entry = new DirectoryEntry();
}
else if (castMe.isFile) {
console.log("This is a file");
entry = new FileEntry();
}
entry.isDirectory = castMe.isDirectory;
entry.isFile = castMe.isFile;
entry.name = castMe.name;
entry.fullPath = castMe.fullPath;
return entry;
};
LocalFileSystem.prototype._castDate = function(pluginResult) {
if (pluginResult.message.modificationTime) {
var modTime = new Date(pluginResult.message.modificationTime);
pluginResult.message.modificationTime = modTime;
}
else if (pluginResult.message.lastModifiedDate) {
var file = new File();
file.size = pluginResult.message.size;
file.type = pluginResult.message.type;
file.name = pluginResult.message.name;
file.fullPath = pluginResult.message.fullPath;
file.lastModifedDate = new Date(pluginResult.message.lastModifiedDate);
pluginResult.message = file;
}
return pluginResult;
};
/**
* Add the FileSystem interface into the browser.
*/
@@ -1055,4 +1060,4 @@ PhoneGap.addConstructor(function() {
if(typeof window.requestFileSystem == "undefined") window.requestFileSystem = pgLocalFileSystem.requestFileSystem;
if(typeof window.resolveLocalFileSystemURI == "undefined") window.resolveLocalFileSystemURI = pgLocalFileSystem.resolveLocalFileSystemURI;
});
};
}

View File

@@ -1,9 +1,9 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("filetransfer")) {
@@ -11,13 +11,15 @@ PhoneGap.addResource("filetransfer");
/**
* FileTransfer uploads a file to a remote server.
* @constructor
*/
FileTransfer = function() {};
var FileTransfer = function() {};
/**
* FileUploadResult
* @constructor
*/
FileUploadResult = function() {
var FileUploadResult = function() {
this.bytesSent = 0;
this.responseCode = null;
this.response = null;
@@ -25,8 +27,9 @@ FileUploadResult = function() {
/**
* FileTransferError
* @constructor
*/
FileTransferError = function() {
var FileTransferError = function() {
this.code = null;
};
@@ -35,13 +38,13 @@ FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
/**
* Given an absolute file path, uploads a file on the device to a remote server
* Given an absolute file path, uploads a file on the device to a remote server
* using a multipart HTTP request.
* @param filePath {String} Full path of the file on the device
* @param server {String} URL of the server to receive the file
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
*/
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, debug) {
@@ -61,21 +64,22 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
params = {};
}
}
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug]);
};
/**
* Options to customize the HTTP request used to upload files.
* @constructor
* @param fileKey {String} Name of file request parameter.
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
* @param params {Object} Object with key: value params to send to the server.
*/
FileUploadOptions = function(fileKey, fileName, mimeType, params) {
var FileUploadOptions = function(fileKey, fileName, mimeType, params) {
this.fileKey = fileKey || null;
this.fileName = fileName || null;
this.mimeType = mimeType || null;
this.params = params || null;
};
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("geolocation")) {
@@ -13,7 +13,7 @@ PhoneGap.addResource("geolocation");
* This class provides access to device GPS data.
* @constructor
*/
Geolocation = function() {
var Geolocation = function() {
// The last known GPS position.
this.lastPosition = null;
@@ -25,10 +25,11 @@ Geolocation = function() {
/**
* Position error object
*
* @constructor
* @param code
* @param message
*/
PositionError = function(code, message) {
var PositionError = function(code, message) {
this.code = code;
this.message = message;
};
@@ -194,4 +195,4 @@ PhoneGap.addConstructor(function() {
Geolocation.usingPhoneGap = true;
}
});
};
}

View File

@@ -3,69 +3,16 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("media")) {
PhoneGap.addResource("media");
/**
* List of media objects.
* PRIVATE
*/
PhoneGap.mediaObjects = {};
/**
* Object that receives native callbacks.
* PRIVATE
*/
PhoneGap.Media = function() {};
/**
* Get the media object.
* PRIVATE
*
* @param id The media object id (string)
*/
PhoneGap.Media.getMediaObject = function(id) {
return PhoneGap.mediaObjects[id];
};
/**
* Audio has status update.
* PRIVATE
*
* @param id The media object id (string)
* @param status The status code (int)
* @param msg The status message (string)
*/
PhoneGap.Media.onStatus = function(id, msg, value) {
var media = PhoneGap.mediaObjects[id];
// If state update
if (msg === Media.MEDIA_STATE) {
if (value === Media.MEDIA_STOPPED) {
if (media.successCallback) {
media.successCallback();
}
}
if (media.statusCallback) {
media.statusCallback(value);
}
}
else if (msg === Media.MEDIA_DURATION) {
media._duration = value;
}
else if (msg === Media.MEDIA_ERROR) {
if (media.errorCallback) {
media.errorCallback(value);
}
}
};
/**
* This class provides access to the device media, interfaces to both sound and video
*
* @constructor
* @param src The file name or url to play
* @param successCallback The callback to be called when the file is done playing or recording.
* successCallback() - OPTIONAL
@@ -76,7 +23,7 @@ PhoneGap.Media.onStatus = function(id, msg, value) {
* @param positionCallback The callback to be called when media position has changed.
* positionCallback(long position) - OPTIONAL
*/
Media = function(src, successCallback, errorCallback, statusCallback, positionCallback) {
var Media = function(src, successCallback, errorCallback, statusCallback, positionCallback) {
// successCallback optional
if (successCallback && (typeof successCallback !== "function")) {
@@ -131,7 +78,7 @@ Media.MEDIA_MSG = ["None", "Starting", "Running", "Paused", "Stopped"];
* This class contains information about any Media errors.
* @constructor
*/
MediaError = function() {
var MediaError = function() {
this.code = null;
this.message = "";
};
@@ -155,6 +102,13 @@ Media.prototype.stop = function() {
return PhoneGap.exec(null, null, "Media", "stopPlayingAudio", [this.id]);
};
/**
* Seek or jump to a new time in the track..
*/
Media.prototype.seekTo = function(milliseconds) {
PhoneGap.exec(null, null, "Media", "seekToAudio", [this.id, milliseconds]);
};
/**
* Pause playing audio file.
*/
@@ -174,8 +128,6 @@ Media.prototype.getDuration = function() {
/**
* Get position of audio.
*
* @return
*/
Media.prototype.getCurrentPosition = function(success, fail) {
PhoneGap.exec(success, fail, "Media", "getCurrentPositionAudio", [this.id]);
@@ -201,4 +153,59 @@ Media.prototype.stopRecord = function() {
Media.prototype.release = function() {
PhoneGap.exec(null, null, "Media", "release", [this.id]);
};
/**
* List of media objects.
* PRIVATE
*/
PhoneGap.mediaObjects = {};
/**
* Object that receives native callbacks.
* PRIVATE
* @constructor
*/
PhoneGap.Media = function() {};
/**
* Get the media object.
* PRIVATE
*
* @param id The media object id (string)
*/
PhoneGap.Media.getMediaObject = function(id) {
return PhoneGap.mediaObjects[id];
};
/**
* Audio has status update.
* PRIVATE
*
* @param id The media object id (string)
* @param status The status code (int)
* @param msg The status message (string)
*/
PhoneGap.Media.onStatus = function(id, msg, value) {
var media = PhoneGap.mediaObjects[id];
// If state update
if (msg === Media.MEDIA_STATE) {
if (value === Media.MEDIA_STOPPED) {
if (media.successCallback) {
media.successCallback();
}
}
if (media.statusCallback) {
media.statusCallback(value);
}
}
else if (msg === Media.MEDIA_DURATION) {
media._duration = value;
}
else if (msg === Media.MEDIA_ERROR) {
if (media.errorCallback) {
media.errorCallback(value);
}
}
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("network")) {
@@ -13,7 +13,7 @@ PhoneGap.addResource("network");
* This class contains information about any NetworkStatus.
* @constructor
*/
NetworkStatus = function() {
var NetworkStatus = function() {
//this.code = null;
//this.message = "";
};
@@ -26,7 +26,7 @@ NetworkStatus.REACHABLE_VIA_WIFI_NETWORK = 2;
* This class provides access to device Network data (reachability).
* @constructor
*/
Network = function() {
var Network = function() {
/**
* The last known Network status.
* { hostName: string, ipAddress: string,
@@ -59,9 +59,54 @@ Network.prototype.isReachable = function(uri, callback, options) {
PhoneGap.exec(callback, null, "Network Status", "isReachable", [uri, isIpAddress]);
};
/**
* This class contains information about the current network Connection.
* @constructor
*/
var Connection = function() {
this.type = null;
this.homeNW = null;
this.currentNW = null;
var me = this;
this.getInfo(
function(info) {
me.type = info.type;
me.homeNW = info.homeNW;
me.currentNW = info.currentNW;
PhoneGap.onPhoneGapConnectionReady.fire();
},
function(e) {
console.log("Error initializing Network Connection: " + e);
});
};
Connection.UNKNOWN = 0;
Connection.ETHERNET = 1;
Connection.WIFI = 2;
Connection.CELL_2G = 3;
Connection.CELL_3G = 4;
Connection.CELL_4G = 5;
Connection.NONE = 20;
/**
* Get connection info
*
* @param {Function} successCallback The function to call when the Connection data is available
* @param {Function} errorCallback The function to call when there is an error getting the Connection data. (OPTIONAL)
*/
Connection.prototype.getInfo = function(successCallback, errorCallback) {
// Get info
PhoneGap.exec(successCallback, errorCallback, "Network Status", "getConnectionInfo", []);
};
PhoneGap.addConstructor(function() {
if (typeof navigator.network === "undefined") {
navigator.network = new Network();
}
if (typeof navigator.network.connection === "undefined") {
navigator.network.connection = new Connection();
}
});
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("notification")) {
@@ -11,8 +11,9 @@ PhoneGap.addResource("notification");
/**
* This class provides access to notifications on the device.
* @constructor
*/
Notification = function() {
var Notification = function() {
};
/**
@@ -118,4 +119,4 @@ PhoneGap.addConstructor(function() {
navigator.notification = new Notification();
}
});
};
}

View File

@@ -1,7 +1,7 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010-2011, IBM Corporation
*/
@@ -33,7 +33,7 @@ if (typeof PhoneGap === "undefined") {
*/
if (typeof(DeviceInfo) !== 'object') {
DeviceInfo = {};
var DeviceInfo = {};
}
/**
@@ -76,6 +76,7 @@ PhoneGap.addResource = function(name) {
/**
* Custom pub-sub channel that can have functions subscribed to it
* @constructor
*/
PhoneGap.Channel = function (type)
{
@@ -87,7 +88,7 @@ PhoneGap.Channel = function (type)
};
/**
* Subscribes the given function to the channel. Any time that
* Subscribes the given function to the channel. Any time that
* Channel.fire is called so too will the function.
* Optionally specify an execution context for the function
* and a guid that can be used to stop subscribing to the channel.
@@ -119,7 +120,7 @@ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
_this.unsubscribe(g);
};
if (this.fired) {
if (typeof c === "object" && f instanceof Function) { f = PhoneGap.close(c, f); }
if (typeof c === "object" && f instanceof Function) { f = PhoneGap.close(c, f); }
f.apply(this, this.fireArgs);
} else {
g = this.subscribe(m);
@@ -127,7 +128,7 @@ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) {
return g;
};
/**
/**
* Unsubscribes the function with the given guid from the channel.
*/
PhoneGap.Channel.prototype.unsubscribe = function(g) {
@@ -136,7 +137,7 @@ PhoneGap.Channel.prototype.unsubscribe = function(g) {
delete this.handlers[g];
};
/**
/**
* Calls all functions subscribed to this channel.
*/
PhoneGap.Channel.prototype.fire = function(e) {
@@ -229,7 +230,7 @@ PhoneGap.addPlugin = function(name, obj) {
};
/**
* onDOMContentLoaded channel is fired when the DOM content
* onDOMContentLoaded channel is fired when the DOM content
* of the page has been parsed.
*/
PhoneGap.onDOMContentLoaded = new PhoneGap.Channel('onDOMContentLoaded');
@@ -257,6 +258,12 @@ PhoneGap.onPhoneGapReady = new PhoneGap.Channel('onPhoneGapReady');
*/
PhoneGap.onPhoneGapInfoReady = new PhoneGap.Channel('onPhoneGapInfoReady');
/**
* onPhoneGapConnectionReady channel is fired when the PhoneGap connection properties
* has been set.
*/
PhoneGap.onPhoneGapConnectionReady = new PhoneGap.Channel('onPhoneGapConnectionReady');
/**
* onResume channel is fired when the PhoneGap native code
* resumes.
@@ -271,7 +278,7 @@ PhoneGap.onPause = new PhoneGap.Channel('onPause');
/**
* onDestroy channel is fired when the PhoneGap native code
* is destroyed. It is used internally.
* is destroyed. It is used internally.
* Window.onunload should be used by the user.
*/
PhoneGap.onDestroy = new PhoneGap.Channel('onDestroy');
@@ -281,7 +288,7 @@ PhoneGap.onDestroy.subscribeOnce(function() {
PhoneGap.shuttingDown = false;
// _nativeReady is global variable that the native side can set
// to signify that the native code is ready. It is a global since
// to signify that the native code is ready. It is a global since
// it may be called before any PhoneGap JS is ready.
if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); }
@@ -293,7 +300,7 @@ PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady');
// Array of channels that must fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsArray = [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady];
PhoneGap.deviceReadyChannelsArray = [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady, PhoneGap.onPhoneGapConnectionReady];
// Hashtable of user defined channels that must also fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsMap = {};
@@ -317,7 +324,7 @@ PhoneGap.waitForInitialization = function(feature) {
* Indicate that initialization code has completed and the feature is ready to be used.
*
* @param feature {String} The unique feature name
*/
*/
PhoneGap.initializationComplete = function(feature) {
var channel = PhoneGap.deviceReadyChannelsMap[feature];
if (channel) {
@@ -355,7 +362,7 @@ PhoneGap.Channel.join(function() {
// Fire onDeviceReady event once all constructors have run and PhoneGap info has been
// received from native side, and any user defined initialization channels.
PhoneGap.Channel.join(function() {
// Turn off app loading dialog
navigator.notification.activityStop();
@@ -386,18 +393,18 @@ document.addEventListener = function(evt, handler, capture) {
}
} else if (e === 'pause') {
PhoneGap.onPause.subscribe(handler);
}
}
else {
// If subscribing to Android backbutton
if (e === 'backbutton') {
PhoneGap.exec(null, null, "App", "overrideBackbutton", [true]);
}
}
PhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
}
};
// Intercept calls to document.removeEventListener and watch for events that
// Intercept calls to document.removeEventListener and watch for events that
// are generated by PhoneGap native code
PhoneGap.m_document_removeEventListener = document.removeEventListener;
@@ -407,7 +414,7 @@ document.removeEventListener = function(evt, handler, capture) {
// If unsubscribing to Android backbutton
if (e === 'backbutton') {
PhoneGap.exec(null, null, "App", "overrideBackbutton", [false]);
}
}
PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture);
};
@@ -426,14 +433,14 @@ PhoneGap.fireEvent = function(type) {
* The restriction on ours is that it must be an array of simple types.
*
* @param args
* @return
* @return {String}
*/
PhoneGap.stringify = function(args) {
if (typeof JSON === "undefined") {
var s = "[";
var i, type, start, name, nameType, a;
for (i = 0; i < args.length; i++) {
if (args[i] != null) {
if (args[i] !== null) {
if (i > 0) {
s = s + ",";
}
@@ -458,7 +465,7 @@ PhoneGap.stringify = function(args) {
// don't copy the functions
s = s + '""';
} else if (args[i][name] instanceof Object) {
s = s + this.stringify(args[i][name]);
s = s + PhoneGap.stringify(args[i][name]);
} else {
s = s + '"' + args[i][name] + '"';
}
@@ -484,41 +491,41 @@ PhoneGap.stringify = function(args) {
* Does a deep clone of the object.
*
* @param obj
* @return
* @return {Object}
*/
PhoneGap.clone = function(obj) {
var i, retVal;
if(!obj) {
return obj;
}
if(obj instanceof Array){
retVal = [];
for(i = 0; i < obj.length; ++i){
retVal.push(PhoneGap.clone(obj[i]));
}
return retVal;
}
if (obj instanceof Function) {
return obj;
}
if(!(obj instanceof Object)){
return obj;
}
if(!obj) {
return obj;
}
if(obj instanceof Array){
retVal = [];
for(i = 0; i < obj.length; ++i){
retVal.push(PhoneGap.clone(obj[i]));
}
return retVal;
}
if (obj instanceof Function) {
return obj;
}
if(!(obj instanceof Object)){
return obj;
}
if (obj instanceof Date) {
return obj;
}
retVal = {};
for(i in obj){
if(!(i in retVal) || retVal[i] !== obj[i]) {
retVal[i] = PhoneGap.clone(obj[i]);
}
}
return retVal;
retVal = {};
for(i in obj){
if(!(i in retVal) || retVal[i] !== obj[i]) {
retVal[i] = PhoneGap.clone(obj[i]);
}
}
return retVal;
};
PhoneGap.callbackId = 0;
@@ -538,7 +545,7 @@ PhoneGap.callbackStatus = {
/**
* Execute a PhoneGap command. It is up to the native side whether this action is synch or async.
* Execute a PhoneGap command. It is up to the native side whether this action is synch or async.
* The native side can return:
* Synchronous: PluginResult object as a JSON string
* Asynchrounous: Empty string ""
@@ -549,7 +556,7 @@ PhoneGap.callbackStatus = {
* @param {Function} fail The fail callback
* @param {String} service The name of the service to use
* @param {String} action Action to be run in PhoneGap
* @param {String[]} [args] Zero or more arguments to pass to the method
* @param {Array.<String>} [args] Zero or more arguments to pass to the method
*/
PhoneGap.exec = function(success, fail, service, action, args) {
try {
@@ -557,13 +564,13 @@ PhoneGap.exec = function(success, fail, service, action, args) {
if (success || fail) {
PhoneGap.callbacks[callbackId] = {success:success, fail:fail};
}
var r = prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
var r = prompt(PhoneGap.stringify(args), "gap:"+PhoneGap.stringify([service, action, callbackId, true]));
// If a result was returned
if (r.length > 0) {
eval("var v="+r+";");
// If status is OK, then return value back to caller
if (v.status === PhoneGap.callbackStatus.OK) {
@@ -586,7 +593,7 @@ PhoneGap.exec = function(success, fail, service, action, args) {
// If no result
else if (v.status === PhoneGap.callbackStatus.NO_RESULT) {
// Clear callback if not expecting any more results
if (!v.keepCallback) {
delete PhoneGap.callbacks[callbackId];
@@ -639,7 +646,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) {
console.log("Error in success callback: "+callbackId+" = "+e);
}
}
// Clear callback if not expecting any more results
if (!args.keepCallback) {
delete PhoneGap.callbacks[callbackId];
@@ -663,7 +670,7 @@ PhoneGap.callbackError = function(callbackId, args) {
catch (e) {
console.log("Error in error callback: "+callbackId+" = "+e);
}
// Clear callback if not expecting any more results
if (!args.keepCallback) {
delete PhoneGap.callbacks[callbackId];
@@ -729,7 +736,7 @@ PhoneGap.JSCallbackToken = null;
/**
* This is only for Android.
*
* Internal function that uses XHR to call into PhoneGap Java code and retrieve
* Internal function that uses XHR to call into PhoneGap Java code and retrieve
* any JavaScript code that needs to be run. This is used for callbacks from
* Java to JavaScript.
*/
@@ -751,7 +758,7 @@ PhoneGap.JSCallback = function() {
// Callback function when XMLHttpRequest is ready
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState === 4){
// Exit if shutting down app
if (PhoneGap.shuttingDown) {
return;
@@ -830,7 +837,7 @@ PhoneGap.UsePolling = false; // T=use polling, F=use XHR
/**
* This is only for Android.
*
* Internal function that uses polling to call into PhoneGap Java code and retrieve
* Internal function that uses polling to call into PhoneGap Java code and retrieve
* any JavaScript code that needs to be run. This is used for callbacks from
* Java to JavaScript.
*/
@@ -868,7 +875,7 @@ PhoneGap.JSCallbackPolling = function() {
/**
* Create a UUID
*
* @return
* @return {String}
*/
PhoneGap.createUUID = function() {
return PhoneGap.UUIDcreatePart(4) + '-' +
@@ -910,7 +917,7 @@ PhoneGap.close = function(context, func, params) {
* @param {Function} successCallback The callback to call when the file has been loaded.
*/
PhoneGap.includeJavascript = function(jsfile, successCallback) {
var id = document.getElementsByTagName("head")[0];
var id = document.getElementsByTagName("head")[0];
var el = document.createElement('script');
el.type = 'text/javascript';
if (typeof successCallback === 'function') {
@@ -932,4 +939,4 @@ var PluginManager = {
}
};
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
if (!PhoneGap.hasResource("position")) {
@@ -20,12 +20,13 @@ PhoneGap.addResource("position");
* @param {Object} vel
* @constructor
*/
Position = function(coords, timestamp) {
var Position = function(coords, timestamp) {
this.coords = coords;
this.timestamp = (timestamp !== 'undefined') ? timestamp : new Date().getTime();
};
Coordinates = function(lat, lng, alt, acc, head, vel, altacc) {
/** @constructor */
var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) {
/**
* The latitude of the position.
*/
@@ -53,14 +54,14 @@ Coordinates = function(lat, lng, alt, acc, head, vel, altacc) {
/**
* The altitude accuracy of the position.
*/
this.altitudeAccuracy = (altacc !== 'undefined') ? altacc : null;
this.altitudeAccuracy = (altacc !== 'undefined') ? altacc : null;
};
/**
* This class specifies the options for requesting position data.
* @constructor
*/
PositionOptions = function() {
var PositionOptions = function() {
/**
* Specifies the desired position accuracy.
*/
@@ -76,7 +77,7 @@ PositionOptions = function() {
* This class contains information about any GSP errors.
* @constructor
*/
PositionError = function() {
var PositionError = function() {
this.code = null;
this.message = "";
};
@@ -85,4 +86,4 @@ PositionError.UNKNOWN_ERROR = 0;
PositionError.PERMISSION_DENIED = 1;
PositionError.POSITION_UNAVAILABLE = 2;
PositionError.TIMEOUT = 3;
};
}

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
/*
@@ -15,9 +15,39 @@
if (!PhoneGap.hasResource("storage")) {
PhoneGap.addResource("storage");
/**
* SQL result set object
* PRIVATE METHOD
* @constructor
*/
var DroidDB_Rows = function() {
this.resultSet = []; // results array
this.length = 0; // number of rows
};
/**
* Get item from SQL result set
*
* @param row The row number to return
* @return The row object
*/
DroidDB_Rows.prototype.item = function(row) {
return this.resultSet[row];
};
/**
* SQL result set that is returned to user.
* PRIVATE METHOD
* @constructor
*/
var DroidDB_Result = function() {
this.rows = new DroidDB_Rows();
};
/**
* Storage object that is called by native code when performing queries.
* PRIVATE METHOD
* @constructor
*/
var DroidDB = function() {
this.queryQueue = {};
@@ -102,9 +132,40 @@ DroidDB.prototype.fail = function(reason, id) {
}
};
/**
* SQL query object
* PRIVATE METHOD
*
* @constructor
* @param tx The transaction object that this query belongs to
*/
var DroidDB_Query = function(tx) {
// Set the id of the query
this.id = PhoneGap.createUUID();
// Add this query to the queue
droiddb.queryQueue[this.id] = this;
// Init result
this.resultSet = [];
// Set transaction that this query belongs to
this.tx = tx;
// Add this query to transaction list
this.tx.queryList[this.id] = this;
// Callbacks
this.successCallback = null;
this.errorCallback = null;
};
/**
* Transaction object
* PRIVATE METHOD
* @constructor
*/
var DroidDB_Tx = function() {
@@ -119,37 +180,6 @@ var DroidDB_Tx = function() {
this.queryList = {};
};
var DatabaseShell = function() {
};
/**
* Start a transaction.
* Does not support rollback in event of failure.
*
* @param process {Function} The transaction function
* @param successCallback {Function}
* @param errorCallback {Function}
*/
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
var tx = new DroidDB_Tx();
tx.successCallback = successCallback;
tx.errorCallback = errorCallback;
try {
process(tx);
} catch (e) {
console.log("Transaction error: "+e);
if (tx.errorCallback) {
try {
tx.errorCallback(e);
} catch (ex) {
console.log("Transaction error calling user error callback: "+e);
}
}
}
};
/**
* Mark query in transaction as complete.
* If all queries are complete, call the user's transaction success callback.
@@ -165,7 +195,7 @@ DroidDB_Tx.prototype.queryComplete = function(id) {
var i;
for (i in this.queryList) {
if (this.queryList.hasOwnProperty(i)) {
count++;
count++;
}
}
if (count === 0) {
@@ -201,35 +231,6 @@ DroidDB_Tx.prototype.queryFailed = function(id, reason) {
}
};
/**
* SQL query object
* PRIVATE METHOD
*
* @param tx The transaction object that this query belongs to
*/
var DroidDB_Query = function(tx) {
// Set the id of the query
this.id = PhoneGap.createUUID();
// Add this query to the queue
droiddb.queryQueue[this.id] = this;
// Init result
this.resultSet = [];
// Set transaction that this query belongs to
this.tx = tx;
// Add this query to transaction list
this.tx.queryList[this.id] = this;
// Callbacks
this.successCallback = null;
this.errorCallback = null;
};
/**
* Execute SQL statement
*
@@ -257,31 +258,33 @@ DroidDB_Tx.prototype.executeSql = function(sql, params, successCallback, errorCa
PhoneGap.exec(null, null, "Storage", "executeSql", [sql, params, query.id]);
};
/**
* SQL result set that is returned to user.
* PRIVATE METHOD
*/
DroidDB_Result = function() {
this.rows = new DroidDB_Rows();
var DatabaseShell = function() {
};
/**
* SQL result set object
* PRIVATE METHOD
*/
DroidDB_Rows = function() {
this.resultSet = []; // results array
this.length = 0; // number of rows
};
/**
* Get item from SQL result set
* Start a transaction.
* Does not support rollback in event of failure.
*
* @param row The row number to return
* @return The row object
* @param process {Function} The transaction function
* @param successCallback {Function}
* @param errorCallback {Function}
*/
DroidDB_Rows.prototype.item = function(row) {
return this.resultSet[row];
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
var tx = new DroidDB_Tx();
tx.successCallback = successCallback;
tx.errorCallback = errorCallback;
try {
process(tx);
} catch (e) {
console.log("Transaction error: "+e);
if (tx.errorCallback) {
try {
tx.errorCallback(e);
} catch (ex) {
console.log("Transaction error calling user error callback: "+e);
}
}
}
};
/**
@@ -293,22 +296,24 @@ DroidDB_Rows.prototype.item = function(row) {
* @param size Database size in bytes
* @return Database object
*/
DroidDB_openDatabase = function(name, version, display_name, size) {
var DroidDB_openDatabase = function(name, version, display_name, size) {
PhoneGap.exec(null, null, "Storage", "openDatabase", [name, version, display_name, size]);
var db = new DatabaseShell();
return db;
};
/**
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
* TODO: Do similar for sessionStorage.
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
* TODO: Do similar for sessionStorage.
*/
/**
* @constructor
*/
var CupcakeLocalStorage = function() {
try {
this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
var storage = {};
this.length = 0;
function setLength (length) {
@@ -326,8 +331,8 @@ var CupcakeLocalStorage = function() {
setLength(result.rows.length);
PhoneGap.initializationComplete("cupcakeStorage");
});
},
},
function (err) {
alert(err.message);
}
@@ -344,7 +349,7 @@ var CupcakeLocalStorage = function() {
}
);
};
this.getItem = function(key) {
this.getItem = function(key) {
return storage[key];
};
this.removeItem = function(key) {
@@ -377,28 +382,41 @@ var CupcakeLocalStorage = function() {
}
}
return null;
}
};
} catch(e) {
alert("Database error "+e+".");
return;
}
};
PhoneGap.addConstructor(function() {
var setupDroidDB = function() {
navigator.openDatabase = window.openDatabase = DroidDB_openDatabase;
window.droiddb = new DroidDB();
}
if ((typeof window.openDatabase === "undefined") || (navigator.userAgent.indexOf("Android 3.0") != -1)) {
if (typeof window.openDatabase === "undefined") {
setupDroidDB();
} else {
window.openDatabase_orig = window.openDatabase;
window.openDatabase = function(name, version, desc, size) {
var db = window.openDatabase_orig(name, version, desc, size);
window.openDatabase = function(name, version, desc, size){
// Some versions of Android will throw a SECURITY_ERR so we need
// to catch the exception and seutp our own DB handling.
var db = null;
try {
db = window.openDatabase_orig(name, version, desc, size);
}
catch (ex) {
db = null;
}
if (db == null) {
setupDroidDB();
return DroidDB_openDatabase(name, version, desc, size);
} else return db;
}
else {
return db;
}
}
}
@@ -407,4 +425,4 @@ PhoneGap.addConstructor(function() {
PhoneGap.waitForInitialization("cupcakeStorage");
}
});
};
}

View File

@@ -1,27 +0,0 @@
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.phonegap;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
public static final int splash=0x7f020001;
}
public static final class id {
public static final int appView=0x7f050000;
}
public static final class layout {
public static final int main=0x7f030000;
}
public static final class string {
public static final int app_name=0x7f040000;
public static final int go=0x7f040001;
}
}

View File

@@ -63,6 +63,9 @@ public class AudioHandler extends Plugin {
else if (action.equals("startPlayingAudio")) {
this.startPlayingAudio(args.getString(0), args.getString(1));
}
else if (action.equals("seekToAudio")) {
this.seekToAudio(args.getString(0), args.getInt(1));
}
else if (action.equals("pausePlayingAudio")) {
this.pausePlayingAudio(args.getString(0));
}
@@ -181,6 +184,20 @@ public class AudioHandler extends Plugin {
audio.startPlaying(file);
}
/**
* Seek to a location.
*
*
* @param id The id of the audio player
* @param miliseconds int: number of milliseconds to skip 1000 = 1 second
*/
public void seekToAudio(String id, int milliseconds) {
AudioPlayer audio = this.players.get(id);
if (audio != null) {
audio.seekToPlaying(milliseconds);
}
}
/**
* Pause playing.
*

View File

@@ -233,6 +233,15 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
}
}
/**
* Seek or jump to a new time in the track.
*/
public void seekToPlaying(int milliseconds) {
if (this.mPlayer != null) {
this.mPlayer.seekTo(milliseconds);
}
}
/**
* Pause playing.
*/

View File

@@ -1,3 +1,10 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2011, IBM Corporation
*/
package com.phonegap;
import java.io.File;

View File

@@ -46,7 +46,14 @@ public class ContactManager extends Plugin {
return new PluginResult(status, res, "navigator.service.contacts.cast");
}
else if (action.equals("save")) {
return new PluginResult(status, contactAccessor.save(args.getJSONObject(0)));
if (contactAccessor.save(args.getJSONObject(0))) {
return new PluginResult(status, result);
}
else {
JSONObject r = new JSONObject();
r.put("code", 0);
return new PluginResult(PluginResult.Status.ERROR, r);
}
}
else if (action.equals("remove")) {
if (contactAccessor.remove(args.getString(0))) {

View File

@@ -125,8 +125,8 @@ public class DroidGap extends PhonegapActivity {
private String baseUrl;
// Plugin to call when activity result is received
private Plugin activityResultCallback = null;
private boolean activityResultKeepRunning;
protected Plugin activityResultCallback = null;
protected boolean activityResultKeepRunning;
// Flag indicates that a loadUrl timeout occurred
private int loadUrlTimeout = 0;
@@ -202,11 +202,11 @@ public class DroidGap extends PhonegapActivity {
WebViewReflect.checkCompatibility();
if (android.os.Build.VERSION.RELEASE.startsWith("2.")) {
this.appView.setWebChromeClient(new EclairClient(DroidGap.this));
if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
this.appView.setWebChromeClient(new GapClient(DroidGap.this));
}
else {
this.appView.setWebChromeClient(new GapClient(DroidGap.this));
this.appView.setWebChromeClient(new EclairClient(DroidGap.this));
}
this.setWebViewClient(this.appView, new GapViewClient(this));
@@ -850,13 +850,13 @@ public class DroidGap extends PhonegapActivity {
}
return true;
}
}
/**
* WebChromeClient that extends GapClient with additional support for Android 2.X
*/
public final class EclairClient extends GapClient {
public class EclairClient extends GapClient {
private String TAG = "PhoneGapLog";
private long MAX_QUOTA = 100 * 1024 * 1024;
@@ -910,6 +910,12 @@ public class DroidGap extends PhonegapActivity {
}
@Override
/**
* Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
*
* @param origin
* @param callback
*/
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
// TODO Auto-generated method stub
super.onGeolocationPermissionsShowPrompt(origin, callback);

View File

@@ -97,48 +97,23 @@ public class FileUtils extends Plugin {
return new PluginResult(status, b);
}
else if (action.equals("readAsText")) {
try {
String s = this.readAsText(args.getString(0), args.getString(1));
return new PluginResult(status, s);
} catch (IOException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
}
String s = this.readAsText(args.getString(0), args.getString(1));
return new PluginResult(status, s);
}
else if (action.equals("readAsDataURL")) {
try {
String s = this.readAsDataURL(args.getString(0));
return new PluginResult(status, s);
} catch (IOException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
}
String s = this.readAsDataURL(args.getString(0));
return new PluginResult(status, s);
}
else if (action.equals("writeAsText")) {
try {
this.writeAsText(args.getString(0), args.getString(1), args.getBoolean(2));
} catch (IOException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
}
this.writeAsText(args.getString(0), args.getString(1), args.getBoolean(2));
}
else if (action.equals("write")) {
try {
long fileSize = this.write(args.getString(0), args.getString(1), args.getLong(2));
return new PluginResult(status, fileSize);
} catch (IOException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
}
long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
return new PluginResult(status, fileSize);
}
else if (action.equals("truncate")) {
try {
long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
return new PluginResult(status, fileSize);
} catch (IOException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
}
long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
return new PluginResult(status, fileSize);
}
else if (action.equals("requestFileSystem")) {
long size = args.optLong(1);
@@ -945,16 +920,26 @@ public class FileUtils extends Plugin {
* @param offset The position to begin writing the file.
* @throws FileNotFoundException, IOException
*/
public long write(String filename, String data, long offset) throws FileNotFoundException, IOException {
RandomAccessFile file = new RandomAccessFile(filename, "rw");
file.seek(offset);
file.writeBytes(data);
file.close();
/**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException {
boolean append = false;
if (offset > 0) {
this.truncateFile(filename, offset);
append = true;
}
byte [] rawData = data.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
FileOutputStream out = new FileOutputStream(filename, append);
byte buff[] = new byte[rawData.length];
in.read(buff, 0, buff.length);
out.write(buff, 0, rawData.length);
out.flush();
out.close();
return data.length();
}
/**
* Truncate the file to size
*

View File

@@ -3,7 +3,7 @@
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
* Copyright (c) 2010-2011, IBM Corporation
*/
package com.phonegap;
@@ -11,21 +11,54 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.*;
import android.telephony.TelephonyManager;
import android.util.Log;
public class NetworkManager extends Plugin {
public static int NOT_REACHABLE = 0;
public static int REACHABLE_VIA_CARRIER_DATA_NETWORK = 1;
public static int REACHABLE_VIA_WIFI_NETWORK = 2;
public static final String WIFI = "wifi";
public static final String WIMAX = "wimax";
// mobile
public static final String MOBILE = "mobile";
// 2G network types
public static final String GSM = "gsm";
public static final String GPRS = "gprs";
public static final String EDGE = "edge";
// 3G network types
public static final String CDMA = "cdma";
public static final String UMTS = "umts";
// 4G network types
public static final String LTE = "lte";
public static final String UMB = "umb";
// return types
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_ETHERNET = 1;
public static final int TYPE_WIFI = 2;
public static final int TYPE_2G = 3;
public static final int TYPE_3G = 4;
public static final int TYPE_4G = 5;
public static final int TYPE_NONE = 20;
private static final String LOG_TAG = "NetworkManager";
private String connectionCallbackId;
ConnectivityManager sockMan;
TelephonyManager telephonyManager;
/**
* Constructor.
@@ -41,7 +74,18 @@ public class NetworkManager extends Plugin {
*/
public void setContext(PhonegapActivity ctx) {
super.setContext(ctx);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
this.telephonyManager = ((TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE));
// We need to listen to connectivity events to update navigator.connection
IntentFilter intentFilter = new IntentFilter() ;
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
ctx.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
}
}, intentFilter);
}
/**
@@ -68,6 +112,13 @@ public class NetworkManager extends Plugin {
int i = this.isReachable(args.getString(0), args.getBoolean(1));
return new PluginResult(status, i);
}
else if (action.equals("getConnectionInfo")) {
this.connectionCallbackId = callbackId;
NetworkInfo info = sockMan.getActiveNetworkInfo();
PluginResult pluginResult = new PluginResult(status, this.getConnectionInfo(info));
pluginResult.setKeepCallback(true);
return pluginResult;
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
@@ -89,7 +140,107 @@ public class NetworkManager extends Plugin {
// LOCAL METHODS
//--------------------------------------------------------------------------
/**
/**
* Updates the JavaScript side whenever the connection changes
*
* @param info the current active network info
* @return
*/
private void updateConnectionInfo(NetworkInfo info) {
JSONObject connection = this.getConnectionInfo(info);
// send update to javascript "navigator.connection"
sendUpdate(connection);
}
/**
* Get the latest network connection information
*
* @param info the current active network info
* @return a JSONObject that represents the network info
*/
private JSONObject getConnectionInfo(NetworkInfo info) {
JSONObject connection = new JSONObject();
try {
if (info != null) {
// If we are not connected to any network set type to none
if (!info.isConnected()) {
connection.put("type", TYPE_NONE);
connection.put("homeNW", null);
connection.put("currentNW", null);
}
else {
// If we are connected check which type
// First off is wifi
if (info.getTypeName().toLowerCase().equals(WIFI)) {
connection.put("type", TYPE_WIFI);
connection.put("homeNW", null);
connection.put("currentNW", null);
}
// Otherwise it must be one of the mobile network protocols
else {
// Determine the correct type, 2G, 3G, 4G
connection.put("type", getType(info));
connection.put("homeNW", telephonyManager.getSimOperatorName());
connection.put("currentNW", telephonyManager.getNetworkOperatorName());
}
}
}
}
catch (JSONException e) {
// this should never happen
Log.e(LOG_TAG, e.getMessage(), e);
}
return connection;
}
/**
* Create a new plugin result and send it back to JavaScript
*
* @param connection the network info to set as navigator.connection
*/
private void sendUpdate(JSONObject connection) {
PluginResult result = new PluginResult(PluginResult.Status.OK, connection);
result.setKeepCallback(true);
this.success(result, this.connectionCallbackId);
}
/**
* Determine the type of connection
*
* @param info the network info so we can determine connection type.
* @return the type of mobile network we are on
*/
private int getType(NetworkInfo info) {
if (info != null) {
String type = info.getTypeName();
if (type.toLowerCase().equals(MOBILE)) {
type = info.getSubtypeName();
if (type.toLowerCase().equals(GSM) ||
type.toLowerCase().equals(GPRS) ||
type.toLowerCase().equals(EDGE)) {
return TYPE_2G;
}
else if (type.toLowerCase().equals(CDMA) ||
type.toLowerCase().equals(UMTS)) {
return TYPE_3G;
}
else if (type.toLowerCase().equals(LTE) ||
type.toLowerCase().equals(UMB)) {
return TYPE_4G;
}
}
}
else {
return TYPE_NONE;
}
return TYPE_UNKNOWN;
}
/**
* Determine if a network connection exists.
*
* @return
@@ -150,4 +301,4 @@ public class NetworkManager extends Plugin {
return reachable;
}
}
}

View File

@@ -5,7 +5,7 @@ class Classic
@android_sdk_path, @name, @pkg, @www, @path = a
build
end
def build
setup
clobber
@@ -16,8 +16,8 @@ class Classic
copy_libs
add_name_to_strings
write_java
end
end
def setup
@android_dir = File.expand_path(File.dirname(__FILE__).gsub(/lib$/,''))
@framework_dir = File.join(@android_dir, "framework")
@@ -31,14 +31,14 @@ class Classic
@app_js_dir = ''
@content = 'index.html'
end
# replaces @path with new android project
def clobber
FileUtils.rm_r(@path) if File.exists? @path
FileUtils.mkdir_p @path
end
# removes local.properties and recreates based on android_sdk_path
# removes local.properties and recreates based on android_sdk_path
# then generates framework/phonegap.jar
def build_jar
%w(local.properties phonegap.js phonegap.jar).each do |f|
@@ -46,7 +46,7 @@ class Classic
end
open(File.join(@framework_dir, "local.properties"), 'w') do |f|
f.puts "sdk.dir=#{ @android_sdk_path }"
end
end
Dir.chdir(@framework_dir)
`ant jar`
Dir.chdir(@android_dir)
@@ -55,9 +55,9 @@ class Classic
# runs android create project
# TODO need to allow more flexible SDK targetting via config.xml
def create_android
IO.popen("android list targets") { |f|
IO.popen("android list targets") { |f|
targets = f.readlines(nil)[0].scan(/id\:.*$/)
if (targets.length > 0)
if (targets.length > 0)
target_id = targets.last.match(/\d+/).to_a.first
`android create project -t #{ target_id } -k #{ @pkg } -a #{ @name } -n #{ @name } -p #{ @path }`
else
@@ -66,7 +66,7 @@ class Classic
end
}
end
# copies the project/www folder into tmp/android/www
def include_www
FileUtils.mkdir_p File.join(@path, "assets", "www")
@@ -127,7 +127,7 @@ class Classic
end
File.open(File.join(@path, "assets", "www", @app_js_dir, "phonegap.#{ version }.js"), 'w') {|f| f.write(phonegapjs) }
end
# puts app name in strings
def add_name_to_strings
x = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
@@ -138,8 +138,8 @@ class Classic
"
open(File.join(@path, "res", "values", "strings.xml"), 'w') do |f|
f.puts x.gsub(' ','')
end
end
end
end
# create java source file
def write_java
@@ -164,7 +164,7 @@ class Classic
FileUtils.mkdir_p(code_dir)
open(File.join(code_dir, "#{ @name }.java"),'w') { |f| f.puts j }
end
# friendly output for now
def msg
puts "Created #{ @path }"

View File

@@ -1,5 +1,5 @@
# Create
#
#
# Generates an Android project from a valid WWW directory and puts it in ../[PROJECT NAME]_android
#
class Create < Classic
@@ -8,35 +8,35 @@ class Create < Classic
read_config
build
end
def guess_paths(path)
# if no path is supplied uses current directory for project
path = FileUtils.pwd if path.nil?
# if a www is found use it for the project
path = File.join(path, 'www') if File.exists? File.join(path, 'www')
# defaults
@name = path.split("/").last.gsub('-','').gsub(' ','') # no dashses nor spaces
@path = File.join(path, '..', "#{ @name }_android")
@www = path
@pkg = "com.phonegap.#{ @name }"
@www = path
@pkg = "com.phonegap.#{ @name }"
@android_sdk_path = Dir.getwd[0,1] != "/" ? `android-sdk-path.bat android.bat`.gsub('\\tools','').gsub('\\', '\\\\\\\\') : `which android`.gsub(/\/tools\/android$/,'').chomp
@android_dir = File.expand_path(File.dirname(__FILE__).gsub('lib',''))
@framework_dir = File.join(@android_dir, "framework")
@icon = File.join(@www, 'icon.png')
@app_js_dir = ''
@content = 'index.html'
# stop executation on errors
raise "Expected index.html in the following folder #{ path }.\nThe path is expected to be the directory droidgap create is run from or specified as a command line arg like droidgap create my_path." unless File.exists? File.join(path, 'index.html')
raise "Expected index.html in the following folder #{ path }.\nThe path is expected to be the directory droidgap create is run from or specified as a command line arg like droidgap create my_path." unless File.exists? File.join(path, 'index.html')
raise 'Could not find android in your PATH!' if @android_sdk_path.empty?
end
# reads in a config.xml file
def read_config
config_file = File.join(@www, 'config.xml')
if File.exists?(config_file)
require 'rexml/document'
f = File.new config_file
@@ -47,9 +47,9 @@ class Create < Classic
@config[:icons] = {}
defaultIconSize = 0
doc.root.elements.each do |n|
@config[:name] = n.text.gsub('-','').gsub(' ','') if n.name == 'name'
@config[:description] = n.text if n.name == 'description'
@config[:content] = n.attributes["src"] if n.name == 'content'
@config[:name] = n.text.gsub('-','').gsub(' ','') if n.name == 'name'
@config[:description] = n.text if n.name == 'description'
@config[:content] = n.attributes["src"] if n.name == 'content'
if n.name == 'icon'
if n.attributes["width"] == '72' && n.attributes["height"] == '72'
@config[:icons]["drawable-hdpi".to_sym] = n.attributes["src"]
@@ -74,12 +74,12 @@ class Create < Classic
end
end
if n.name == "preference" && n.attributes["name"] == 'javascript_folder'
@config[:js_dir] = n.attributes["value"]
end
end
end
end
# extract android specific stuff
@config[:versionCode] = doc.elements["//android:versionCode"] ? doc.elements["//android:versionCode"].text : 3
@config[:minSdkVersion] = doc.elements["//android:minSdkVersion"] ? doc.elements["//android:minSdkVersion"].text : 1
@@ -92,6 +92,6 @@ class Create < Classic
@app_js_dir = @config[:js_dir] ? @config[:js_dir] : ''
# sets the start page
@content = @config[:content] ? @config[:content] : 'index.html'
end
end
end
end
end