diff --git a/framework/src/com/phonegap/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java
index dcf6839f..d17528ac 100644
--- a/framework/src/com/phonegap/ContactAccessor.java
+++ b/framework/src/com/phonegap/ContactAccessor.java
@@ -24,7 +24,6 @@
package com.phonegap;
-import java.lang.reflect.Constructor;
import java.util.HashMap;
import android.app.Activity;
@@ -44,53 +43,9 @@ import org.json.JSONObject;
*/
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;
- }
/**
* Check to see if the data associated with the key is required to
diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java
deleted file mode 100644
index b482051f..00000000
--- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java
+++ /dev/null
@@ -1,833 +0,0 @@
-// Taken from Android tutorials
-/*
- * PhoneGap is available under *either* the terms of the modified BSD license *or* the
- * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
- *
- * Copyright (c) 2005-2010, Nitobi Software Inc.
- * Copyright (c) 2010, IBM Corporation
- */
-/*
- * Copyright (C) 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.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.Contacts;
-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 String PEOPLE_ID_EQUALS = "people._id = ?";
- /**
- * A static map that converts the JavaScript property name to Android database column name.
- */
- 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);
- }
-
- /**
- * Create an contact accessor.
- */
- public ContactAccessorSdk3_4(WebView view, Activity app)
- {
- mApp = app;
- mView = view;
- }
-
- @Override
- /**
- * This method takes the fields required and search options in order to produce an
- * array of contacts that matches the criteria provided.
- * @param fields an array of items to be used as search criteria
- * @param options that can be applied to contact searching
- * @return an array of contacts
- */
- public JSONArray search(JSONArray fields, JSONObject options) {
- String searchTerm = "";
- int limit = Integer.MAX_VALUE;
- boolean multiple = true;
-
- if (options != null) {
- searchTerm = options.optString("filter");
- if (searchTerm.length()==0) {
- searchTerm = "%";
- }
- else {
- searchTerm = "%" + searchTerm + "%";
- }
- try {
- multiple = options.getBoolean("multiple");
- if (!multiple) {
- limit = 1;
- }
- } catch (JSONException e) {
- // Multiple was not specified so we assume the default is true.
- }
- }
- else {
- searchTerm = "%";
- }
-
- ContentResolver cr = mApp.getContentResolver();
-
- Set contactIds = buildSetOfContactIds(fields, searchTerm);
- HashMap populate = buildPopulationSet(fields);
-
- 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
- Cursor cur = cr.query(People.CONTENT_URI,
- new String[] {People.DISPLAY_NAME, People.NOTES},
- PEOPLE_ID_EQUALS,
- new String[] {contactId},
- null);
- cur.moveToFirst();
-
- 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
- // birthdays
- // anniversary
-
- pos++;
- cur.close();
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- contacts.put(contact);
- }
- return contacts;
- }
-
- /**
- * Query the database using the search term to build up a list of contact ID's
- * matching the search term
- * @param fields
- * @param searchTerm
- * @return a set of contact ID's
- */
- private Set buildSetOfContactIds(JSONArray fields, 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();
- }
-
- /**
- * Create a ContactField JSONArray
- * @param cr database access object
- * @param contactId the ID to search the database for
- * @return a JSONArray representing a set of ContactFields
- */
- 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("id", cursor.getString(
- cursor.getColumnIndex(ContactMethods._ID)));
- im.put("perf", false);
- im.put("value", cursor.getString(
- cursor.getColumnIndex(ContactMethodsColumns.DATA)));
- im.put("type", getContactType(cursor.getInt(
- cursor.getColumnIndex(ContactMethodsColumns.TYPE))));
- ims.put(im);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- }
- cursor.close();
- return null;
- }
-
- /**
- * Create a ContactOrganization JSONArray
- * @param cr database access object
- * @param contactId the ID to search the database for
- * @return a JSONArray representing a set of ContactOrganization
- */
- 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("id", cursor.getString(cursor.getColumnIndex(Organizations._ID)));
- 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)));
- organizations.put(organization);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- }
- return organizations;
- }
-
- /**
- * Create a ContactAddress JSONArray
- * @param cr database access object
- * @param contactId the ID to search the database for
- * @return a JSONArray representing a set of ContactAddress
- */
- 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("id", cursor.getString(cursor.getColumnIndex(ContactMethods._ID)));
- address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactMethodsColumns.DATA)));
- addresses.put(address);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- }
- return addresses;
- }
-
- /**
- * Create a ContactField JSONArray
- * @param cr database access object
- * @param contactId the ID to search the database for
- * @return a JSONArray representing a set of ContactFields
- */
- 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("id", cursor.getString(cursor.getColumnIndex(Phones._ID)));
- phone.put("perf", false);
- phone.put("value", cursor.getString(cursor.getColumnIndex(Phones.NUMBER)));
- phone.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(Phones.TYPE))));
- phones.put(phone);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- }
- return phones;
- }
-
- /**
- * Create a ContactField JSONArray
- * @param cr database access object
- * @param contactId the ID to search the database for
- * @return a JSONArray representing a set of ContactFields
- */
- 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("id", cursor.getString(cursor.getColumnIndex(ContactMethods._ID)));
- email.put("perf", 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;
- }
-
- /**
- * This method will save a contact object into the devices contacts database.
- *
- * @param contact the contact to be saved.
- * @returns true if the contact is successfully saved, false otherwise.
- */
- @Override
- public String save(JSONObject contact) {
- ContentValues personValues = new ContentValues();
-
- String id = getJsonString(contact, "id");
-
- String name = getJsonString(contact, "displayName");
- if (name != null) {
- personValues.put(Contacts.People.NAME, name);
- }
- String note = getJsonString(contact, "note");
- if (note != null) {
- personValues.put(Contacts.People.NOTES, note);
- }
-
- /* STARRED 0 = Contacts, 1 = Favorites */
- personValues.put(Contacts.People.STARRED, 0);
-
- Uri newPersonUri;
- // Add new contact
- if (id == null) {
- newPersonUri = Contacts.People.createPersonInMyContactsGroup(mApp.getContentResolver(), personValues);
- }
- // modify existing contact
- else {
- newPersonUri = Uri.withAppendedPath(Contacts.People.CONTENT_URI, id);
- mApp.getContentResolver().update(newPersonUri, personValues, PEOPLE_ID_EQUALS, new String[]{id});
- }
-
- if (newPersonUri != null) {
- // phoneNumbers
- savePhoneNumbers(contact, newPersonUri);
- // emails
- saveEntries(contact, newPersonUri, "emails", Contacts.KIND_EMAIL);
- // addresses
- saveAddresses(contact, newPersonUri);
- // organizations
- saveOrganizations(contact, newPersonUri);
- // ims
- saveEntries(contact, newPersonUri, "ims", Contacts.KIND_IM);
-
- // Successfully create a Contact
- return id;
- }
- return null;
- }
-
- /**
- * Takes a JSON contact object and loops through the available organizations. If the
- * organization has an id that is not equal to null the organization will be updated in the database.
- * If the id is null then we treat it as a new organization.
- *
- * @param contact the contact to extract the organizations from
- * @param uri the base URI for this contact.
- */
- private void saveOrganizations(JSONObject contact, Uri newPersonUri) {
- ContentValues values = new ContentValues();
- Uri orgUri = Uri.withAppendedPath(newPersonUri,
- Contacts.Organizations.CONTENT_DIRECTORY);
- String id = null;
- try {
- JSONArray orgs = contact.getJSONArray("organizations");
- if (orgs != null && orgs.length() > 0) {
- JSONObject org;
- for (int i=0; i 0) {
- JSONObject entry;
- values.put(Contacts.ContactMethods.KIND, Contacts.KIND_POSTAL);
- for (int i=0; i 0 ) {
- buffer.append(", ");
- }
- buffer.append(getJsonString(entry, "region"));
- }
- if (getJsonString(entry, "postalCode") != null ) {
- if (buffer.length() > 0 ) {
- buffer.append(", ");
- }
- buffer.append(getJsonString(entry, "postalCode"));
- }
- if (getJsonString(entry, "country") != null ) {
- if (buffer.length() > 0 ) {
- buffer.append(", ");
- }
- buffer.append(getJsonString(entry, "country"));
- }
- return buffer.toString();
- }
-
- /**
- * Takes a JSON contact object and loops through the available entries (Emails/IM's). If the
- * entry has an id that is not equal to null the entry will be updated in the database.
- * If the id is null then we treat it as a new entry.
- *
- * @param contact the contact to extract the entries from
- * @param uri the base URI for this contact.
- */
- private void saveEntries(JSONObject contact, Uri uri, String dataType, int contactKind) {
- ContentValues values = new ContentValues();
- Uri newUri = Uri.withAppendedPath(uri,
- Contacts.People.ContactMethods.CONTENT_DIRECTORY);
- String id = null;
-
- try {
- JSONArray entries = contact.getJSONArray(dataType);
- if (entries != null && entries.length() > 0) {
- JSONObject entry;
- values.put(Contacts.ContactMethods.KIND, contactKind);
- for (int i=0; i 0) {
- JSONObject phone;
- for (int i=0; i 0) ? true : false;
- }
-
- @Override
- public JSONObject getContactById(String id) throws JSONException {
- // TODO Auto-generated method stub
- return null;
- }
-}
\ No newline at end of file
diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java
index 60edd545..6e41f0f2 100755
--- a/framework/src/com/phonegap/ContactManager.java
+++ b/framework/src/com/phonegap/ContactManager.java
@@ -16,9 +16,18 @@ import android.util.Log;
public class ContactManager extends Plugin {
- private static ContactAccessor contactAccessor;
+ private ContactAccessor contactAccessor;
private static final String LOG_TAG = "Contact Query";
+ public static final int UNKNOWN_ERROR = 0;
+ public static final int INVALID_ARGUMENT_ERROR = 1;
+ public static final int TIMEOUT_ERROR = 2;
+ public static final int PENDING_OPERATION_ERROR = 3;
+ public static final int IO_ERROR = 4;
+ public static final int NOT_SUPPORTED_ERROR = 5;
+ public static final int PERMISSION_DENIED_ERROR = 20;
+
+
/**
* Constructor.
*/
@@ -34,12 +43,34 @@ public class ContactManager extends Plugin {
* @return A PluginResult object with a status and message.
*/
public PluginResult execute(String action, JSONArray args, String callbackId) {
- if (contactAccessor == null) {
- contactAccessor = ContactAccessor.getInstance(webView, ctx);
- }
- PluginResult.Status status = PluginResult.Status.OK;
- String result = "";
-
+ PluginResult.Status status = PluginResult.Status.OK;
+ String result = "";
+
+ /**
+ * Check to see if we are on an Android 1.X device. If we are return an error as we
+ * do not support this as of PhoneGap 1.0.
+ */
+ if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
+ JSONObject res = null;
+ try {
+ res = new JSONObject();
+ res.put("code", NOT_SUPPORTED_ERROR);
+ res.put("message", "Contacts are not supported in Android 1.X devices");
+ } catch (JSONException e) {
+ // This should never happen
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ return new PluginResult(PluginResult.Status.ERROR, res);
+ }
+
+ /**
+ * Only create the contactAccessor after we check the Android version or the program will crash
+ * older phones.
+ */
+ if (this.contactAccessor == null) {
+ this.contactAccessor = new ContactAccessorSdk5(this.webView, this.ctx);
+ }
+
try {
if (action.equals("search")) {
JSONArray res = contactAccessor.search(args.getJSONArray(0), args.optJSONObject(1));
@@ -61,7 +92,7 @@ public class ContactManager extends Plugin {
}
// If we get to this point an error has occurred
JSONObject r = new JSONObject();
- r.put("code", 0);
+ r.put("code", UNKNOWN_ERROR);
return new PluginResult(PluginResult.Status.ERROR, r);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);