*
- * private reader callback delegation
- * called from native code
+ * @param file The name of the file
*/
-FileMgr.prototype.reader_onloadstart = function(filePath,result)
-{
- this.fileReaders[filePath].onloadstart(result);
-}
+FileReader.prototype.readAsDataURL = function(file) {
+ this.fileName = file;
-FileMgr.prototype.reader_onprogress = function(filePath,result)
-{
- this.fileReaders[filePath].onprogress(result);
-}
+ // LOADING state
+ this.readyState = FileReader.LOADING;
-FileMgr.prototype.reader_onload = function(filePath,result)
-{
- this.fileReaders[filePath].result = unescape(result);
- this.fileReaders[filePath].onload(this.fileReaders[filePath].result);
-}
+ // If loadstart callback
+ if (typeof this.onloadstart == "function") {
+ var evt = File._createEvent("loadstart", this);
+ this.onloadstart(evt);
+ }
-FileMgr.prototype.reader_onerror = function(filePath,err)
-{
- this.fileReaders[filePath].result = err;
- this.fileReaders[filePath].onerror(err);
-}
+ var me = this;
-FileMgr.prototype.reader_onloadend = function(filePath,result)
-{
- this.fileReaders[filePath].onloadend(result);
-}
+ // Read file
+ navigator.fileMgr.readAsDataURL(file,
-/*******************************************
+ // Success callback
+ function(r) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileReader.DONE) {
+ return;
+ }
+
+ // Save result
+ me.result = r;
+
+ // DONE state
+ me.readyState = FileReader.DONE;
+
+ // If onload callback
+ if (typeof me.onload == "function") {
+ var evt = File._createEvent("load", me);
+ me.onload(evt);
+ }
+
+ // If onloadend callback
+ if (typeof me.onloadend == "function") {
+ var evt = File._createEvent("loadend", me);
+ me.onloadend(evt);
+ }
+ },
+
+ // Error callback
+ function(e) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileReader.DONE) {
+ return;
+ }
+
+ // Save error
+ me.error = e;
+
+ // DONE state
+ me.readyState = FileReader.DONE;
+
+ // If onerror callback
+ if (typeof me.onerror == "function") {
+ var evt = File._createEvent("error", me);
+ me.onerror(evt);
+ }
+
+ // If onloadend callback
+ if (typeof me.onloadend == "function") {
+ var evt = File._createEvent("loadend", me);
+ me.onloadend(evt);
+ }
+ }
+ );
+};
+
+/**
+ * Read file and return data as a binary data.
*
- * 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);
-}
+ * @param file The name of the file
+ */
+FileReader.prototype.readAsBinaryString = function(file) {
+ // TODO - Can't return binary data to browser.
+ this.fileName = file;
+};
+//-----------------------------------------------------------------------------
// File Writer
+//-----------------------------------------------------------------------------
-function FileWriter()
-{
- this.fileName = "";
- this.result = null;
- this.readyState = 0; // EMPTY
- this.result = null;
- this.onerror = null;
- this.oncomplete = null;
-}
+/**
+ * This class writes to the mobile device file system.
+ *
+ * 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"
+ */
+function FileWriter() {
+ this.fileName = "";
+ this.result = null;
+ this.readyState = 0; // EMPTY
+ this.result = null;
+ this.onerror = null;
+ this.oncomplete = null;
+};
+
+// States
+FileWriter.EMPTY = 0;
+FileWriter.LOADING = 1;
+FileWriter.DONE = 2;
+
+FileWriter.prototype.writeAsText = function(file, text, bAppend) {
+ if (bAppend != true) {
+ bAppend = false; // for null values
+ }
+
+ this.fileName = file;
+
+ // LOADING state
+ this.readyState = FileWriter.LOADING;
+
+ var me = this;
+
+ // Read file
+ navigator.fileMgr.writeAsText(file, text, bAppend,
+
+ // Success callback
+ function(r) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileWriter.DONE) {
+ return;
+ }
+
+ // Save result
+ me.result = r;
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If oncomplete callback
+ if (typeof me.oncomplete == "function") {
+ var evt = File._createEvent("complete", me);
+ me.oncomplete(evt);
+ }
+ },
+
+ // Error callback
+ function(e) {
+
+ // If DONE (cancelled), then don't do anything
+ if (me.readyState == FileWriter.DONE) {
+ return;
+ }
+
+ // Save error
+ me.error = e;
+
+ // DONE state
+ me.readyState = FileWriter.DONE;
+
+ // If onerror callback
+ if (typeof me.onerror == "function") {
+ var evt = File._createEvent("error", me);
+ me.onerror(evt);
+ }
+ }
+ );
+
+};
-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.
- */
+
+ // The last known GPS position.
this.lastPosition = null;
- this.lastError = null;
- this.listeners = null;
+
+ // Geolocation listeners
+ this.listeners = {};
};
-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
+/**
+ * Position error object
*
+ * @param code
+ * @param message
*/
-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);
+function PositionError(code, message) {
+ this.code = code;
+ this.message = message;
+};
+
+PositionError.PERMISSION_DENIED = 1;
+PositionError.POSITION_UNAVAILABLE = 2;
+PositionError.TIMEOUT = 3;
+
+/**
+ * Asynchronously aquires the current position.
+ *
+ * @param {Function} successCallback The function to call when the position data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading position. (OPTIONAL)
+ * @param {PositionOptions} options The options for getting the position data. (OPTIONAL)
+ */
+Geolocation.prototype.getCurrentPosition = function(successCallback, errorCallback, options) {
+ if (navigator._geo.listeners["global"]) {
+ console.log("Geolocation Error: Still waiting for previous getCurrentPosition() request.");
+ try {
+ errorCallback(new PositionError(PositionError.TIMEOUT, "Geolocation Error: Still waiting for previous getCurrentPosition() request."));
+ } catch (e) {
+ }
+ return;
+ }
+ var maximumAge = 10000;
+ var enableHighAccuracy = false;
+ var timeout = 10000;
+ if (typeof options != "undefined") {
+ if (typeof options.maximumAge != "undefined") {
+ maximumAge = options.maximumAge;
+ }
+ if (typeof options.enableHighAccuracy != "undefined") {
+ enableHighAccuracy = options.enableHighAccuracy;
+ }
+ if (typeof options.timeout != "undefined") {
+ timeout = options.timeout;
+ }
+ }
+ navigator._geo.listeners["global"] = {"success" : successCallback, "fail" : errorCallback };
+ PhoneGap.execAsync(null, null, "Geolocation", "getCurrentLocation", [enableHighAccuracy, timeout, maximumAge]);
}
-Geolocation.prototype.fail = function(key)
-{
- geoListeners[key].fail();
-}
-
-Geolocation.prototype.clearWatch = function(watchId)
-{
- Geo.stop(watchId);
-}
+/**
+ * Asynchronously watches the geolocation for changes to geolocation. When a change occurs,
+ * the successCallback is called with the new location.
+ *
+ * @param {Function} successCallback The function to call each time the location data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the location data. (OPTIONAL)
+ * @param {PositionOptions} options The options for getting the location data such as frequency. (OPTIONAL)
+ * @return String The watch id that must be passed to #clearWatch to stop watching.
+ */
+Geolocation.prototype.watchPosition = function(successCallback, errorCallback, options) {
+ var maximumAge = 10000;
+ var enableHighAccuracy = false;
+ var timeout = 10000;
+ if (typeof options != "undefined") {
+ if (typeof options.frequency != "undefined") {
+ maximumAge = options.frequency;
+ }
+ if (typeof options.maximumAge != "undefined") {
+ maximumAge = options.maximumAge;
+ }
+ if (typeof options.enableHighAccuracy != "undefined") {
+ enableHighAccuracy = options.enableHighAccuracy;
+ }
+ if (typeof options.timeout != "undefined") {
+ timeout = options.timeout;
+ }
+ }
+ var id = PhoneGap.createUUID();
+ navigator._geo.listeners[id] = {"success" : successCallback, "fail" : errorCallback };
+ PhoneGap.execAsync(null, null, "Geolocation", "start", [id, enableHighAccuracy, timeout, maximumAge]);
+ return id;
+};
+
+/*
+ * Native callback when watch position has a new position.
+ * PRIVATE METHOD
+ *
+ * @param {String} id
+ * @param {Number} lat
+ * @param {Number} lng
+ * @param {Number} alt
+ * @param {Number} altacc
+ * @param {Number} head
+ * @param {Number} vel
+ * @param {Number} stamp
+ */
+Geolocation.prototype.success = function(id, lat, lng, alt, altacc, head, vel, stamp) {
+ var coords = new Coordinates(lat, lng, alt, altacc, head, vel);
+ var loc = new Position(coords, stamp);
+ try {
+ if (lat == "undefined" || lng == "undefined") {
+ navigator._geo.listeners[id].fail(new PositionError(PositionError.POSITION_UNAVAILABLE, "Lat/Lng are undefined."));
+ }
+ else {
+ navigator._geo.lastPosition = loc;
+ navigator._geo.listeners[id].success(loc);
+ }
+ }
+ catch (e) {
+ console.log("Geolocation Error: Error calling success callback function.");
+ }
+
+ if (id == "global") {
+ delete navigator._geo.listeners["global"];
+ }
+};
+
+/**
+ * Native callback when watch position has an error.
+ * PRIVATE METHOD
+ *
+ * @param {String} id The ID of the watch
+ * @param {Number} code The error code
+ * @param {String} msg The error message
+ */
+Geolocation.prototype.fail = function(id, code, msg) {
+ try {
+ navigator._geo.listeners[id].fail(new PositionError(code, msg));
+ }
+ catch (e) {
+ console.log("Geolocation Error: Error calling error callback function.");
+ }
+};
+
+/**
+ * Clears the specified heading watch.
+ *
+ * @param {String} id The ID of the watch returned from #watchPosition
+ */
+Geolocation.prototype.clearWatch = function(id) {
+ PhoneGap.execAsync(null, null, "Geolocation", "stop", [id]);
+ delete navigator._geo.listeners[id];
+};
+
+/**
+ * Force the PhoneGap geolocation to be used instead of built-in.
+ */
+Geolocation.usingPhoneGap = false;
+Geolocation.usePhoneGap = function() {
+ if (Geolocation.usingPhoneGap) {
+ return;
+ }
+ Geolocation.usingPhoneGap = true;
+
+ // Set built-in geolocation methods to our own implementations
+ // (Cannot replace entire geolocation, but can replace individual methods)
+ navigator.geolocation.setLocation = navigator._geo.setLocation;
+ navigator.geolocation.getCurrentPosition = navigator._geo.getCurrentPosition;
+ navigator.geolocation.watchPosition = navigator._geo.watchPosition;
+ navigator.geolocation.clearWatch = navigator._geo.clearWatch;
+ navigator.geolocation.start = navigator._geo.start;
+ navigator.geolocation.stop = navigator._geo.stop;
+};
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();
- }
+ navigator._geo = new Geolocation();
+
+ // No native geolocation object for Android 1.x, so use PhoneGap geolocation
+ if (typeof navigator.geolocation == 'undefined') {
+ navigator.geolocation = navigator._geo;
+ Geolocation.usingPhoneGap = true;
+ }
});
+
function KeyEvent()
{
}
@@ -1421,31 +1765,6 @@ 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.
@@ -1511,8 +1830,10 @@ PhoneGap.Media.onStatus = function(id, msg, value) {
* errorCallback(int errorCode) - OPTIONAL
* @param statusCallback The callback to be called when media status has changed.
* statusCallback(int statusCode) - OPTIONAL
+ * @param positionCallback The callback to be called when media position has changed.
+ * positionCallback(long position) - OPTIONAL
*/
-Media = function(src, successCallback, errorCallback, statusCallback) {
+Media = function(src, successCallback, errorCallback, statusCallback, positionCallback) {
// successCallback optional
if (successCallback && (typeof successCallback != "function")) {
@@ -1532,19 +1853,27 @@ Media = function(src, successCallback, errorCallback, statusCallback) {
return;
}
+ // statusCallback optional
+ if (positionCallback && (typeof positionCallback != "function")) {
+ console.log("Media Error: positionCallback 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.positionCallback = positionCallback;
this._duration = -1;
+ this._position = -1;
};
// Media messages
Media.MEDIA_STATE = 1;
Media.MEDIA_DURATION = 2;
-Media.MEDIA_ERROR = 3;
+Media.MEDIA_ERROR = 9;
// Media states
Media.MEDIA_NONE = 0;
@@ -1573,21 +1902,21 @@ MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
* Start or resume playing audio file.
*/
Media.prototype.play = function() {
- com.phonegap.AudioHandler.startPlayingAudio(this.id, this.src);
+ PhoneGap.execAsync(null, null, "Media", "startPlayingAudio", [this.id, this.src]);
};
/**
* Stop playing audio file.
*/
Media.prototype.stop = function() {
- com.phonegap.AudioHandler.stopPlayingAudio(this.id);
+ return PhoneGap.execAsync(null, null, "Media", "stopPlayingAudio", [this.id]);
};
/**
* Pause playing audio file.
*/
Media.prototype.pause = function() {
- com.phonegap.AudioHandler.pausePlayingAudio(this.id);
+ PhoneGap.execAsync(null, null, "Media", "pausePlayingAudio", [this.id]);
};
/**
@@ -1605,45 +1934,32 @@ Media.prototype.getDuration = function() {
*
* @return
*/
-Media.prototype.getCurrentPosition = function() {
- return com.phonegap.AudioHandler.getCurrentPositionAudio(this.id);
+Media.prototype.getCurrentPosition = function(success, fail) {
+ PhoneGap.execAsync(success, fail, "Media", "getCurrentPositionAudio", [this.id]);
};
/**
* Start recording audio file.
*/
Media.prototype.startRecord = function() {
- com.phonegap.AudioHandler.startRecordingAudio(this.id, this.src);
+ PhoneGap.execAsync(null, null, "Media", "startRecordingAudio", [this.id, this.src]);
};
/**
* Stop recording audio file.
*/
Media.prototype.stopRecord = function() {
- com.phonegap.AudioHandler.stopRecordingAudio(this.id);
+ PhoneGap.execAsync(null, null, "Media", "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 = "";
+ //this.code = null;
+ //this.message = "";
};
NetworkStatus.NOT_REACHABLE = 0;
@@ -1667,39 +1983,34 @@ function Network() {
* Called by the geolocation framework when the reachability status has changed.
* @param {Reachibility} reachability The current reachability status.
*/
+// TODO: Callback from native code not implemented for Android
Network.prototype.updateReachability = function(reachability) {
this.lastReachability = reachability;
};
/**
- *
+ * Determine if a URI is reachable over the network.
+
* @param {Object} uri
- * @param {Function} win
+ * @param {Function} callback
* @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;
- }
+Network.prototype.isReachable = function(uri, callback, options) {
+ var isIpAddress = false;
+ if (options && options.isIpAddress) {
+ isIpAddress = options.isIpAddress;
}
- else {
- status.code = NetworkStatus.NOT_REACHABLE;
- }
- win(status);
+ PhoneGap.execAsync(callback, null, "Network Status", "isReachable", [uri, isIpAddress]);
};
PhoneGap.addConstructor(function() {
if (typeof navigator.network == "undefined") navigator.network = new Network();
-});/**
+});
+
+/**
* This class provides access to notifications on the device.
*/
function Notification() {
-
}
/**
@@ -1731,7 +2042,7 @@ Notification.prototype.activityStop = function() {
* @param {String} colour The colour of the light.
*/
Notification.prototype.blink = function(count, colour) {
-
+
};
/**
@@ -1739,16 +2050,17 @@ Notification.prototype.blink = function(count, colour) {
* @param {Integer} mills The number of milliseconds to vibrate for.
*/
Notification.prototype.vibrate = function(mills) {
-
+ PhoneGap.execAsync(null, null, "Notification", "vibrate", [mills]);
};
/**
* Causes the device to beep.
+ * On Android, the default notification ringtone is played.
+ *
* @param {Integer} count The number of beeps.
- * @param {Integer} volume The volume of the beep.
*/
-Notification.prototype.beep = function(count, volume) {
-
+Notification.prototype.beep = function(count) {
+ PhoneGap.execAsync(null, null, "Notification", "beep", [count]);
};
// TODO: of course on Blackberry and Android there notifications in the UI as well
@@ -1757,21 +2069,6 @@ 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
@@ -1852,17 +2149,7 @@ 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
@@ -1907,7 +2194,7 @@ var Tx = function() {
};
Tx.prototype.executeSql = function(query, params, win, fail) {
- com.phonegap.Storage.executeSql(query, params, this.id);
+ PhoneGap.execAsync(null, null, "Storage", "executeSql", [query, params, this.id]);
tx.win = win;
tx.fail = fail;
};
@@ -1926,7 +2213,7 @@ Rows.prototype.item = function(row_id) {
};
var dbSetup = function(name, version, display_name, size) {
- com.phonegap.Storage.openDatabase(name, version, display_name, size)
+ PhoneGap.execAsync(null, null, "Storage", "openDatabase", [name, version, display_name, size]);
db_object = new DatabaseShell();
return db_object;
};
diff --git a/framework/src/com/phonegap/AccelListener.java b/framework/src/com/phonegap/AccelListener.java
index 4f4cae62..b24261d0 100755
--- a/framework/src/com/phonegap/AccelListener.java
+++ b/framework/src/com/phonegap/AccelListener.java
@@ -21,7 +21,7 @@ import android.webkit.WebView;
* This class listens to the accelerometer sensor and stores the latest
* acceleration values x,y,z.
*/
-public class AccelListener implements SensorEventListener, Plugin{
+public class AccelListener implements SensorEventListener, Plugin {
public static int STOPPED = 0;
public static int STARTING = 1;
@@ -118,6 +118,7 @@ public class AccelListener implements SensorEventListener, Plugin{
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
}
}
+ this.lastAccessTime = System.currentTimeMillis();
JSONObject r = new JSONObject();
r.put("x", this.x);
r.put("y", this.y);
diff --git a/framework/src/com/phonegap/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java
new file mode 100644
index 00000000..ac03c414
--- /dev/null
+++ b/framework/src/com/phonegap/ContactAccessor.java
@@ -0,0 +1,90 @@
+// Taken from Android Tutorials
+
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.phonegap;
+
+import java.lang.reflect.Constructor;
+
+import android.app.Activity;
+import android.webkit.WebView;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ * This abstract class defines SDK-independent API for communication with
+ * Contacts Provider. The actual implementation used by the application depends
+ * on the level of API available on the device. If the API level is Cupcake or
+ * Donut, we want to use the {@link ContactAccessorSdk3_4} class. If it is
+ * Eclair or higher, we want to use {@link ContactAccessorSdk5}.
+ */
+public abstract class ContactAccessor {
+
+ /**
+ * Static singleton instance of {@link ContactAccessor} holding the
+ * SDK-specific implementation of the class.
+ */
+ private static ContactAccessor sInstance;
+ protected final String LOG_TAG = "ContactsAccessor";
+ protected Activity mApp;
+ protected WebView mView;
+
+ public static ContactAccessor getInstance(WebView view, Activity app) {
+ if (sInstance == null) {
+ String className;
+
+ /*
+ * Check the version of the SDK we are running on. Choose an
+ * implementation class designed for that version of the SDK.
+ *
+ * Unfortunately we have to use strings to represent the class
+ * names. If we used the conventional ContactAccessorSdk5.class.getName()
+ * syntax, we would get a ClassNotFoundException at runtime on pre-Eclair SDKs.
+ * Using the above syntax would force Dalvik to load the class and try to
+ * resolve references to all other classes it uses. Since the pre-Eclair
+ * does not have those classes, the loading of ContactAccessorSdk5 would fail.
+ */
+
+ if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
+ className = "com.phonegap.ContactAccessorSdk3_4";
+ } else {
+ className = "com.phonegap.ContactAccessorSdk5";
+ }
+
+ /*
+ * Find the required class by name and instantiate it.
+ */
+ try {
+ Class extends ContactAccessor> clazz =
+ Class.forName(className).asSubclass(ContactAccessor.class);
+ // Grab constructor for contactsmanager class dynamically.
+ Constructor extends ContactAccessor> classConstructor = clazz.getConstructor(Class.forName("android.webkit.WebView"), Class.forName("android.app.Activity"));
+ sInstance = classConstructor.newInstance(view, app);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ return sInstance;
+ }
+
+ /**
+ * Handles searching through SDK-specific contacts API.
+ */
+ public abstract void search(JSONArray filter, JSONObject options);
+}
\ No newline at end of file
diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java
new file mode 100644
index 00000000..086e1052
--- /dev/null
+++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java
@@ -0,0 +1,362 @@
+// Taken from Android tutorials
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.phonegap;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.Contacts.ContactMethods;
+import android.provider.Contacts.ContactMethodsColumns;
+import android.provider.Contacts.Organizations;
+import android.provider.Contacts.People;
+import android.provider.Contacts.Phones;
+import android.util.Log;
+import android.webkit.WebView;
+
+/**
+ * An implementation of {@link ContactAccessor} that uses legacy Contacts API.
+ * These APIs are deprecated and should not be used unless we are running on a
+ * pre-Eclair SDK.
+ *
+ * There are several reasons why we wouldn't want to use this class on an Eclair device:
+ *
+ * - It would see at most one account, namely the first Google account created on the device.
+ *
- It would work through a compatibility layer, which would make it inherently less efficient.
+ *
- Not relevant to this particular example, but it would not have access to new kinds
+ * of data available through current APIs.
+ *
+ */
+@SuppressWarnings("deprecation")
+public class ContactAccessorSdk3_4 extends ContactAccessor {
+ private static final Map dbMap = new HashMap();
+ static {
+ dbMap.put("id", People._ID);
+ dbMap.put("displayName", People.DISPLAY_NAME);
+ dbMap.put("phoneNumbers", Phones.NUMBER);
+ dbMap.put("phoneNumbers.value", Phones.NUMBER);
+ dbMap.put("emails", ContactMethods.DATA);
+ dbMap.put("emails.value", ContactMethods.DATA);
+ dbMap.put("addresses", ContactMethodsColumns.DATA);
+ dbMap.put("addresses.formatted", ContactMethodsColumns.DATA);
+ dbMap.put("ims", ContactMethodsColumns.DATA);
+ dbMap.put("ims.value", ContactMethodsColumns.DATA);
+ dbMap.put("organizations", Organizations.COMPANY);
+ dbMap.put("organizations.name", Organizations.COMPANY);
+ dbMap.put("organizations.title", Organizations.TITLE);
+ dbMap.put("note", People.NOTES);
+ }
+
+ public ContactAccessorSdk3_4(WebView view, Activity app)
+ {
+ mApp = app;
+ mView = view;
+ }
+
+ @Override
+ public void search(JSONArray filter, JSONObject options) {
+ String searchTerm = "";
+ int limit = Integer.MAX_VALUE;
+ boolean multiple = true;
+ try {
+ searchTerm = options.getString("filter");
+ if (searchTerm.length()==0) {
+ searchTerm = "%";
+ }
+ else {
+ searchTerm = "%" + searchTerm + "%";
+ }
+ multiple = options.getBoolean("multiple");
+ if (multiple) {
+ limit = options.getInt("limit");
+ }
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+
+ ContentResolver cr = mApp.getContentResolver();
+
+ Set contactIds = buildSetOfContactIds(filter, searchTerm);
+
+ Iterator it = contactIds.iterator();
+
+ JSONArray contacts = new JSONArray();
+ JSONObject contact;
+ String contactId;
+ int pos = 0;
+ while (it.hasNext() && (pos < limit)) {
+ contact = new JSONObject();
+ try {
+ contactId = it.next();
+ contact.put("id", contactId);
+
+ // Do query for name and note
+ // Right now we are just querying the displayName
+ Cursor cur = cr.query(People.CONTENT_URI,
+ null,
+ "people._id = ?",
+ new String[] {contactId},
+ null);
+ cur.moveToFirst();
+
+ // name
+ contact.put("displayName", cur.getString(cur.getColumnIndex(People.DISPLAY_NAME)));
+ // phone number
+ contact.put("phoneNumbers", phoneQuery(cr, contactId));
+ // email
+ contact.put("emails", emailQuery(cr, contactId));
+ // addresses
+ contact.put("addresses", addressQuery(cr, contactId));
+ // organizations
+ contact.put("organizations", organizationQuery(cr, contactId));
+ // ims
+ contact.put("ims", imQuery(cr, contactId));
+ // note
+ contact.put("note", cur.getString(cur.getColumnIndex(People.NOTES)));
+ // nickname
+ // urls
+ // relationship
+ // birthdays
+ // anniversary
+
+ pos++;
+ cur.close();
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ contacts.put(contact);
+ }
+ mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');");
+ }
+
+ private Set buildSetOfContactIds(JSONArray filter, String searchTerm) {
+ Set contactIds = new HashSet();
+
+ String key;
+ try {
+ for (int i=0; i contactIds,
+ Uri uri, String projection, String selection, String[] selectionArgs) {
+ ContentResolver cr = mApp.getContentResolver();
+
+ Cursor cursor = cr.query(
+ uri,
+ null,
+ selection,
+ selectionArgs,
+ null);
+
+ while (cursor.moveToNext()) {
+ contactIds.add(cursor.getString(cursor.getColumnIndex(projection)));
+ }
+ cursor.close();
+ }
+
+ private JSONArray imQuery(ContentResolver cr, String contactId) {
+ String imWhere = ContactMethods.PERSON_ID
+ + " = ? AND " + ContactMethods.KIND + " = ?";
+ String[] imWhereParams = new String[]{contactId, ContactMethods.CONTENT_IM_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactMethods.CONTENT_URI,
+ null, imWhere, imWhereParams, null);
+ JSONArray ims = new JSONArray();
+ JSONObject im;
+ while (cursor.moveToNext()) {
+ im = new JSONObject();
+ try{
+ im.put("primary", false);
+ im.put("value", cursor.getString(
+ cursor.getColumnIndex(ContactMethodsColumns.DATA)));
+ im.put("type", cursor.getString(
+ cursor.getColumnIndex(ContactMethodsColumns.TYPE)));
+ ims.put(im);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return null;
+ }
+
+ private JSONArray organizationQuery(ContentResolver cr, String contactId) {
+ String orgWhere = ContactMethods.PERSON_ID + " = ?";
+ String[] orgWhereParams = new String[]{contactId};
+ Cursor cursor = cr.query(Organizations.CONTENT_URI,
+ null, orgWhere, orgWhereParams, null);
+ JSONArray organizations = new JSONArray();
+ JSONObject organization;
+ while (cursor.moveToNext()) {
+ organization = new JSONObject();
+ try{
+ organization.put("name", cursor.getString(cursor.getColumnIndex(Organizations.COMPANY)));
+ organization.put("title", cursor.getString(cursor.getColumnIndex(Organizations.TITLE)));
+ // organization.put("department", cursor.getString(cursor.getColumnIndex(Organizations)));
+ // organization.put("description", cursor.getString(cursor.getColumnIndex(Organizations)));
+ // organization.put("endDate", cursor.getString(cursor.getColumnIndex(Organizations)));
+ // organization.put("location", cursor.getString(cursor.getColumnIndex(Organizations)));
+ // organization.put("startDate", cursor.getString(cursor.getColumnIndex(Organizations)));
+ organizations.put(organization);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ return organizations;
+ }
+
+ private JSONArray addressQuery(ContentResolver cr, String contactId) {
+ String addrWhere = ContactMethods.PERSON_ID
+ + " = ? AND " + ContactMethods.KIND + " = ?";
+ String[] addrWhereParams = new String[]{contactId,
+ ContactMethods.CONTENT_POSTAL_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactMethods.CONTENT_URI,
+ null, addrWhere, addrWhereParams, null);
+ JSONArray addresses = new JSONArray();
+ JSONObject address;
+ while (cursor.moveToNext()) {
+ address = new JSONObject();
+ try{
+ address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactMethodsColumns.DATA)));
+ addresses.put(address);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ return addresses;
+ }
+
+ private JSONArray phoneQuery(ContentResolver cr, String contactId) {
+ Cursor cursor = cr.query(
+ Phones.CONTENT_URI,
+ null,
+ Phones.PERSON_ID +" = ?",
+ new String[]{contactId}, null);
+ JSONArray phones = new JSONArray();
+ JSONObject phone;
+ while (cursor.moveToNext()) {
+ phone = new JSONObject();
+ try{
+ phone.put("primary", false);
+ phone.put("value", cursor.getString(cursor.getColumnIndex(Phones.NUMBER)));
+ phone.put("type", cursor.getString(cursor.getColumnIndex(Phones.TYPE)));
+ phones.put(phone);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ return phones;
+ }
+
+ private JSONArray emailQuery(ContentResolver cr, String contactId) {
+ Cursor cursor = cr.query(
+ ContactMethods.CONTENT_EMAIL_URI,
+ null,
+ ContactMethods.PERSON_ID +" = ?",
+ new String[]{contactId}, null);
+ JSONArray emails = new JSONArray();
+ JSONObject email;
+ while (cursor.moveToNext()) {
+ email = new JSONObject();
+ try{
+ email.put("primary", false);
+ email.put("value", cursor.getString(cursor.getColumnIndex(ContactMethods.DATA)));
+ // TODO Find out why adding an email type throws and exception
+ //email.put("type", cursor.getString(cursor.getColumnIndex(ContactMethods.TYPE)));
+ emails.put(email);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ return emails;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java
new file mode 100644
index 00000000..bcad148f
--- /dev/null
+++ b/framework/src/com/phonegap/ContactAccessorSdk5.java
@@ -0,0 +1,553 @@
+// Taken from Android tutorials
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.phonegap;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.util.Log;
+import android.webkit.WebView;
+
+/**
+ * An implementation of {@link ContactAccessor} that uses current Contacts API.
+ * This class should be used on Eclair or beyond, but would not work on any earlier
+ * release of Android. As a matter of fact, it could not even be loaded.
+ *
+ * This implementation has several advantages:
+ *
+ * - It sees contacts from multiple accounts.
+ *
- It works with aggregated contacts. So for example, if the contact is the result
+ * of aggregation of two raw contacts from different accounts, it may return the name from
+ * one and the phone number from the other.
+ *
- It is efficient because it uses the more efficient current API.
+ *
- Not obvious in this particular example, but it has access to new kinds
+ * of data available exclusively through the new APIs. Exercise for the reader: add support
+ * for nickname (see {@link android.provider.ContactsContract.CommonDataKinds.Nickname}) or
+ * social status updates (see {@link android.provider.ContactsContract.StatusUpdates}).
+ *
+ */
+public class ContactAccessorSdk5 extends ContactAccessor {
+
+ private static final String WHERE_STRING = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
+ private static final Map dbMap = new HashMap();
+ static {
+ dbMap.put("id", ContactsContract.Contacts._ID);
+ dbMap.put("displayName", ContactsContract.Contacts.DISPLAY_NAME);
+ dbMap.put("name", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
+ dbMap.put("name.formatted", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
+ dbMap.put("name.familyName", ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
+ dbMap.put("name.givenName", ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
+ dbMap.put("name.middleName", ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
+ dbMap.put("name.honorificPrefix", ContactsContract.CommonDataKinds.StructuredName.PREFIX);
+ dbMap.put("name.honorificSuffix", ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
+ dbMap.put("nickname", ContactsContract.CommonDataKinds.Nickname.NAME);
+ dbMap.put("phoneNumbers", ContactsContract.CommonDataKinds.Phone.NUMBER);
+ dbMap.put("phoneNumbers.value", ContactsContract.CommonDataKinds.Phone.NUMBER);
+ dbMap.put("emails", ContactsContract.CommonDataKinds.Email.DATA);
+ dbMap.put("emails.value", ContactsContract.CommonDataKinds.Email.DATA);
+ dbMap.put("addresses", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
+ dbMap.put("addresses.formatted", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
+ dbMap.put("addresses.streetAddress", ContactsContract.CommonDataKinds.StructuredPostal.STREET);
+ dbMap.put("addresses.locality", ContactsContract.CommonDataKinds.StructuredPostal.CITY);
+ dbMap.put("addresses.region", ContactsContract.CommonDataKinds.StructuredPostal.REGION);
+ dbMap.put("addresses.postalCode", ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
+ dbMap.put("addresses.country", ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
+ dbMap.put("ims", ContactsContract.CommonDataKinds.Im.DATA);
+ dbMap.put("ims.value", ContactsContract.CommonDataKinds.Im.DATA);
+ dbMap.put("organizations", ContactsContract.CommonDataKinds.Organization.COMPANY);
+ dbMap.put("organizations.name", ContactsContract.CommonDataKinds.Organization.COMPANY);
+ dbMap.put("organizations.department", ContactsContract.CommonDataKinds.Organization.DEPARTMENT);
+ dbMap.put("organizations.title", ContactsContract.CommonDataKinds.Organization.TITLE);
+ dbMap.put("organizations.location", ContactsContract.CommonDataKinds.Organization.OFFICE_LOCATION);
+ dbMap.put("organizations.description", ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION);
+ //dbMap.put("published", null);
+ //dbMap.put("updated", null);
+ dbMap.put("birthday", ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
+ dbMap.put("anniversary", ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
+ //dbMap.put("gender", null);
+ dbMap.put("note", ContactsContract.CommonDataKinds.Note.NOTE);
+ //dbMap.put("preferredUsername", null);
+ //dbMap.put("photos.value", null);
+ //dbMap.put("tags.value", null);
+ dbMap.put("relationships", ContactsContract.CommonDataKinds.Relation.NAME);
+ dbMap.put("relationships.value", ContactsContract.CommonDataKinds.Relation.NAME);
+ dbMap.put("urls", ContactsContract.CommonDataKinds.Website.URL);
+ dbMap.put("urls.value", ContactsContract.CommonDataKinds.Website.URL);
+ //dbMap.put("accounts.domain", null);
+ //dbMap.put("accounts.username", null);
+ //dbMap.put("accounts.userid", null);
+ //dbMap.put("utcOffset", null);
+ //dbMap.put("connected", null);
+ }
+
+ public ContactAccessorSdk5(WebView view, Activity app)
+ {
+ mApp = app;
+ mView = view;
+ }
+
+ @Override
+ public void search(JSONArray filter, JSONObject options) {
+ String searchTerm = "";
+ int limit = Integer.MAX_VALUE;
+ boolean multiple = true;
+ try {
+ searchTerm = options.getString("filter");
+ if (searchTerm.length()==0) {
+ searchTerm = "%";
+ }
+ else {
+ searchTerm = "%" + searchTerm + "%";
+ }
+ multiple = options.getBoolean("multiple");
+ if (multiple) {
+ limit = options.getInt("limit");
+ }
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ // Get a cursor by creating the query.
+ ContentResolver cr = mApp.getContentResolver();
+
+ Set contactIds = buildSetOfContactIds(filter, searchTerm);
+
+ Iterator it = contactIds.iterator();
+
+ JSONArray contacts = new JSONArray();
+ JSONObject contact;
+ String contactId;
+ int pos = 0;
+ while (it.hasNext() && (pos < limit)) {
+ contact = new JSONObject();
+ contactId = it.next();
+
+ try {
+ contact.put("id", contactId);
+ contact.put("displayName", displayNameQuery(cr, contactId));
+ contact.put("name", nameQuery(cr, contactId));
+ contact.put("phoneNumbers", phoneQuery(cr, contactId));
+ contact.put("emails", emailQuery(cr, contactId));
+ contact.put("addresses", addressQuery(cr, contactId));
+ contact.put("organizations", organizationQuery(cr, contactId));
+ contact.put("ims",imQuery(cr, contactId));
+ contact.put("note",noteQuery(cr, contactId));
+ contact.put("nickname",nicknameQuery(cr, contactId));
+ contact.put("urls",websiteQuery(cr, contactId));
+ contact.put("relationships",relationshipQuery(cr, contactId));
+ contact.put("birthday",birthdayQuery(cr, contactId));
+ contact.put("anniversary",anniversaryQuery(cr, contactId));
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+
+ contacts.put(contact);
+ pos++;
+ }
+ mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');");
+ }
+
+ private Set buildSetOfContactIds(JSONArray filter, String searchTerm) {
+ Set contactIds = new HashSet();
+
+ String key;
+ try {
+ for (int i=0; i contactIds,
+ Uri uri, String projection, String selection, String[] selectionArgs) {
+ // Get a cursor by creating the query.
+ ContentResolver cr = mApp.getContentResolver();
+
+ Cursor cursor = cr.query(
+ uri,
+ new String[] {projection},
+ selection,
+ selectionArgs,
+ null);
+
+ while (cursor.moveToNext()) {
+ contactIds.add(cursor.getString(cursor.getColumnIndex(projection)));
+ }
+ cursor.close();
+ }
+
+ private String displayNameQuery(ContentResolver cr, String contactId) {
+ Cursor cursor = cr.query(
+ ContactsContract.Contacts.CONTENT_URI,
+ new String[] {ContactsContract.Contacts.DISPLAY_NAME},
+ ContactsContract.Contacts._ID + " = ?",
+ new String[] {contactId},
+ null);
+ cursor.moveToFirst();
+ String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
+ cursor.close();
+ return displayName;
+ }
+
+ private JSONArray organizationQuery(ContentResolver cr, String contactId) {
+ String[] orgWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, orgWhereParams, null);
+ JSONArray organizations = new JSONArray();
+ JSONObject organization = new JSONObject();
+ while (cursor.moveToNext()) {
+ try {
+ organization.put("department", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DEPARTMENT)));
+ organization.put("description", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION)));
+ // TODO No endDate
+ // organization.put("endDate", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization)));
+ organization.put("location", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.OFFICE_LOCATION)));
+ organization.put("name", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.COMPANY)));
+ // TODO no startDate
+ // organization.put("startDate", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization)));
+ organization.put("title", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE)));
+ organizations.put(organization);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return organizations;
+ }
+
+ private JSONArray addressQuery(ContentResolver cr, String contactId) {
+ String[] addrWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, addrWhereParams, null);
+ JSONArray addresses = new JSONArray();
+ JSONObject address = new JSONObject();
+ while (cursor.moveToNext()) {
+ try {
+ address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS)));
+ address.put("streetAddress", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET)));
+ address.put("locality", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)));
+ address.put("region", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION)));
+ address.put("postalCode", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE)));
+ address.put("country", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)));
+ addresses.put(address);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return addresses;
+ }
+
+ private JSONObject nameQuery(ContentResolver cr, String contactId) {
+ String[] addrWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE};
+ Cursor name = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, addrWhereParams, null);
+ JSONObject contactName = new JSONObject();
+ if (name.moveToFirst()) {
+ try {
+ String familyName = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
+ String givenName = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
+ String middleName = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
+ String honorificPrefix = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX));
+ String honorificSuffix = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX));
+
+ // Create the formatted name
+ StringBuffer formatted = new StringBuffer("");
+ if (honorificPrefix != null) { formatted.append(honorificPrefix + " "); }
+ if (givenName != null) { formatted.append(givenName + " "); }
+ if (middleName != null) { formatted.append(middleName + " "); }
+ if (familyName != null) { formatted.append(familyName + " "); }
+ if (honorificSuffix != null) { formatted.append(honorificSuffix + " "); }
+
+ contactName.put("familyName", familyName);
+ contactName.put("givenName", givenName);
+ contactName.put("middleName", middleName);
+ contactName.put("honorificPrefix", honorificPrefix);
+ contactName.put("honorificSuffix", honorificSuffix);
+ contactName.put("formatted", formatted);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ name.close();
+ return contactName;
+ }
+
+ private JSONArray phoneQuery(ContentResolver cr, String contactId) {
+ Cursor phones = cr.query(
+ ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+ null,
+ ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId,
+ null, null);
+ JSONArray phoneNumbers = new JSONArray();
+ JSONObject phoneNumber = new JSONObject();
+ while (phones.moveToNext()) {
+ try {
+ phoneNumber.put("primary", false); // Android does not store primary attribute
+ phoneNumber.put("value", phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
+ phoneNumber.put("type", phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)));
+ phoneNumbers.put(phoneNumber);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ phones.close();
+ return phoneNumbers;
+ }
+
+ private JSONArray emailQuery(ContentResolver cr, String contactId) {
+ Cursor emails = cr.query(
+ ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ null,
+ ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId,
+ null, null);
+ JSONArray emailAddresses = new JSONArray();
+ JSONObject email = new JSONObject();
+ while (emails.moveToNext()) {
+ try {
+ email.put("primary", false); // Android does not store primary attribute
+ email.put("value", emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)));
+ email.put("type", emails.getInt(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE)));
+ emailAddresses.put(email);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ emails.close();
+ return emailAddresses;
+ }
+
+ private JSONArray imQuery(ContentResolver cr, String contactId) {
+ String[] addrWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, addrWhereParams, null);
+ JSONArray ims = new JSONArray();
+ JSONObject im = new JSONObject();
+ while (cursor.moveToNext()) {
+ try {
+ im.put("primary", false); // Android does not store primary attribute
+ im.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
+ im.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.TYPE)));
+ ims.put(im);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return ims;
+ }
+
+ private String noteQuery(ContentResolver cr, String contactId) {
+ String[] noteWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, noteWhereParams, null);
+ String note = new String("");
+ if (cursor.moveToFirst()) {
+ note = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
+ }
+ cursor.close();
+ return note;
+ }
+
+ private String nicknameQuery(ContentResolver cr, String contactId) {
+ String[] nicknameWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, nicknameWhereParams, null);
+ String nickname = new String("");
+ if (cursor.moveToFirst()) {
+ nickname = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME));
+ }
+ cursor.close();
+ return nickname;
+ }
+
+ private JSONArray websiteQuery(ContentResolver cr, String contactId) {
+ String[] websiteWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, websiteWhereParams, null);
+ JSONArray websites = new JSONArray();
+ JSONObject website = new JSONObject();
+ while (cursor.moveToNext()) {
+ try {
+ website.put("primary", false); // Android does not store primary attribute
+ website.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL)));
+ website.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.TYPE)));
+ websites.put(website);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return websites;
+ }
+
+ private JSONArray relationshipQuery(ContentResolver cr, String contactId) {
+ String[] relationshipWhereParams = new String[]{contactId,
+ ContactsContract.CommonDataKinds.Relation.CONTENT_ITEM_TYPE};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, relationshipWhereParams, null);
+ JSONArray relationships = new JSONArray();
+ JSONObject relationship = new JSONObject();
+ while (cursor.moveToNext()) {
+ try {
+ relationship.put("primary", false); // Android does not store primary attribute
+ relationship.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Relation.NAME)));
+ relationship.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Relation.TYPE)));
+ relationships.put(relationship);
+ } catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+ cursor.close();
+ return relationships;
+ }
+
+ private String birthdayQuery(ContentResolver cr, String contactId) {
+ String birthday = conditionalStringQuery(cr, contactId, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
+ ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY, ContactsContract.CommonDataKinds.Event.TYPE,
+ ContactsContract.CommonDataKinds.Event.START_DATE);
+ return birthday;
+ }
+
+ private String anniversaryQuery(ContentResolver cr, String contactId) {
+ String anniversary = conditionalStringQuery(cr, contactId, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
+ ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY, ContactsContract.CommonDataKinds.Event.TYPE,
+ ContactsContract.CommonDataKinds.Event.START_DATE);
+ return anniversary;
+ }
+
+ private String conditionalStringQuery(ContentResolver cr, String contactId, String dataType, int type, String label, String data) {
+ String[] whereParams = new String[]{contactId, dataType};
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI,
+ null, WHERE_STRING, whereParams, null);
+ String retVal = new String("");
+ while (cursor.moveToNext()) {
+ if (type == cursor.getInt(cursor.getColumnIndex(label))) {
+ retVal = cursor.getString(cursor.getColumnIndex(data));
+ }
+ }
+ cursor.close();
+ return retVal;
+ }
+}
\ No newline at end of file
diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java
index 8924ccf9..9cf6a891 100755
--- a/framework/src/com/phonegap/ContactManager.java
+++ b/framework/src/com/phonegap/ContactManager.java
@@ -6,32 +6,17 @@ import org.json.JSONException;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
-import android.provider.Contacts.ContactMethods;
-import android.provider.Contacts.People;
import android.util.Log;
import android.webkit.WebView;
import android.content.Intent;
-import android.net.Uri;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
-@SuppressWarnings("deprecation")
public class ContactManager implements Plugin {
- public class ContactTriplet
- {
- public String name = "";
- public String email = "";
- public String phone = "";
- }
-
+ private static ContactAccessor contactAccessor;
WebView webView; // WebView object
DroidGap ctx; // DroidGap object
private static final String LOG_TAG = "Contact Query";
- Uri mPeople = android.provider.Contacts.People.CONTENT_URI;
- Uri mPhone = android.provider.Contacts.Phones.CONTENT_URI;
- Uri mEmail = android.provider.Contacts.ContactMethods.CONTENT_URI;
/**
* Constructor.
@@ -67,18 +52,28 @@ public class ContactManager implements Plugin {
* @return A CommandResult object with a status and message.
*/
public PluginResult execute(String action, JSONArray args) {
+ if (contactAccessor == null) {
+ contactAccessor = ContactAccessor.getInstance(webView, ctx);
+ }
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
try {
- if (action.equals("getContactsAndSendBack")) {
- this.getContactsAndSendBack();
+ if (action.equals("search")) {
+ contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1));
}
- else if (action.equals("search")) {
- this.search(args.getString(0), args.getString(1), args.getString(2));
+ else if (action.equals("create")) {
+ // TODO Coming soon!
+ }
+ else if (action.equals("save")) {
+ // TODO Coming soon!
+ }
+ else if (action.equals("remove")) {
+ // TODO Coming soon!
}
return new PluginResult(status, result);
} catch (JSONException e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
@@ -123,269 +118,4 @@ public class ContactManager implements Plugin {
*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
}
-
- //--------------------------------------------------------------------------
- // LOCAL METHODS
- //--------------------------------------------------------------------------
-
- // This is to add backwards compatibility to the OLD Contacts API\
- public void getContactsAndSendBack()
- {
- String[] projection = new String[] {
- People._ID,
- People.NAME,
- People.NUMBER,
- People.PRIMARY_EMAIL_ID
- };
-
- try{
- Cursor myCursor = this.ctx.managedQuery(mPeople, projection,
- null, null , People.NAME + " ASC");
- processResults(myCursor, true);
- }
- catch (SQLiteException ex)
- {
- Log.d(LOG_TAG, ex.getMessage());
- }
- }
-
- public void search(String name, String npa, String email)
- {
-
- if (email.length() > 0)
- searchByEmail(email);
- else
- searchPeople(name, npa);
- }
-
- private void searchByEmail(String email)
- {
- String[] projection = new String[] {
- ContactMethods._ID,
- ContactMethods.DATA,
- ContactMethods.KIND,
- ContactMethods.PERSON_ID
- };
- String[] variables = new String[] {
- email
- };
-
- try{
- Cursor myCursor = this.ctx.managedQuery(mEmail, projection,
- "contact_methods." + ContactMethods.DATA + " = ?" + "AND contact_methods.kind = 1", variables , ContactMethods.DATA + " ASC");
- getMethodData(myCursor);
-
- }
- catch (SQLiteException ex)
- {
- Log.d(LOG_TAG, ex.getMessage());
- }
-
- }
-
- private void searchPeople(String name, String number)
- {
- String conditions = "";
-
- if (name.length() == 0)
- {
- name = "%";
- conditions += People.NAME + " LIKE ? AND ";
- }
- else
- {
- conditions += People.NAME + " = ? AND ";
- }
-
- if (number.length() == 0)
- number = "%";
- else
- {
- number = number.replace('+', '%');
- number = number.replace('.', '%');
- number = number.replace('-', '%');
- }
-
- conditions += People.NUMBER + " LIKE ? ";
-
- String[] projection = new String[] {
- People._ID,
- People.NAME,
- People.NUMBER,
- People.PRIMARY_EMAIL_ID
- };
-
- String[] variables = new String[] {
- name, number
- };
-
- try{
- Cursor myCursor = this.ctx.managedQuery(mPeople, projection,
- conditions, variables , People.NAME + " ASC");
- processResults(myCursor, false);
- }
- catch (SQLiteException ex)
- {
- Log.d(LOG_TAG, ex.getMessage());
- }
-
- }
-
- private void processResults(Cursor cur, boolean all){
-
- if (cur.moveToFirst()) {
-
- String name;
- String phoneNumber;
- String email_id;
- String email;
-
- int nameColumn = cur.getColumnIndex(People.NAME);
- int phoneColumn = cur.getColumnIndex(People.NUMBER);
- int emailIdColumn = cur.getColumnIndex(People.PRIMARY_EMAIL_ID);
-
- do {
- // Get the field values
- name = cur.getString(nameColumn);
- phoneNumber = cur.getString(phoneColumn);
- email_id = cur.getString(emailIdColumn);
- if (email_id != null && email_id.length() > 0)
- email = getEmail(email_id);
- else
- email = "";
-
- // Code for backwards compatibility with the OLD Contacts API
- if (all) {
- this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"');");
- }
- else {
- this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"');");
- }
- } while (cur.moveToNext());
- if (all) {
- this.ctx.sendJavascript("navigator.contacts.droidDone();");
- }
- else {
- this.ctx.sendJavascript("navigator.contacts.droidDone();");
- }
- }
- else
- {
- if (all) {
- this.ctx.sendJavascript("navigator.contacts.fail('Error');");
- }
- else {
- this.ctx.sendJavascript("navigator.contacts.fail('None found!');");
- }
- }
- }
-
- private void getMethodData(Cursor cur)
- {
- ContactTriplet data = new ContactTriplet();
- String id;
- String email;
-
- if (cur.moveToFirst()) {
-
- int idColumn = cur.getColumnIndex(ContactMethods._ID);
- int emailColumn = cur.getColumnIndex(ContactMethods.DATA);
- do {
- // Get the field values
- id = cur.getString(idColumn);
- email = cur.getString(emailColumn);
-
- data = getContactData(id);
- if(data != null)
- {
- data.email = email;
- this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + data.name + "','" + data.phone + "','" + data.email +"');");
- }
- } while (cur.moveToNext());
- this.ctx.sendJavascript("navigator.contacts.droidDoneContacts();");
- }
- }
-
- private ContactTriplet getContactData(String id) {
- ContactTriplet data = null;
- String[] projection = new String[] {
- People._ID,
- People.NAME,
- People.NUMBER,
- People.PRIMARY_EMAIL_ID
- };
-
- String[] variables = new String[] {
- id
- };
-
- try{
- Cursor myCursor = this.ctx.managedQuery(mPeople, projection,
- People.PRIMARY_EMAIL_ID + " = ?", variables , People.NAME + " ASC");
- data = getTriplet(myCursor);
- }
- catch (SQLiteException ex)
- {
- Log.d(LOG_TAG, ex.getMessage());
- }
-
- return data;
- }
-
- private ContactTriplet getTriplet(Cursor cur) {
- ContactTriplet data = new ContactTriplet();
- if (cur.moveToFirst()) {
-
- int nameColumn = cur.getColumnIndex(People.NAME);
- int numberColumn = cur.getColumnIndex(People.NUMBER);
- do {
-
- data.name = cur.getString(nameColumn);
- data.phone = cur.getString(numberColumn);
-
- } while (cur.moveToNext());
- }
- return data;
- }
-
- private String getEmailColumnData(Cursor cur)
- {
- String email = "";
- if (cur != null && cur.moveToFirst()) {
- int emailColumn = cur.getColumnIndex(ContactMethods.DATA);
- do {
- // Get the field values
- email = cur.getString(emailColumn);
- } while (cur.moveToNext());
- }
- return email;
- }
-
- private String getEmail(String id)
- {
- String email = "";
- String[] projection = new String[] {
- ContactMethods._ID,
- ContactMethods.DATA,
- ContactMethods.KIND
- };
- String[] variables = new String[] {
- id
- };
-
- try
- {
- Cursor myCursor = this.ctx.managedQuery(mEmail, projection,
- "contact_methods." + ContactMethods._ID + " = ?" + " AND contact_methods.kind = 1", variables , ContactMethods.DATA + " ASC");
- email = getEmailColumnData(myCursor);
- }
- catch (SQLiteException ex)
- {
- Log.d(LOG_TAG, ex.getMessage());
- }
-
- return email;
- }
-
-
}
diff --git a/framework/src/com/phonegap/Device.java b/framework/src/com/phonegap/Device.java
old mode 100644
new mode 100755
index babd09fe..80c1281b
--- a/framework/src/com/phonegap/Device.java
+++ b/framework/src/com/phonegap/Device.java
@@ -23,23 +23,16 @@ package com.phonegap;
*/
import java.util.TimeZone;
-
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
-
import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
-import android.os.Vibrator;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.webkit.WebView;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
public class Device implements Plugin {
@@ -101,12 +94,6 @@ public class Device implements Plugin {
//r.put("phonegap", pg);
return new PluginResult(status, r);
}
- else if (action.equals("beep")) {
- this.beep(args.getLong(0));
- }
- else if (action.equals("vibrate")) {
- this.vibrate(args.getLong(0));
- }
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
@@ -160,46 +147,7 @@ public class Device implements Plugin {
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
-
- /**
- * Beep plays the default notification ringtone.
- *
- * @param count Number of times to play notification
- */
- public void beep(long count) {
- Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
- Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone);
- // If phone is not set to silent mode
- if (notification != null) {
- for (long i = 0; i < count; ++i) {
- notification.play();
- long timeout = 5000;
- while (notification.isPlaying() && (timeout > 0)) {
- timeout = timeout - 100;
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- }
- }
- }
- }
- }
-
- /**
- * Vibrates the device for the specified amount of time.
- *
- * @param time Time to vibrate in ms.
- */
- public void vibrate(long time){
- // Start the vibration, 0 defaults to half a second.
- if (time == 0) {
- time = 500;
- }
- Vibrator vibrator = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE);
- vibrator.vibrate(time);
- }
-
/**
* Get the OS name.
*
diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java
index 70d15328..a861732c 100755
--- a/framework/src/com/phonegap/DroidGap.java
+++ b/framework/src/com/phonegap/DroidGap.java
@@ -296,6 +296,7 @@ public class DroidGap extends Activity {
this.addService("File", "com.phonegap.FileUtils");
this.addService("Location", "com.phonegap.GeoBroker");
this.addService("Network Status", "com.phonegap.NetworkManager");
+ this.addService("Notification", "com.phonegap.Notification");
this.addService("Storage", "com.phonegap.Storage");
this.addService("Temperature", "com.phonegap.TempListener");
}
diff --git a/framework/src/com/phonegap/Notification.java b/framework/src/com/phonegap/Notification.java
new file mode 100755
index 00000000..68a18397
--- /dev/null
+++ b/framework/src/com/phonegap/Notification.java
@@ -0,0 +1,157 @@
+package com.phonegap;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import com.phonegap.api.Plugin;
+import com.phonegap.api.PluginResult;
+import android.content.Context;
+import android.content.Intent;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Vibrator;
+import android.webkit.WebView;
+
+/**
+ * This class provides access to notifications on the device.
+ */
+public class Notification implements Plugin {
+
+ WebView webView; // WebView object
+ DroidGap ctx; // DroidGap object
+
+ /**
+ * Constructor.
+ */
+ public Notification() {
+ }
+
+ /**
+ * Sets the context of the Command. This can then be used to do things like
+ * get file paths associated with the Activity.
+ *
+ * @param ctx The context of the main Activity.
+ */
+ public void setContext(DroidGap ctx) {
+ this.ctx = ctx;
+ }
+
+ /**
+ * Sets the main View of the application, this is the WebView within which
+ * a PhoneGap app runs.
+ *
+ * @param webView The PhoneGap WebView
+ */
+ public void setView(WebView webView) {
+ this.webView = webView;
+ }
+
+ /**
+ * Executes the request and returns CommandResult.
+ *
+ * @param action The command to execute.
+ * @param args JSONArry of arguments for the command.
+ * @return A CommandResult object with a status and message.
+ */
+ public PluginResult execute(String action, JSONArray args) {
+ PluginResult.Status status = PluginResult.Status.OK;
+ String result = "";
+
+ try {
+ if (action.equals("beep")) {
+ this.beep(args.getLong(0));
+ }
+ else if (action.equals("vibrate")) {
+ this.vibrate(args.getLong(0));
+ }
+ return new PluginResult(status, result);
+ } catch (JSONException e) {
+ return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ }
+ }
+
+ /**
+ * Identifies if action to be executed returns a value and should be run synchronously.
+ *
+ * @param action The action to execute
+ * @return T=returns value
+ */
+ public boolean isSynch(String action) {
+ return false;
+ }
+
+ /**
+ * Called when the system is about to start resuming a previous activity.
+ */
+ public void onPause() {
+ }
+
+ /**
+ * Called when the activity will start interacting with the user.
+ */
+ public void onResume() {
+ }
+
+ /**
+ * Called by AccelBroker when listener is to be shut down.
+ * Stop listener.
+ */
+ public void onDestroy() {
+ }
+
+ /**
+ * Called when an activity you launched exits, giving you the requestCode you started it with,
+ * the resultCode it returned, and any additional data from it.
+ *
+ * @param requestCode The request code originally supplied to startActivityForResult(),
+ * allowing you to identify who this result came from.
+ * @param resultCode The integer result code returned by the child activity through its setResult().
+ * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
+ */
+ public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+ }
+
+ //--------------------------------------------------------------------------
+ // LOCAL METHODS
+ //--------------------------------------------------------------------------
+
+ /**
+ * Beep plays the default notification ringtone.
+ *
+ * @param count Number of times to play notification
+ */
+ public void beep(long count) {
+ Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+ Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone);
+
+ // If phone is not set to silent mode
+ if (notification != null) {
+ for (long i = 0; i < count; ++i) {
+ notification.play();
+ long timeout = 5000;
+ while (notification.isPlaying() && (timeout > 0)) {
+ timeout = timeout - 100;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Vibrates the device for the specified amount of time.
+ *
+ * @param time Time to vibrate in ms.
+ */
+ public void vibrate(long time){
+ // Start the vibration, 0 defaults to half a second.
+ if (time == 0) {
+ time = 500;
+ }
+ Vibrator vibrator = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE);
+ vibrator.vibrate(time);
+ }
+
+}