diff --git a/example/index.html b/example/index.html index bdfee7c3..ecf05ee7 100644 --- a/example/index.html +++ b/example/index.html @@ -104,6 +104,7 @@ var obj = new ContactFindOptions(); obj.filter=""; obj.multiple=true; + obj.limit=5; navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], count_contacts, fail, obj); } diff --git a/framework/assets/js/accelerometer.js b/framework/assets/js/accelerometer.js index 3923a56a..f87cd082 100755 --- a/framework/assets/js/accelerometer.js +++ b/framework/assets/js/accelerometer.js @@ -102,7 +102,7 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb Accelerometer.prototype.clearWatch = function(id) { // Stop javascript timer & remove from timer list - if (id && navigator.accelerometer.timers[id]) { + if (id && navigator.accelerometer.timers[id] != undefined) { clearInterval(navigator.accelerometer.timers[id]); delete navigator.accelerometer.timers[id]; } diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 1d5eb4c0..2d735027 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -27,6 +27,27 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad this.connected = connected || null; }; + +Contact.prototype.remove = function(successCB, errorCB) { + if (this.id == null) { + var errorObj = new ContactError(); + errorObj.code = ContactError.NOT_FOUND_ERROR; + errorCB(errorObj); + } + + PhoneGap.execAsync(successCB, errorCB, "Contacts", "remove", [this.id]); +}; + +Contact.prototype.clone = function() { + var clonedContact = PhoneGap.clone(this); + clonedContact.id = null; + return clonedContact; +}; + +Contact.prototype.save = function(win, fail) { +}; + + var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { this.formatted = formatted || null; this.familyName = familyName || null; @@ -72,30 +93,26 @@ var Contacts = function() { this.records = new Array(); } -// Contacts.prototype.find = function(obj, win, fail) { Contacts.prototype.find = function(fields, win, fail, options) { - this.win = win; - this.fail = fail; - - PhoneGap.execAsync(null, null, "Contacts", "search", [fields, options]); + PhoneGap.execAsync(win, fail, "Contacts", "search", [fields, options]); +}; + +//This function does not create a new contact in the db. +//Must call contact.save() for it to be persisted in the db. +Contacts.prototype.create = function(properties) { + var contact = new Contact(); + for (i in properties) { + if (contact[i]!='undefined') { + contact[i]=properties[i]; + } + } + return contact; }; Contacts.prototype.droidDone = function(contacts) { this.win(eval('(' + contacts + ')')); }; -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); @@ -112,14 +129,14 @@ var ContactError = function() { this.code=null; }; -ContactError.INVALID_ARGUMENT_ERROR = 0; -ContactError.IO_ERROR = 1; +ContactError.UNKNOWN_ERROR = 0; +ContactError.INVALID_ARGUMENT_ERROR = 1; ContactError.NOT_FOUND_ERROR = 2; -ContactError.NOT_SUPPORTED_ERROR = 3; +ContactError.TIMEOUT_ERROR = 3; ContactError.PENDING_OPERATION_ERROR = 4; -ContactError.PERMISSION_DENIED_ERROR = 5; -ContactError.TIMEOUT_ERROR = 6; -ContactError.UNKNOWN_ERROR = 7; +ContactError.IO_ERROR = 5; +ContactError.NOT_SUPPORTED_ERROR = 6; +ContactError.PERMISSION_DENIED_ERROR = 20; PhoneGap.addConstructor(function() { if(typeof navigator.service == "undefined") navigator.service = new Object(); diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index 0c31d018..ab71d3d7 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -324,6 +324,42 @@ PhoneGap.stringify = function(args) { } }; +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +PhoneGap.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 0964a8eb..8aa92570 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -324,6 +324,42 @@ PhoneGap.stringify = function(args) { } }; +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +PhoneGap.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; @@ -687,7 +723,7 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb Accelerometer.prototype.clearWatch = function(id) { // Stop javascript timer & remove from timer list - if (id && navigator.accelerometer.timers[id]) { + if (id && navigator.accelerometer.timers[id] != undefined) { clearInterval(navigator.accelerometer.timers[id]); delete navigator.accelerometer.timers[id]; } @@ -940,6 +976,27 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad this.connected = connected || null; }; + +Contact.prototype.remove = function(successCB, errorCB) { + if (this.id == null) { + var errorObj = new ContactError(); + errorObj.code = ContactError.NOT_FOUND_ERROR; + errorCB(errorObj); + } + + PhoneGap.execAsync(successCB, errorCB, "Contacts", "remove", [this.id]); +}; + +Contact.prototype.clone = function() { + var clonedContact = PhoneGap.clone(this); + clonedContact.id = null; + return clonedContact; +}; + +Contact.prototype.save = function(win, fail) { +}; + + var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { this.formatted = formatted || null; this.familyName = familyName || null; @@ -985,30 +1042,26 @@ var Contacts = function() { this.records = new Array(); } -// Contacts.prototype.find = function(obj, win, fail) { Contacts.prototype.find = function(fields, win, fail, options) { - this.win = win; - this.fail = fail; - - PhoneGap.execAsync(null, null, "Contacts", "search", [fields, options]); + PhoneGap.execAsync(win, fail, "Contacts", "search", [fields, options]); +}; + +//This function does not create a new contact in the db. +//Must call contact.save() for it to be persisted in the db. +Contacts.prototype.create = function(properties) { + var contact = new Contact(); + for (i in properties) { + if (contact[i]!='undefined') { + contact[i]=properties[i]; + } + } + return contact; }; Contacts.prototype.droidDone = function(contacts) { this.win(eval('(' + contacts + ')')); }; -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); @@ -1025,14 +1078,14 @@ var ContactError = function() { this.code=null; }; -ContactError.INVALID_ARGUMENT_ERROR = 0; -ContactError.IO_ERROR = 1; +ContactError.UNKNOWN_ERROR = 0; +ContactError.INVALID_ARGUMENT_ERROR = 1; ContactError.NOT_FOUND_ERROR = 2; -ContactError.NOT_SUPPORTED_ERROR = 3; +ContactError.TIMEOUT_ERROR = 3; ContactError.PENDING_OPERATION_ERROR = 4; -ContactError.PERMISSION_DENIED_ERROR = 5; -ContactError.TIMEOUT_ERROR = 6; -ContactError.UNKNOWN_ERROR = 7; +ContactError.IO_ERROR = 5; +ContactError.NOT_SUPPORTED_ERROR = 6; +ContactError.PERMISSION_DENIED_ERROR = 20; PhoneGap.addConstructor(function() { if(typeof navigator.service == "undefined") navigator.service = new Object(); diff --git a/framework/src/com/phonegap/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java index ac03c414..e276118c 100644 --- a/framework/src/com/phonegap/ContactAccessor.java +++ b/framework/src/com/phonegap/ContactAccessor.java @@ -19,11 +19,14 @@ package com.phonegap; import java.lang.reflect.Constructor; +import java.util.HashMap; import android.app.Activity; +import android.util.Log; import android.webkit.WebView; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; /** @@ -82,9 +85,78 @@ public abstract class ContactAccessor { return sInstance; } + + protected boolean isRequired(String key, HashMap map) { + Boolean retVal = map.get(key); + return (retVal == null) ? false : retVal.booleanValue(); + } + + protected HashMap buildPopulationSet(JSONArray filter) { + HashMap map = new HashMap(); + + String key; + try { + for (int i=0; i contactIds = buildSetOfContactIds(filter, searchTerm); - + HashMap populate = buildPopulationSet(filter); + Iterator it = contactIds.iterator(); JSONArray contacts = new JSONArray(); @@ -124,20 +125,27 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { 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))); + if (isRequired("displayName",populate)) { + contact.put("displayName", cur.getString(cur.getColumnIndex(People.DISPLAY_NAME))); + } + if (isRequired("phoneNumbers",populate)) { + contact.put("phoneNumbers", phoneQuery(cr, contactId)); + } + if (isRequired("emails",populate)) { + contact.put("emails", emailQuery(cr, contactId)); + } + if (isRequired("addresses",populate)) { + contact.put("addresses", addressQuery(cr, contactId)); + } + if (isRequired("organizations",populate)) { + contact.put("organizations", organizationQuery(cr, contactId)); + } + if (isRequired("ims",populate)) { + contact.put("ims", imQuery(cr, contactId)); + } + if (isRequired("note",populate)) { + contact.put("note", cur.getString(cur.getColumnIndex(People.NOTES))); + } // nickname // urls // relationship @@ -151,7 +159,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } contacts.put(contact); } - mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');"); + return contacts; } private Set buildSetOfContactIds(JSONArray filter, String searchTerm) { @@ -359,4 +367,19 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } return emails; } + + @Override + public void save(JSONObject contact) { + // TODO Auto-generated method stub + + } + + @Override + public boolean remove(String id) { + int result = mApp.getContentResolver().delete(People.CONTENT_URI, + "people._id = ?", + new String[] {id}); + + return (result > 0) ? true : false; + } } \ No newline at end of file diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index bcad148f..b4ab52a6 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -107,14 +107,13 @@ public class ContactAccessorSdk5 extends ContactAccessor { //dbMap.put("connected", null); } - public ContactAccessorSdk5(WebView view, Activity app) - { + public ContactAccessorSdk5(WebView view, Activity app) { mApp = app; mView = view; } @Override - public void search(JSONArray filter, JSONObject options) { + public JSONArray search(JSONArray filter, JSONObject options) { String searchTerm = ""; int limit = Integer.MAX_VALUE; boolean multiple = true; @@ -133,49 +132,90 @@ public class ContactAccessorSdk5 extends ContactAccessor { } 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); - + HashMap populate = buildPopulationSet(filter); + Iterator it = contactIds.iterator(); JSONArray contacts = new JSONArray(); JSONObject contact; String contactId; int pos = 0; + String[] events = null; 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)); + if (isRequired("displayName",populate)) { + contact.put("displayName", displayNameQuery(cr, contactId)); + } + if (isRequired("name",populate)) { + contact.put("name", nameQuery(cr, contactId)); + } + if (isRequired("phoneNumbers",populate)) { + contact.put("phoneNumbers", phoneQuery(cr, contactId)); + } + if (isRequired("emails",populate)) { + contact.put("emails", emailQuery(cr, contactId)); + } + if (isRequired("addresses",populate)) { + contact.put("addresses", addressQuery(cr, contactId)); + } + if (isRequired("organizations",populate)) { + contact.put("organizations", organizationQuery(cr, contactId)); + } + if (isRequired("ims",populate)) { + contact.put("ims",imQuery(cr, contactId)); + } + if (isRequired("note",populate)) { + contact.put("note",noteQuery(cr, contactId)); + } + if (isRequired("nickname",populate)) { + contact.put("nickname",nicknameQuery(cr, contactId)); + } + if (isRequired("urls",populate)) { + contact.put("urls",websiteQuery(cr, contactId)); + } + if (isRequired("relationships",populate)) { + contact.put("relationships",relationshipQuery(cr, contactId)); + } + if (isRequired("birthday",populate) || isRequired("anniversary",populate)) { + events = eventQuery(cr, contactId); + contact.put("birthday",events[0]); + contact.put("anniversary",events[1]); + } } catch (JSONException e) { Log.e(LOG_TAG, e.getMessage(), e); } + Log.d(LOG_TAG, "putting in contact ID = " + contactId); contacts.put(contact); pos++; - } - mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');"); + } + return contacts; } - + private Set buildSetOfContactIds(JSONArray filter, String searchTerm) { Set contactIds = new HashSet(); + /* + * Special case for when the user wants all the contacts + */ + if ("%".equals(searchTerm)) { + doQuery(searchTerm, contactIds, + ContactsContract.Contacts.CONTENT_URI, + ContactsContract.Contacts._ID, + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", + new String[] {searchTerm}); + return contactIds; + } + String key; try { for (int i=0; i 0) ? true : false; } } \ No newline at end of file diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index 9cf6a891..3d3bb7e4 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -2,6 +2,7 @@ package com.phonegap; import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import com.phonegap.api.Plugin; import com.phonegap.api.PluginResult; @@ -60,16 +61,21 @@ public class ContactManager implements Plugin { try { if (action.equals("search")) { - contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1)); - } - else if (action.equals("create")) { - // TODO Coming soon! + JSONArray res = contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1)); + return new PluginResult(status, res); } else if (action.equals("save")) { // TODO Coming soon! } else if (action.equals("remove")) { - // TODO Coming soon! + if (contactAccessor.remove(args.getString(0))) { + return new PluginResult(status, result); + } + else { + JSONObject r = new JSONObject(); + r.put("code", 2); + return new PluginResult(PluginResult.Status.ERROR, r); + } } return new PluginResult(status, result); } catch (JSONException e) { diff --git a/framework/src/com/phonegap/api/PluginResult.java b/framework/src/com/phonegap/api/PluginResult.java index 777f2605..7523bfe7 100755 --- a/framework/src/com/phonegap/api/PluginResult.java +++ b/framework/src/com/phonegap/api/PluginResult.java @@ -1,5 +1,6 @@ package com.phonegap.api; +import org.json.JSONArray; import org.json.JSONObject; public class PluginResult { @@ -16,6 +17,11 @@ public class PluginResult { this.message = "'" + message + "'"; } + public PluginResult(Status status, JSONArray message) { + this.status = status.ordinal(); + this.message = message.toString(); + } + public PluginResult(Status status, JSONObject message) { this.status = status.ordinal(); this.message = message.toString();