if (typeof(DeviceInfo) != 'object') DeviceInfo = {}; var com = {}; com.phonegap = {}; /** * This represents the PhoneGap API itself, and provides a global namespace for accessing * information about the state of PhoneGap. * @class */ var PhoneGap = { queue: { ready: true, commands: [], timer: null } }; /** * Custom pub-sub channel that can have functions subscribed to it */ PhoneGap.Channel = function(type) { this.type = type; this.handlers = {}; this.guid = 0; this.fired = false; this.enabled = true; }; /** * 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. * Returns the guid. */ PhoneGap.Channel.prototype.subscribe = function(f, c, g) { // need a function to call if (f == null) { return; } var func = f; if (typeof c == "object" && f instanceof Function) { func = PhoneGap.close(c, f); } g = g || func.observer_guid || f.observer_guid || this.guid++; func.observer_guid = g; f.observer_guid = g; this.handlers[g] = func; return g; }; /** * Like subscribe but the function is only called once and then it * auto-unsubscribes itself. */ PhoneGap.Channel.prototype.subscribeOnce = function(f, c) { var g = null; var _this = this; var m = function() { f.apply(c || null, arguments); _this.unsubscribe(g); } if (this.fired) { if (typeof c == "object" && f instanceof Function) { f = PhoneGap.close(c, f); } f.apply(this, this.fireArgs); } else { g = this.subscribe(m); } return g; }; /** * Unsubscribes the function with the given guid from the channel. */ PhoneGap.Channel.prototype.unsubscribe = function(g) { if (g instanceof Function) { g = g.observer_guid; } this.handlers[g] = null; delete this.handlers[g]; }; /** * Calls all functions subscribed to this channel. */ PhoneGap.Channel.prototype.fire = function(e) { if (this.enabled) { var fail = false; for (var item in this.handlers) { var handler = this.handlers[item]; if (handler instanceof Function) { var rv = (handler.apply(this, arguments)==false); fail = fail || rv; } } this.fired = true; this.fireArgs = arguments; return !fail; } return true; }; /** * Calls the provided function only after all of the channels specified * have been fired. */ PhoneGap.Channel.join = function(h, c) { var i = c.length; var f = function() { if (!(--i)) h(); } for (var j=0; j= 0) { com.phonegap.AccelListener.start(); // Wait until started var timer = setInterval(function() { var status = com.phonegap.AccelListener.getStatus(); // If accelerometer is running if (status == Accelerometer.RUNNING) { clearInterval(timer); try { var accel = com.phonegap.AccelListener.getAcceleration(); successCallback(accel); } catch (e) { console.log("Accelerometer Error in successCallback: " + e); } } // If accelerometer error else if (status == Accelerometer.ERROR_FAILED_TO_START) { clearInterval(timer); console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); try { if (errorCallback) { errorCallback(status); } } catch (e) { console.log("Accelerometer Error in errorCallback: " + e); } } }, 10); } }; /** * Asynchronously aquires the acceleration repeatedly at a given interval. * * @param {Function} successCallback The function to call each time the acceleration data is available * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. * @return String The watch id that must be passed to #clearWatch to stop watching. */ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) { // Default interval (10 sec) var frequency = (options != undefined)? options.frequency : 10000; // successCallback required if (typeof successCallback != "function") { console.log("Accelerometer Error: successCallback is not a function"); return; } // errorCallback optional if (errorCallback && (typeof errorCallback != "function")) { console.log("Accelerometer Error: errorCallback is not a function"); return; } // Make sure accelerometer timeout > frequency + 10 sec var timeout = com.phonegap.AccelListener.getTimeout(); if (timeout < (frequency + 10000)) { com.phonegap.AccelListener.setTimeout(frequency + 10000); // set to frequency + 10 sec } var id = PhoneGap.createUUID(); com.phonegap.AccelListener.start(); // Start watch timer navigator.accelerometer.timers[id] = setInterval(function() { var status = com.phonegap.AccelListener.getStatus(); // If accelerometer is running if (status == Accelerometer.RUNNING) { try { var accel = com.phonegap.AccelListener.getAcceleration(); successCallback(accel); } catch (e) { console.log("Accelerometer Error in successCallback: " + e); } } // If accelerometer had error else if (status == Accelerometer.ERROR_FAILED_TO_START) { console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); try { navigator.accelerometer.clearWatch(id); if (errorCallback) { errorCallback(status); } } catch (e) { console.log("Accelerometer Error in errorCallback: " + e); } } }, (frequency ? frequency : 1)); return id; }; /** * Clears the specified accelerometer watch. * * @param {String} id The id of the watch returned from #watchAcceleration. */ Accelerometer.prototype.clearWatch = function(id) { // Stop javascript timer & remove from timer list if (id && navigator.accelerometer.timers[id]) { clearInterval(navigator.accelerometer.timers[id]); delete navigator.accelerometer.timers[id]; } }; PhoneGap.addConstructor(function() { if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer(); }); com.phonegap.CameraLauncherProxy = function() { this.className = "com.phonegap.CameraLauncher"; }; com.phonegap.CameraLauncherProxy.prototype.setBase64 = function(b) { return PhoneGap.exec(this.className, "setBase64", [b]); }; com.phonegap.CameraLauncherProxy.prototype.takePicture = function(quality) { return PhoneGap.exec(this.className, "takePicture", [quality]); }; com.phonegap.CameraLauncher = new com.phonegap.CameraLauncherProxy(); /** * This class provides access to the device camera. * * @constructor */ function Camera() { this.successCallback = null; this.errorCallback = null; this.options = null; }; /** * Takes a photo and returns the image as a base64 encoded `String`. * * @param {Function} successCallback * @param {Function} errorCallback * @param {Object} options */ Camera.prototype.getPicture = function(successCallback, errorCallback, options) { // successCallback required if (typeof successCallback != "function") { console.log("Camera Error: successCallback is not a function"); return; } // errorCallback optional if (errorCallback && (typeof errorCallback != "function")) { console.log("Camera Error: errorCallback is not a function"); return; } this.successCallback = successCallback; this.errorCallback = errorCallback; this.options = options; if (options.quality) { com.phonegap.CameraLauncher.takePicture(options.quality); } else { com.phonegap.CameraLauncher.takePicture(80); } }; /** * Callback function from native code that is called when image has been captured. * * @param picture The base64 encoded string of the image */ Camera.prototype.success = function(picture) { if (this.successCallback) { this.successCallback(picture); } }; /** * Callback function from native code that is called when there is an error * capturing an image, or the capture is cancelled. * * @param err The error message */ Camera.prototype.error = function(err) { if (this.errorCallback) { this.errorCallback(err); } }; PhoneGap.addConstructor(function() { if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); }); com.phonegap.CompassListenerProxy = function() { this.className = "com.phonegap.CompassListener"; }; com.phonegap.CompassListenerProxy.prototype.start = function() { return PhoneGap.exec(this.className, "start", []); }; com.phonegap.CompassListenerProxy.prototype.stop = function() { return PhoneGap.exec(this.className, "stop", []); }; com.phonegap.CompassListenerProxy.prototype.getStatus = function() { return PhoneGap.exec(this.className, "getStatus", []); }; com.phonegap.CompassListenerProxy.prototype.getHeading = function() { return PhoneGap.exec(this.className, "getHeading", []); }; com.phonegap.CompassListenerProxy.prototype.setTimeout = function(timeout) { return PhoneGap.exec(this.className, "setTimeout", [timeout]); }; com.phonegap.CompassListenerProxy.prototype.getTimeout = function() { return PhoneGap.exec(this.className, "getTimeout", []); }; com.phonegap.CompassListener = new com.phonegap.CompassListenerProxy(); /** * This class provides access to device Compass data. * @constructor */ function Compass() { /** * The last known Compass position. */ this.lastHeading = null; /** * List of compass watch timers */ this.timers = {}; }; Compass.STOPPED = 0; Compass.STARTING = 1; Compass.RUNNING = 2; Compass.ERROR_FAILED_TO_START = 3; Compass.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"]; /** * Asynchronously aquires the current heading. * * @param {Function} successCallback The function to call when the heading data is available * @param {Function} errorCallback The function to call when there is an error getting the heading data. * @param {PositionOptions} options The options for getting the heading data such as timeout. */ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) { // successCallback required if (typeof successCallback != "function") { console.log("Compass Error: successCallback is not a function"); return; } // errorCallback optional if (errorCallback && (typeof errorCallback != "function")) { console.log("Compass Error: errorCallback is not a function"); return; } // Get current compass status var status = com.phonegap.CompassListener.getStatus(); // If running, then call successCallback if (status == Compass.RUNNING) { try { var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); } } // If not running, then start it else { com.phonegap.CompassListener.start(); // Wait until started var timer = setInterval(function() { var status = com.phonegap.CompassListener.getStatus(); if (status != Compass.STARTING) { clearInterval(timer); // If compass is running if (status == Compass.RUNNING) { try { var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); } } // If compass error else { console.log("Compass Error: "+ Compass.ERROR_MSG[status]); try { if (errorCallback) { errorCallback(status); } } catch (e) { console.log("Compass Error in errorCallback: " + e); } } } }, 10); } }; /** * Asynchronously aquires the heading repeatedly at a given interval. * * @param {Function} successCallback The function to call each time the heading data is available * @param {Function} errorCallback The function to call when there is an error getting the heading data. * @param {HeadingOptions} options The options for getting the heading data such as timeout and the frequency of the watch. * @return String The watch id that must be passed to #clearWatch to stop watching. */ Compass.prototype.watchHeading= function(successCallback, errorCallback, options) { // Default interval (100 msec) var frequency = (options != undefined) ? options.frequency : 100; // successCallback required if (typeof successCallback != "function") { console.log("Compass Error: successCallback is not a function"); return; } // errorCallback optional if (errorCallback && (typeof errorCallback != "function")) { console.log("Compass Error: errorCallback is not a function"); return; } // Make sure compass timeout > frequency + 10 sec var timeout = com.phonegap.CompassListener.getTimeout(); if (timeout < (frequency + 10000)) { com.phonegap.CompassListener.setTimeout(frequency + 10000); // set to frequency + 10 sec } var id = PhoneGap.createUUID(); com.phonegap.CompassListener.start(); // Start watch timer navigator.compass.timers[id] = setInterval(function() { var status = com.phonegap.CompassListener.getStatus(); // If compass is running if (status == Compass.RUNNING) { try { var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); } } // If compass had error else if (status != Compass.STARTING) { console.log("Compass Error: "+ Compass.ERROR_MSG[status]); try { navigator.compass.clearWatch(id); if (errorCallback) { errorCallback(status); } } catch (e) { console.log("Compass Error in errorCallback: " + e); } } }, (frequency ? frequency : 1)); return id; }; /** * Clears the specified heading watch. * * @param {String} id The ID of the watch returned from #watchHeading. */ Compass.prototype.clearWatch = function(id) { // Stop javascript timer & remove from timer list if (id && navigator.compass.timers[id]) { clearInterval(navigator.compass.timers[id]); delete navigator.compass.timers[id]; } }; PhoneGap.addConstructor(function() { if (typeof navigator.compass == "undefined") navigator.compass = new Compass(); }); com.phonegap.ContactManagerProxy = function() { this.className = "com.phonegap.ContactManager"; }; com.phonegap.ContactManagerProxy.prototype.getContactsAndSendBack = function() { return PhoneGap.exec(this.className, "getContactsAndSendBack", []); }; com.phonegap.ContactManagerProxy.prototype.search = function(name, npa, mail) { return PhoneGap.exec(this.className, "search", [name, npa, mail]); }; com.phonegap.ContactManager = new com.phonegap.ContactManagerProxy(); var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, ims, organizations, published, updated, birthday, anniversary, gender, note, preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) { this.id = id || ''; this.displayName = displayName || ''; this.name = name || null; // ContactName this.nickname = nickname || ''; this.phoneNumbers = phoneNumbers || null; // ContactField[] this.emails = emails || null; // ContactField[] this.addresses = addresses || null; // ContactAddress[] this.ims = ims || null; // ContactField[] this.organizations = organizations || null; // ContactOrganization[] this.published = published || ''; this.updated = updated || ''; this.birthday = birthday || ''; this.anniversary = anniversary || ''; this.gender = gender || ''; this.note = note || ''; this.preferredUsername = preferredUsername || ''; this.photos = photos || null; // ContactField[] this.tags = tags || null; // ContactField[] this.relationships = relationships || null; // ContactField[] this.urls = urls || null; // ContactField[] this.accounts = accounts || null; // ContactAccount[] this.utcOffset = utcOffset || ''; this.connected = connected || ''; }; var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { this.formatted = formatted || ''; this.familyName = familyName || ''; this.givenName = givenName || ''; this.middleName = middle || ''; this.honorificPrefix = prefix || ''; this.honorificSuffix = suffix || ''; }; var ContactField = function(type, value, primary) { this.type = type || ''; this.value = value || ''; this.primary = primary || ''; }; var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) { this.formatted = formatted || ''; this.streetAddress = streetAddress || ''; this.locality = locality || ''; this.region = region || ''; this.postalCode = postalCode || ''; this.country = country || ''; }; var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) { this.name = name || ''; this.department = dept || ''; this.title = title || ''; this.startDate = startDate || ''; this.endDate = endDate || ''; this.location = location || ''; this.description = desc || ''; }; var ContactAccount = function(domain, username, userid) { this.domain = domain || ''; this.username = username || ''; this.userid = userid || ''; } var Contacts = function() { this.inProgress = false; this.records = []; } Contacts.prototype.find = function(obj, win, fail) { if(obj.name != null) { // Build up the search term that we'll use in SQL, based on the structure/contents of the contact object passed into find. var searchTerm = ''; if (obj.name.givenName && obj.name.givenName.length > 0) { searchTerm = obj.name.givenName.split(' ').join('%'); } if (obj.name.familyName && obj.name.familyName.length > 0) { searchTerm += obj.name.familyName.split(' ').join('%'); } if (!obj.name.familyName && !obj.name.givenName && obj.name.formatted) { searchTerm = obj.name.formatted; } com.phonegap.ContactManager.search(searchTerm, "", ""); } this.win = win; this.fail = fail; }; Contacts.prototype.droidFoundContact = function(name, npa, email) { this.records = new Array(); var contact = new Contact(); contact.name = new ContactName(); contact.name.formatted = name; contact.name.givenName = name; contact.emails = new Array(); var mail = new ContactField(); mail.type = "home"; mail.value = email; mail.primary = true; contact.emails.push(mail); contact.phones = new Array(); phone = new ContactField(); phone.type = "home"; phone.value = npa; contact.phones.push(phone); this.records.push(contact); }; Contacts.prototype.droidDone = function() { this.win(this.records); }; Contacts.prototype.remove = function(contact) { }; Contacts.prototype.save = function(contact) { }; Contacts.prototype.create = function(contact) { }; Contacts.prototype.m_foundContacts = function(win, contacts) { this.inProgress = false; win(contacts); }; var ContactFindOptions = function(filter, multiple, limit, updatedSince) { this.filter = filter || ''; this.multiple = multiple || true; this.limit = limit || 0; this.updatedSince = updatedSince || ''; }; var ContactError = function() { }; ContactError.INVALID_ARGUMENT_ERROR = 0; ContactError.IO_ERROR = 1; ContactError.NOT_FOUND_ERROR = 2; ContactError.NOT_SUPPORTED_ERROR = 3; ContactError.PENDING_OPERATION_ERROR = 4; ContactError.PERMISSION_DENIED_ERROR = 5; ContactError.TIMEOUT_ERROR = 6; ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { if(typeof navigator.service == "undefined") navigator.service = new Object(); if(typeof navigator.service.contacts == "undefined") navigator.service.contacts = new Contacts(); }); com.phonegap.CryptoHandlerProxy = function() { this.className = "com.phonegap.CryptoHandler"; }; com.phonegap.CryptoHandlerProxy.prototype.encrypt = function(pass, text) { return PhoneGap.exec(this.className, "encrypt", [pass, text]); }; com.phonegap.CryptoHandlerProxy.prototype.decrypt = function(pass, text) { return PhoneGap.exec(this.className, "decrypt", [pass, text]); }; com.phonegap.CryptoHandler = new com.phonegap.CryptoHandlerProxy(); var Crypto = function() { }; Crypto.prototype.encrypt = function(seed, string, callback) { com.phonegap.CryptoHandler.encrypt(seed, string); this.encryptWin = callback; }; Crypto.prototype.decrypt = function(seed, string, callback) { com.phonegap.CryptoHandler.decrypt(seed, string); this.decryptWin = callback; }; Crypto.prototype.gotCryptedString = function(string) { this.encryptWin(string); }; Crypto.prototype.getPlainString = function(string) { this.decryptWin(string); }; PhoneGap.addConstructor(function() { if (typeof navigator.Crypto == "undefined") navigator.Crypto = new Crypto(); }); /** * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the * phone, etc. * @constructor */ function Device() { this.available = PhoneGap.available; this.platform = null; this.version = null; this.name = null; this.gap = null; this.uuid = null; try { if (window.DroidGap) { this.available = true; this.uuid = window.DroidGap.getUuid(); this.version = window.DroidGap.getOSVersion(); this.gapVersion = window.DroidGap.getVersion(); this.platform = window.DroidGap.getPlatform(); this.name = window.DroidGap.getProductName(); this.line1Number = window.DroidGap.getLine1Number(); this.deviceId = window.DroidGap.getDeviceId(); this.simSerialNumber = window.DroidGap.getSimSerialNumber(); this.subscriberId = window.DroidGap.getSubscriberId(); } } catch(e) { this.available = false; } } /* * You must explicitly override the back button. */ Device.prototype.overrideBackButton = function() { BackButton.override(); } /* * This resets the back button to the default behaviour */ Device.prototype.resetBackButton = function() { BackButton.reset(); } /* * This terminates the activity! */ Device.prototype.exitApp = function() { BackButton.exitApp(); } PhoneGap.addConstructor(function() { navigator.device = window.device = new Device(); }); PhoneGap.addConstructor(function() { if (typeof navigator.fileMgr == "undefined") navigator.fileMgr = new FileMgr();}); /** * This class provides iPhone read and write access to the mobile device file system. * Based loosely on http://www.w3.org/TR/2009/WD-FileAPI-20091117/#dfn-empty */ function FileMgr() { this.fileWriters = {}; // empty maps this.fileReaders = {}; this.docsFolderPath = "../../Documents"; this.tempFolderPath = "../../tmp"; this.freeDiskSpace = -1; this.getFileBasePaths(); } // private, called from Native Code FileMgr.prototype._setPaths = function(docs,temp) { this.docsFolderPath = docs; this.tempFolderPath = temp; } // private, called from Native Code FileMgr.prototype._setFreeDiskSpace = function(val) { this.freeDiskSpace = val; } // FileWriters add/remove // called internally by writers FileMgr.prototype.addFileWriter = function(filePath,fileWriter) { this.fileWriters[filePath] = fileWriter; } FileMgr.prototype.removeFileWriter = function(filePath) { this.fileWriters[filePath] = null; } // File readers add/remove // called internally by readers FileMgr.prototype.addFileReader = function(filePath,fileReader) { this.fileReaders[filePath] = fileReader; } FileMgr.prototype.removeFileReader = function(filePath) { this.fileReaders[filePath] = null; } /******************************************* * * private reader callback delegation * called from native code */ FileMgr.prototype.reader_onloadstart = function(filePath,result) { this.fileReaders[filePath].onloadstart(result); } FileMgr.prototype.reader_onprogress = function(filePath,result) { this.fileReaders[filePath].onprogress(result); } FileMgr.prototype.reader_onload = function(filePath,result) { this.fileReaders[filePath].result = unescape(result); this.fileReaders[filePath].onload(this.fileReaders[filePath].result); } FileMgr.prototype.reader_onerror = function(filePath,err) { this.fileReaders[filePath].result = err; this.fileReaders[filePath].onerror(err); } FileMgr.prototype.reader_onloadend = function(filePath,result) { this.fileReaders[filePath].onloadend(result); } /******************************************* * * private writer callback delegation * called from native code */ FileMgr.prototype.writer_onerror = function(filePath,err) { this.fileWriters[filePath].onerror(err); } FileMgr.prototype.writer_oncomplete = function(filePath,result) { this.fileWriters[filePath].oncomplete(result); // result contains bytes written } FileMgr.prototype.getFileBasePaths = function() { //PhoneGap.exec("File.getFileBasePaths"); } FileMgr.prototype.testFileExists = function(fileName, successCallback, errorCallback) { var test = FileUtil.testFileExists(fileName); test ? successCallback() : errorCallback(); } FileMgr.prototype.testDirectoryExists = function(dirName, successCallback, errorCallback) { this.successCallback = successCallback; this.errorCallback = errorCallback; var test = FileUtil.testDirectoryExists(dirName); test ? successCallback() : errorCallback(); } FileMgr.prototype.createDirectory = function(dirName, successCallback, errorCallback) { this.successCallback = successCallback; this.errorCallback = errorCallback; var test = FileUtil.createDirectory(dirName); test ? successCallback() : errorCallback(); } FileMgr.prototype.deleteDirectory = function(dirName, successCallback, errorCallback) { this.successCallback = successCallback; this.errorCallback = errorCallback; var test = FileUtil.deleteDirectory(dirName); test ? successCallback() : errorCallback(); } FileMgr.prototype.deleteFile = function(fileName, successCallback, errorCallback) { this.successCallback = successCallback; this.errorCallback = errorCallback; FileUtil.deleteFile(fileName); test ? successCallback() : errorCallback(); } FileMgr.prototype.getFreeDiskSpace = function(successCallback, errorCallback) { if(this.freeDiskSpace > 0) { return this.freeDiskSpace; } else { this.successCallback = successCallback; this.errorCallback = errorCallback; this.freeDiskSpace = FileUtil.getFreeDiskSpace(); (this.freeDiskSpace > 0) ? successCallback() : errorCallback(); } } // File Reader function FileReader() { this.fileName = ""; this.result = null; this.onloadstart = null; this.onprogress = null; this.onload = null; this.onerror = null; this.onloadend = null; } FileReader.prototype.abort = function() { // Not Implemented } FileReader.prototype.readAsText = function(file) { if(this.fileName && this.fileName.length > 0) { navigator.fileMgr.removeFileReader(this.fileName,this); } this.fileName = file; navigator.fileMgr.addFileReader(this.fileName,this); return FileUtil.read(this.fileName); } // File Writer function FileWriter() { this.fileName = ""; this.result = null; this.readyState = 0; // EMPTY this.result = null; this.onerror = null; this.oncomplete = null; } FileWriter.prototype.writeAsText = function(file,text,bAppend) { if(this.fileName && this.fileName.length > 0) { navigator.fileMgr.removeFileWriter(this.fileName,this); } this.fileName = file; if(bAppend != true) { bAppend = false; // for null values } navigator.fileMgr.addFileWriter(file,this); this.readyState = 0; // EMPTY var call = FileUtil.write(file, text, bAppend); this.result = null; } /** * This class provides access to device GPS data. * @constructor */ function Geolocation() { /** * The last known GPS position. */ this.lastPosition = null; this.lastError = null; this.listeners = null; }; var geoListeners = []; Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) { var position = Geo.getCurrentLocation(); this.global_success = successCallback; this.fail = errorCallback; } // Run the global callback Geolocation.prototype.gotCurrentPosition = function(lat, lng, alt, altacc, head, vel, stamp) { if (lat == "undefined" || lng == "undefined") { this.fail(); } else { coords = new Coordinates(lat, lng, alt, acc, head, vel); loc = new Position(coords, stamp); this.lastPosition = loc; this.global_success(loc); } } /* * This turns on the GeoLocator class, which has two listeners. * The listeners have their own timeouts, and run independently of this process * In this case, we return the key to the watch hash */ Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) { var frequency = (options != undefined)? options.frequency : 10000; var key = geoListeners.push( {"success" : successCallback, "fail" : errorCallback }) - 1; // TO-DO: Get the names of the method and pass them as strings to the Java. return Geo.start(frequency, key); } /* * Retrieve and stop this listener from listening to the GPS * */ Geolocation.prototype.success = function(key, lat, lng, alt, altacc, head, vel, stamp) { var coords = new Coordinates(lat, lng, alt, acc, head, vel); var loc = new Position(coords, stamp); geoListeners[key].success(loc); } Geolocation.prototype.fail = function(key) { geoListeners[key].fail(); } Geolocation.prototype.clearWatch = function(watchId) { Geo.stop(watchId); } PhoneGap.addConstructor(function() { // Taken from Jesse's geo fix (similar problem) in PhoneGap iPhone. Go figure, same browser! function __proxyObj(origObj, proxyObj, funkList) { for (var v in funkList) { origObj[funkList[v]] = proxyObj[funkList[v]]; } } // In the case of Android, we can use the Native Geolocation Object if it exists, so only load this on 1.x devices if (typeof navigator.geolocation == 'undefined') { navigator.geolocation = new Geolocation(); } }); function KeyEvent() { } KeyEvent.prototype.backTrigger = function() { var e = document.createEvent('Events'); e.initEvent('backKeyDown'); document.dispatchEvent(e); } if (document.keyEvent == null || typeof document.keyEvent == 'undefined') { window.keyEvent = document.keyEvent = new KeyEvent(); } com.phonegap.AudioHandlerProxy = function() { this.className = "com.phonegap.AudioHandler"; }; com.phonegap.AudioHandlerProxy.prototype.startRecordingAudio = function(id, file) { return PhoneGap.exec(this.className, "startRecordingAudio", [id, file]); }; com.phonegap.AudioHandlerProxy.prototype.stopRecordingAudio = function(id) { return PhoneGap.exec(this.className, "stopRecordingAudio", [id]); }; com.phonegap.AudioHandlerProxy.prototype.startPlayingAudio = function(id, file) { return PhoneGap.exec(this.className, "startPlayingAudio", [id, file]); }; com.phonegap.AudioHandlerProxy.prototype.pausePlayingAudio = function(id) { return PhoneGap.exec(this.className, "pausePlayingAudio", [id]); }; com.phonegap.AudioHandlerProxy.prototype.stopPlayingAudio = function(id) { return PhoneGap.exec(this.className, "stopPlayingAudio", [id]); }; com.phonegap.AudioHandlerProxy.prototype.getCurrentPositionAudio = function(id) { return PhoneGap.exec(this.className, "getCurrentPositionAudio", [id]); }; com.phonegap.AudioHandlerProxy.prototype.getDurationAudio = function(id, file) { return PhoneGap.exec(this.className, "getDurationAudio", [id, file]); }; com.phonegap.AudioHandler = new com.phonegap.AudioHandlerProxy(); /** * 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 * * @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 * @param errorCallback The callback to be called if there is an error. * errorCallback(int errorCode) - OPTIONAL * @param statusCallback The callback to be called when media status has changed. * statusCallback(int statusCode) - OPTIONAL */ Media = function(src, successCallback, errorCallback, statusCallback) { // successCallback optional if (successCallback && (typeof successCallback != "function")) { console.log("Media Error: successCallback is not a function"); return; } // errorCallback optional if (errorCallback && (typeof errorCallback != "function")) { console.log("Media Error: errorCallback is not a function"); return; } // statusCallback optional if (statusCallback && (typeof statusCallback != "function")) { console.log("Media Error: statusCallback is not a function"); return; } this.id = PhoneGap.createUUID(); PhoneGap.mediaObjects[this.id] = this; this.src = src; this.successCallback = successCallback; this.errorCallback = errorCallback; this.statusCallback = statusCallback; this._duration = -1; }; // Media messages Media.MEDIA_STATE = 1; Media.MEDIA_DURATION = 2; Media.MEDIA_ERROR = 3; // Media states Media.MEDIA_NONE = 0; Media.MEDIA_STARTING = 1; Media.MEDIA_RUNNING = 2; Media.MEDIA_PAUSED = 3; Media.MEDIA_STOPPED = 4; Media.MEDIA_MSG = ["None", "Starting", "Running", "Paused", "Stopped"]; // TODO: Will MediaError be used? /** * This class contains information about any Media errors. * @constructor */ function MediaError() { this.code = null, this.message = ""; }; MediaError.MEDIA_ERR_ABORTED = 1; MediaError.MEDIA_ERR_NETWORK = 2; MediaError.MEDIA_ERR_DECODE = 3; MediaError.MEDIA_ERR_NONE_SUPPORTED = 4; /** * Start or resume playing audio file. */ Media.prototype.play = function() { com.phonegap.AudioHandler.startPlayingAudio(this.id, this.src); }; /** * Stop playing audio file. */ Media.prototype.stop = function() { com.phonegap.AudioHandler.stopPlayingAudio(this.id); }; /** * Pause playing audio file. */ Media.prototype.pause = function() { com.phonegap.AudioHandler.pausePlayingAudio(this.id); }; /** * Get duration of an audio file. * The duration is only set for audio that is playing, paused or stopped. * * @return duration or -1 if not known. */ Media.prototype.getDuration = function() { return this._duration; }; /** * Get position of audio. * * @return */ Media.prototype.getCurrentPosition = function() { return com.phonegap.AudioHandler.getCurrentPositionAudio(this.id); }; /** * Start recording audio file. */ Media.prototype.startRecord = function() { com.phonegap.AudioHandler.startRecordingAudio(this.id, this.src); }; /** * Stop recording audio file. */ Media.prototype.stopRecord = function() { com.phonegap.AudioHandler.stopRecordingAudio(this.id); }; com.phonegap.NetworkManagerProxy = function() { this.className = "com.phonegap.NetworkManager"; }; com.phonegap.NetworkManagerProxy.prototype.isAvailable = function() { return PhoneGap.exec(this.className, "isAvailable", []); }; com.phonegap.NetworkManagerProxy.prototype.isWifiActive = function() { return PhoneGap.exec(this.className, "isWifiActive", []); }; com.phonegap.NetworkManagerProxy.prototype.isReachable = function(uri) { return PhoneGap.exec(this.className, "isReachable", [uri]); }; com.phonegap.NetworkManager = new com.phonegap.NetworkManagerProxy(); /** * This class contains information about any NetworkStatus. * @constructor */ function NetworkStatus() { this.code = null; this.message = ""; }; NetworkStatus.NOT_REACHABLE = 0; NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK = 1; NetworkStatus.REACHABLE_VIA_WIFI_NETWORK = 2; /** * This class provides access to device Network data (reachability). * @constructor */ function Network() { /** * The last known Network status. * { hostName: string, ipAddress: string, remoteHostStatus: int(0/1/2), internetConnectionStatus: int(0/1/2), localWiFiConnectionStatus: int (0/2) } */ this.lastReachability = null; }; /** * Called by the geolocation framework when the reachability status has changed. * @param {Reachibility} reachability The current reachability status. */ Network.prototype.updateReachability = function(reachability) { this.lastReachability = reachability; }; /** * * @param {Object} uri * @param {Function} win * @param {Object} options (isIpAddress:boolean) */ Network.prototype.isReachable = function(uri, win, options) { var status = new NetworkStatus(); if(com.phonegap.NetworkManager.isReachable(uri)) { if (com.phonegap.NetworkManager.isWifiActive()) { status.code = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK; } else { status.code = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK; } } else { status.code = NetworkStatus.NOT_REACHABLE; } win(status); }; PhoneGap.addConstructor(function() { if (typeof navigator.network == "undefined") navigator.network = new Network(); });/** * This class provides access to notifications on the device. */ function Notification() { } /** * Open a native alert dialog, with a customizable title and button text. * @param {String} message Message to print in the body of the alert * @param {String} [title="Alert"] Title of the alert dialog (default: Alert) * @param {String} [buttonLabel="OK"] Label of the close button (default: OK) */ Notification.prototype.alert = function(message, title, buttonLabel) { // Default is to use a browser alert; this will use "index.html" as the title though alert(message); }; /** * Start spinning the activity indicator on the statusbar */ Notification.prototype.activityStart = function() { }; /** * Stop spinning the activity indicator on the statusbar, if it's currently spinning */ Notification.prototype.activityStop = function() { }; /** * Causes the device to blink a status LED. * @param {Integer} count The number of blinks. * @param {String} colour The colour of the light. */ Notification.prototype.blink = function(count, colour) { }; /** * Causes the device to vibrate. * @param {Integer} mills The number of milliseconds to vibrate for. */ Notification.prototype.vibrate = function(mills) { }; /** * Causes the device to beep. * @param {Integer} count The number of beeps. * @param {Integer} volume The volume of the beep. */ Notification.prototype.beep = function(count, volume) { }; // TODO: of course on Blackberry and Android there notifications in the UI as well PhoneGap.addConstructor(function() { if (typeof navigator.notification == "undefined") navigator.notification = new Notification(); }); Notification.prototype.vibrate = function(mills) { DroidGap.vibrate(mills); } /* * On the Android, we don't beep, we notify you with your * notification! We shouldn't keep hammering on this, and should * review what we want beep to do. */ Notification.prototype.beep = function(count, volume) { DroidGap.beep(count); } /** * This class contains position information. * @param {Object} lat * @param {Object} lng * @param {Object} acc * @param {Object} alt * @param {Object} altacc * @param {Object} head * @param {Object} vel * @constructor */ function Position(coords, timestamp) { this.coords = coords; this.timestamp = new Date().getTime(); } function Coordinates(lat, lng, alt, acc, head, vel, altacc) { /** * The latitude of the position. */ this.latitude = lat; /** * The longitude of the position, */ this.longitude = lng; /** * The accuracy of the position. */ this.accuracy = acc; /** * The altitude of the position. */ this.altitude = alt; /** * The direction the device is moving at the position. */ this.heading = head; /** * The velocity with which the device is moving at the position. */ this.speed = vel; /** * The altitude accuracy of the position. */ this.altitudeAccuracy = (altacc != 'undefined') ? altacc : null; } /** * This class specifies the options for requesting position data. * @constructor */ function PositionOptions() { /** * Specifies the desired position accuracy. */ this.enableHighAccuracy = true; /** * The timeout after which if position data cannot be obtained the errorCallback * is called. */ this.timeout = 10000; } /** * This class contains information about any GSP errors. * @constructor */ function PositionError() { this.code = null; this.message = ""; } PositionError.UNKNOWN_ERROR = 0; PositionError.PERMISSION_DENIED = 1; PositionError.POSITION_UNAVAILABLE = 2; PositionError.TIMEOUT = 3; PhoneGap.addConstructor(function() { if (typeof navigator.splashScreen == "undefined") { navigator.splashScreen = SplashScreen; // SplashScreen object come from native side through addJavaScriptInterface } });com.phonegap.StorageProxy = function() { this.className = "com.phonegap.Storage"; }; com.phonegap.StorageProxy.prototype.executeSql = function(query, params, id) { return PhoneGap.exec(this.className, "executeSql", [query, params, id]); }; com.phonegap.StorageProxy.prototype.openDatabase = function(name, version, display_name, size) { return PhoneGap.exec(this.className, "openDatabase", [name, version, display_name, size]); }; com.phonegap.Storage = new com.phonegap.StorageProxy(); /* * This is purely for the Android 1.5/1.6 HTML 5 Storage * I was hoping that Android 2.0 would deprecate this, but given the fact that * most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required */ var DroidDB = function() { this.txQueue = []; }; DroidDB.prototype.addResult = function(rawdata, tx_id) { eval("var data = " + rawdata); var tx = this.txQueue[tx_id]; tx.resultSet.push(data); }; DroidDB.prototype.completeQuery = function(tx_id) { var tx = this.txQueue[tx_id]; var r = new result(); r.rows.resultSet = tx.resultSet; r.rows.length = tx.resultSet.length; tx.win(r); }; DroidDB.prototype.fail = function(reason, tx_id) { var tx = this.txQueue[tx_id]; tx.fail(reason); }; var DatabaseShell = function() { }; DatabaseShell.prototype.transaction = function(process) { tx = new Tx(); process(tx); }; var Tx = function() { droiddb.txQueue.push(this); this.id = droiddb.txQueue.length - 1; this.resultSet = []; }; Tx.prototype.executeSql = function(query, params, win, fail) { com.phonegap.Storage.executeSql(query, params, this.id); tx.win = win; tx.fail = fail; }; var result = function() { this.rows = new Rows(); }; var Rows = function() { this.resultSet = []; this.length = 0; }; Rows.prototype.item = function(row_id) { return this.resultSet[id]; }; var dbSetup = function(name, version, display_name, size) { com.phonegap.Storage.openDatabase(name, version, display_name, size) db_object = new DatabaseShell(); return db_object; }; PhoneGap.addConstructor(function() { if (typeof window.openDatabase == "undefined") { navigator.openDatabase = window.openDatabase = dbSetup; window.droiddb = new DroidDB(); } });