From 633100a3ce660049f732d697261091a618666cbc Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 10 Sep 2010 15:09:40 -0400 Subject: [PATCH 01/21] Merging Fil's contact changes with Bryce's Plugins --- example/index.html | 6 +- .../src/com/phonegap/ContactAccessor.java | 98 ++++ .../com/phonegap/ContactAccessorSdk3_4.java | 287 ++++++++++ .../src/com/phonegap/ContactAccessorSdk5.java | 108 ++++ .../src/com/phonegap/ContactManager.java | 542 +++++++++--------- 5 files changed, 772 insertions(+), 269 deletions(-) create mode 100644 framework/src/com/phonegap/ContactAccessor.java create mode 100644 framework/src/com/phonegap/ContactAccessorSdk3_4.java create mode 100644 framework/src/com/phonegap/ContactAccessorSdk5.java diff --git a/example/index.html b/example/index.html index e12e895b..dca39dd4 100644 --- a/example/index.html +++ b/example/index.html @@ -101,7 +101,11 @@ function get_contacts() { - navigator.ContactManager.getAllContacts(count_contacts, fail, null); + var obj = new Contact(); + var name = new ContactName(); + name.givenName = ''; + obj.name = name; + navigator.contacts.find(obj, count_contacts, fail); } function count_contacts(contacts) diff --git a/framework/src/com/phonegap/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java new file mode 100644 index 00000000..8f12f635 --- /dev/null +++ b/framework/src/com/phonegap/ContactAccessor.java @@ -0,0 +1,98 @@ +// 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.content.ContentResolver; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.webkit.WebView; + +/** + * 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 { + + public class ContactTriplet + { + public String name = ""; + public String email = ""; + public String phone = ""; + } + + /** + * 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 clazz = + Class.forName(className).asSubclass(ContactAccessor.class); + // Grab constructor for contactsmanager class dynamically. + Constructor 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(String name, String npa, String email); +} \ 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..a806edf3 --- /dev/null +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -0,0 +1,287 @@ +// 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 android.app.Activity; +import android.content.AsyncQueryHandler; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.net.Uri; +import android.provider.Contacts.ContactMethods; +import android.provider.Contacts.People; +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: + *

+ */ +@SuppressWarnings("deprecation") +public class ContactAccessorSdk3_4 extends ContactAccessor { + + private Uri mPeople = android.provider.Contacts.People.CONTENT_URI; + private Uri mPhone = android.provider.Contacts.Phones.CONTENT_URI; + private Uri mEmail = android.provider.Contacts.ContactMethods.CONTENT_URI; + + public ContactAccessorSdk3_4(WebView view, Activity app) + { + mApp = app; + mView = view; + } + + @Override + 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 = mApp.managedQuery(mEmail, projection, + "contact_methods." + ContactMethods.DATA + " = ?" + "AND contact_methods.kind = 1", variables , ContactMethods.DATA + " ASC"); + getMethodData(myCursor); + + } + catch (SQLiteException ex) + { + Log.d(this.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 = mApp.managedQuery(mPeople, projection, + conditions, variables , People.NAME + " ASC"); + processResults(myCursor, false); + } + catch (SQLiteException ex) + { + Log.d(this.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) + mView.loadUrl("javascript:navigator.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"')"); + else + mView.loadUrl("javascript:navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"')"); + + } while (cur.moveToNext()); + if (all) + mView.loadUrl("javascript:navigator.ContactManager.droidDone()"); + else + mView.loadUrl("javascript:navigator.contacts.droidDone();"); + } + else + { + if(all) + mView.loadUrl("javascript:navigator.ContactManager.fail()"); + else + mView.loadUrl("javascript: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; + mView.loadUrl("javascript:navigator.Contacts.droidFoundContact('" + data.name + "','" + data.phone + "','" + data.email +"')"); + } + } while (cur.moveToNext()); + mView.loadUrl("javascript: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 = mApp.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 = mApp.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; + } +} \ 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..a7d27d1e --- /dev/null +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -0,0 +1,108 @@ +// 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 android.app.Activity; +import android.content.ContentResolver; +import android.content.Intent; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.net.Uri; +import android.provider.ContactsContract; +import android.provider.Contacts.People; +import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.CommonDataKinds.Phone; +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: + *

+ */ +public class ContactAccessorSdk5 extends ContactAccessor { + + public ContactAccessorSdk5(WebView view, Activity app) + { + mApp = app; + mView = view; + } + + @Override + public void search(String name, String npa, String email) { + if (name.length()==0) name = "%"; + // Get a cursor by creating the query. + // TODO: parse name/number/email and dispatch to different query types. + // Right now assumption is only name search. Lame but I'm on time constraints. + ContentResolver cr = mApp.getContentResolver(); + Cursor cursor = cr.query( + ContactsContract.Contacts.CONTENT_URI, + new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts.DISPLAY_NAME}, + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", + new String[] {name}, + ContactsContract.Contacts.DISPLAY_NAME + " ASC"); + while (cursor.moveToNext()) { + String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); + if (contactName.trim().length() == 0) continue; + String phoneNumber = "null"; + String emailAddress = "null"; + + String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); + String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); + if (Boolean.parseBoolean(hasPhone)) { + Cursor phones = cr.query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, + null, + ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, + null, null); + if (phones.moveToFirst()) { + phoneNumber = "'" + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace('\'', '`') + "'"; + } + phones.close(); + } + Cursor emails = cr.query( + ContactsContract.CommonDataKinds.Email.CONTENT_URI, + null, + ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, + null, null); + if (emails.moveToFirst()) { + // This would allow you get several email addresses + emailAddress = "'" + emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)).replace('\'', '`') + "'"; + } + emails.close(); + String contactAddJS = "javascript:navigator.contacts.droidFoundContact('" + contactName.replace('\'', '`') + "'," + phoneNumber + "," + emailAddress +")"; + mView.loadUrl(contactAddJS); + } + cursor.close(); + mView.loadUrl("javascript:navigator.contacts.droidDone();"); + } + +} \ No newline at end of file diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index 82cc5644..d498fb82 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -18,13 +18,14 @@ import android.database.sqlite.SQLiteException; @SuppressWarnings("deprecation") public class ContactManager implements Plugin { - public class ContactTriplet - { - public String name = ""; - public String email = ""; - public String phone = ""; - } +// public class ContactTriplet +// { +// public String name = ""; +// public String email = ""; +// public String phone = ""; +// } + private static ContactAccessor contactAccessor; WebView webView; // WebView object DroidGap ctx; // DroidGap object @@ -67,15 +68,20 @@ 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(); - } - else if (action.equals("search")) { - this.search(args.getString(0), args.getString(1), args.getString(2)); + //if (action.equals("getContactsAndSendBack")) { + // contactAccessor.getContactsAndSendBack(); + //} + //else if (action.equals("search")) { + if (action.equals("search")) { + Log.d(LOG_TAG, "Executing search using accessor"); + contactAccessor.search(args.getString(0), args.getString(1), args.getString(2)); } return new PluginResult(status, result); } catch (JSONException e) { @@ -129,263 +135,263 @@ public class ContactManager implements Plugin { //-------------------------------------------------------------------------- // 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.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"');"); - } - else { - this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"');"); - } - } while (cur.moveToNext()); - if (all) { - this.ctx.sendJavascript("navigator.ContactManager.droidDone();"); - } - else { - this.ctx.sendJavascript("navigator.contacts.droidDone();"); - } - } - else - { - if (all) { - this.ctx.sendJavascript("navigator.ContactManager.fail();"); - } - 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; - } +// 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.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"');"); +// } +// else { +// this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"');"); +// } +// } while (cur.moveToNext()); +// if (all) { +// this.ctx.sendJavascript("navigator.ContactManager.droidDone();"); +// } +// else { +// this.ctx.sendJavascript("navigator.contacts.droidDone();"); +// } +// } +// else +// { +// if (all) { +// this.ctx.sendJavascript("navigator.ContactManager.fail();"); +// } +// 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; +// } } From 0efe871efed381e3b5456edfc7fd75f4c73346a0 Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 10 Sep 2010 16:06:22 -0400 Subject: [PATCH 02/21] Adding new data model to contact.js to conform to W3C spec --- framework/assets/js/contact.js | 132 +++++- framework/assets/www/phonegap.js | 762 +++++++++++++++++++++---------- 2 files changed, 622 insertions(+), 272 deletions(-) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 7debac8d..721d228e 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -1,32 +1,76 @@ -var Contact = function() { - this.name = new ContactName(); - this.emails = []; - this.phones = []; +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, published, updated, birthday, anniversary, gender, note, + preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) { + this.id = id || ''; + this.displayName = displayName || ''; + this.name = name || null; // ContactName + this.nickname = nickname || ''; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.published = published || ''; + this.updated = updated || ''; + this.birthday = birthday || ''; + this.anniversary = anniversary || ''; + this.gender = gender || ''; + this.note = note || ''; + this.preferredUsername = preferredUsername || ''; + this.photos = photos || null; // ContactField[] + this.tags = tags || null; // ContactField[] + this.relationships = relationships || null; // ContactField[] + this.urls = urls || null; // ContactField[] + this.accounts = accounts || null; // ContactAccount[] + this.utcOffset = utcOffset || ''; + this.connected = connected || ''; }; -var ContactName = function() { - this.formatted = ""; - this.familyName = ""; - this.givenName = ""; - this.additionalNames = []; - this.prefixes = []; - this.suffixes = []; +var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { + this.formatted = formatted || ''; + this.familyName = familyName || ''; + this.givenName = givenName || ''; + this.middleName = middle || ''; + this.honorificPrefix = prefix || ''; + this.honorificSuffix = suffix || ''; }; -var ContactEmail = function() { - this.types = []; - this.address = ""; +var ContactField = function(type, value, primary) { + this.type = type || ''; + this.value = value || ''; + this.primary = primary || ''; }; -var ContactPhoneNumber = function() { - this.types = []; - this.number = ""; +var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) { + this.formatted = formatted || ''; + this.streetAddress = streetAddress || ''; + this.locality = locality || ''; + this.region = region || ''; + this.postalCode = postalCode || ''; + this.country = country || ''; }; +var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) { + this.name = name || ''; + this.department = dept || ''; + this.title = title || ''; + this.startDate = startDate || ''; + this.endDate = endDate || ''; + this.location = location || ''; + this.description = desc || ''; +}; + +var ContactAccount = function(domain, username, userid) { + this.domain = domain || ''; + this.username = username || ''; + this.userid = userid || ''; +} + var Contacts = function() { + this.inProgress = false; this.records = []; -}; +} Contacts.prototype.find = function(obj, win, fail) { this.win = win; @@ -48,17 +92,21 @@ Contacts.prototype.find = function(obj, win, fail) { }; Contacts.prototype.droidFoundContact = function(name, npa, email) { + this.records = new Array(); var contact = new Contact(); contact.name = new ContactName(); contact.name.formatted = name; contact.name.givenName = name; - var mail = new ContactEmail(); - mail.types.push("home"); - mail.address = email; + contact.emails = new Array(); + var mail = new ContactField(); + mail.type = "home"; + mail.value = email; + mail.primary = true; contact.emails.push(mail); - phone = new ContactPhoneNumber(); - phone.types.push("home"); - phone.number = npa; + contact.phones = new Array(); + phone = new ContactField(); + phone.type = "home"; + phone.value = npa; contact.phones.push(phone); this.records.push(contact); }; @@ -67,6 +115,42 @@ Contacts.prototype.droidDone = function() { this.win(this.records); }; +Contacts.prototype.remove = function(contact) { + +}; + +Contacts.prototype.save = function(contact) { + +}; + +Contacts.prototype.create = function(contact) { + +}; + +Contacts.prototype.m_foundContacts = function(win, contacts) { + this.inProgress = false; + win(contacts); +}; + +var ContactFindOptions = function() { + this.filter = ''; + this.multiple = true; + this.limit = 0; + this.updatedSince = 0; +}; + +var ContactError = function() { +}; + +ContactError.INVALID_ARGUMENT_ERROR = 0; +ContactError.IO_ERROR = 1; +ContactError.NOT_FOUND_ERROR = 2; +ContactError.NOT_SUPPORTED_ERROR = 3; +ContactError.PENDING_OPERATION_ERROR = 4; +ContactError.PERMISSION_DENIED_ERROR = 5; +ContactError.TIMEOUT_ERROR = 6; +ContactError.UNKNOWN_ERROR = 7; + PhoneGap.addConstructor(function() { if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); }); diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index d775c39d..64d7c73e 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -1,6 +1,10 @@ if (typeof(DeviceInfo) != 'object') DeviceInfo = {}; +var com = {}; + +com.phonegap = {}; + /** * This represents the PhoneGap API itself, and provides a global namespace for accessing * information about the state of PhoneGap. @@ -185,7 +189,7 @@ if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); } PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady'); PhoneGap.onDeviceReady.subscribeOnce(function() { - PhoneGap.JSCallback(); + PhoneGap.JSCallback(); }); PhoneGap.Channel.join(function() { @@ -206,7 +210,7 @@ document.addEventListener('DOMContentLoaded', function() { PhoneGap.m_document_addEventListener = document.addEventListener; document.addEventListener = function(evt, handler, capture) { - var e = evt.toLowerCase(); + var e = evt.toLowerCase(); if (e == 'deviceready') { PhoneGap.onDeviceReady.subscribeOnce(handler); } else if (e == 'resume') { @@ -229,23 +233,68 @@ PhoneGap.callbacks = {}; * @param {String[]} [args] Zero or more arguments to pass to the method */ PhoneGap.exec = function(clazz, action, args) { - return CommandManager.exec(clazz, action, callbackId, JSON.stringify(args), false); + try { + var callbackId = 0; + var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), false); + eval("var v="+r+";"); + + // If status is OK, then return value back to caller + if (v.status == 0) { + return v.message; + } + + // If error, then display error + else { + console.log("Error: Status="+r.status+" Message="+v.message); + return null; + } + } catch (e) { + console.log("Error: "+e); + } }; PhoneGap.execAsync = function(success, fail, clazz, action, args) { - var callbackId = clazz + PhoneGap.callbackId++; - PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; - return CommandManager.exec(clazz, action, callbackId, JSON.stringify(args), true); + try { + var callbackId = clazz + PhoneGap.callbackId++; + PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; + var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), true); + if (r) { + eval("var v="+r+";"); + + // If status is OK, then return value back to caller + if (v.status == 0) { + return v.message; + } + + // If error, then display error + else { + console.log("Error: Status="+r.status+" Message="+v.message); + return null; + } + } + } catch (e) { + console.log("Error: "+e); + } }; PhoneGap.callbackSuccess = function(callbackId, args) { - PhoneGap.callbacks[callbackId].success(args); - delete PhoneGap.callbacks[callbackId]; + try { + PhoneGap.callbacks[callbackId].success(args.message); + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + delete PhoneGap.callbacks[callbackId]; }; PhoneGap.callbackError = function(callbackId, args) { - PhoneGap.callbacks[callbackId].fail(args); - delete PhoneGap.callbacks[callbackId]; + try { + PhoneGap.callbacks[callbackId].fail(args.message); + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + delete PhoneGap.callbacks[callbackId]; }; @@ -376,12 +425,45 @@ PhoneGap.close = function(context, func, params) { } }; +com.phonegap.AccelListenerProxy = function() { + this.className = "com.phonegap.AccelListener"; + this.status = -1; // not set yet +}; +com.phonegap.AccelListenerProxy.prototype.getStatus = function() { + if (this.status == -1) { // if not set, then request status + this.status = PhoneGap.exec(this.className, "getStatus", []); + } + return this.status; +}; +com.phonegap.AccelListenerProxy.prototype.onStatus = function(status) { + console.log("AccelListener.onStatus("+status+")"); + this.status = status; +}; +com.phonegap.AccelListenerProxy.prototype.getAcceleration = function() { + var r = PhoneGap.exec(this.className, "getAcceleration", []); + var a = new Acceleration(r.x,r.y,r.z); + return a; +}; +com.phonegap.AccelListenerProxy.prototype.start = function() { + return PhoneGap.exec(this.className, "start", []); +}; +com.phonegap.AccelListenerProxy.prototype.stop = function() { + return PhoneGap.exec(this.className, "stop", []); +}; +com.phonegap.AccelListenerProxy.prototype.setTimeout = function(timeout) { + return PhoneGap.exec(this.className, "setTimeout", [timeout]); +}; +com.phonegap.AccelListenerProxy.prototype.getTimeout = function() { + return PhoneGap.exec(this.className, "getTimeout", []); +}; +com.phonegap.AccelListener = new com.phonegap.AccelListenerProxy(); + function Acceleration(x, y, z) { this.x = x; this.y = y; this.z = z; this.timestamp = new Date().getTime(); -} +}; /** * This class provides access to device accelerometer data. @@ -398,7 +480,7 @@ function Accelerometer() { * List of accelerometer watch timers */ this.timers = {}; -} +}; Accelerometer.STOPPED = 0; Accelerometer.STARTING = 1; @@ -428,13 +510,12 @@ Accelerometer.prototype.getCurrentAcceleration = function(successCallback, error } // Get current acceleration status - var status = Accel.getStatus(); + var status = com.phonegap.AccelListener.getStatus(); // If running, then call successCallback if (status == Accelerometer.RUNNING) { try { - navigator.accelerometer.turnOffTimer = 0; - var accel = new Acceleration(Accel.getX(), Accel.getY(), Accel.getZ()); + var accel = com.phonegap.AccelListener.getAcceleration(); successCallback(accel); } catch (e) { console.log("Accelerometer Error in successCallback: " + e); @@ -442,40 +523,39 @@ Accelerometer.prototype.getCurrentAcceleration = function(successCallback, error } // If not running, then start it - else { - Accel.start(); + else if (status >= 0) { + com.phonegap.AccelListener.start(); // Wait until started var timer = setInterval(function() { - var status = Accel.getStatus(); - if (status != Accelerometer.STARTING) { + var status = com.phonegap.AccelListener.getStatus(); + + // If accelerometer is running + if (status == Accelerometer.RUNNING) { clearInterval(timer); - - // If accelerometer is running - if (status == Accelerometer.RUNNING) { - try { - var accel = new Acceleration(Accel.getX(), Accel.getY(), Accel.getZ()); - successCallback(accel); - } catch (e) { - console.log("Accelerometer Error in successCallback: " + e); - } + try { + var accel = com.phonegap.AccelListener.getAcceleration(); + successCallback(accel); + } catch (e) { + console.log("Accelerometer Error in successCallback: " + e); } + } - // If accelerometer error - else { - console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); - try { - if (errorCallback) { - errorCallback(status); - } - } catch (e) { - console.log("Accelerometer Error in errorCallback: " + e); + // If accelerometer error + else if (status == Accelerometer.ERROR_FAILED_TO_START) { + clearInterval(timer); + console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); + try { + if (errorCallback) { + errorCallback(status); } + } catch (e) { + console.log("Accelerometer Error in errorCallback: " + e); } } }, 10); } -} +}; /** * Asynchronously aquires the acceleration repeatedly at a given interval. @@ -503,22 +583,22 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb } // Make sure accelerometer timeout > frequency + 10 sec - var timeout = Accel.getTimeout(); + var timeout = com.phonegap.AccelListener.getTimeout(); if (timeout < (frequency + 10000)) { - Accel.setTimeout(frequency + 10000); // set to frequency + 10 sec + com.phonegap.AccelListener.setTimeout(frequency + 10000); // set to frequency + 10 sec } var id = PhoneGap.createUUID(); - Accel.start(); + com.phonegap.AccelListener.start(); // Start watch timer navigator.accelerometer.timers[id] = setInterval(function() { - var status = Accel.getStatus(); + var status = com.phonegap.AccelListener.getStatus(); // If accelerometer is running if (status == Accelerometer.RUNNING) { try { - var accel = new Acceleration(Accel.getX(), Accel.getY(), Accel.getZ()); + var accel = com.phonegap.AccelListener.getAcceleration(); successCallback(accel); } catch (e) { console.log("Accelerometer Error in successCallback: " + e); @@ -526,7 +606,7 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb } // If accelerometer had error - else if (status != Accelerometer.STARTING) { + else if (status == Accelerometer.ERROR_FAILED_TO_START) { console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); try { navigator.accelerometer.clearWatch(id); @@ -540,7 +620,7 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb }, (frequency ? frequency : 1)); return id; -} +}; /** * Clears the specified accelerometer watch. @@ -554,11 +634,22 @@ Accelerometer.prototype.clearWatch = function(id) { clearInterval(navigator.accelerometer.timers[id]); delete navigator.accelerometer.timers[id]; } -} +}; PhoneGap.addConstructor(function() { if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer(); }); +com.phonegap.CameraLauncherProxy = function() { + this.className = "com.phonegap.CameraLauncher"; +}; +com.phonegap.CameraLauncherProxy.prototype.setBase64 = function(b) { + return PhoneGap.exec(this.className, "setBase64", [b]); +}; +com.phonegap.CameraLauncherProxy.prototype.takePicture = function(quality) { + return PhoneGap.exec(this.className, "takePicture", [quality]); +}; +com.phonegap.CameraLauncher = new com.phonegap.CameraLauncherProxy(); + /** * This class provides access to the device camera. * @@ -595,10 +686,10 @@ Camera.prototype.getPicture = function(successCallback, errorCallback, options) this.errorCallback = errorCallback; this.options = options; if (options.quality) { - GapCam.takePicture(options.quality); + com.phonegap.CameraLauncher.takePicture(options.quality); } else { - GapCam.takePicture(80); + com.phonegap.CameraLauncher.takePicture(80); } }; @@ -613,7 +704,6 @@ Camera.prototype.success = function(picture) { } }; - /** * Callback function from native code that is called when there is an error * capturing an image, or the capture is cancelled. @@ -629,6 +719,29 @@ Camera.prototype.error = function(err) { PhoneGap.addConstructor(function() { if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); }); +com.phonegap.CompassListenerProxy = function() { + this.className = "com.phonegap.CompassListener"; +}; +com.phonegap.CompassListenerProxy.prototype.start = function() { + return PhoneGap.exec(this.className, "start", []); +}; +com.phonegap.CompassListenerProxy.prototype.stop = function() { + return PhoneGap.exec(this.className, "stop", []); +}; +com.phonegap.CompassListenerProxy.prototype.getStatus = function() { + return PhoneGap.exec(this.className, "getStatus", []); +}; +com.phonegap.CompassListenerProxy.prototype.getHeading = function() { + return PhoneGap.exec(this.className, "getHeading", []); +}; +com.phonegap.CompassListenerProxy.prototype.setTimeout = function(timeout) { + return PhoneGap.exec(this.className, "setTimeout", [timeout]); +}; +com.phonegap.CompassListenerProxy.prototype.getTimeout = function() { + return PhoneGap.exec(this.className, "getTimeout", []); +}; +com.phonegap.CompassListener = new com.phonegap.CompassListenerProxy(); + /** * This class provides access to device Compass data. * @constructor @@ -673,12 +786,12 @@ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, o } // Get current compass status - var status = CompassHook.getStatus(); + var status = com.phonegap.CompassListener.getStatus(); // If running, then call successCallback if (status == Compass.RUNNING) { try { - var heading = CompassHook.getHeading(); + var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); @@ -687,18 +800,18 @@ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, o // If not running, then start it else { - CompassHook.start(); + com.phonegap.CompassListener.start(); // Wait until started var timer = setInterval(function() { - var status = CompassHook.getStatus(); + var status = com.phonegap.CompassListener.getStatus(); if (status != Compass.STARTING) { clearInterval(timer); // If compass is running if (status == Compass.RUNNING) { try { - var heading = CompassHook.getHeading(); + var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); @@ -719,7 +832,7 @@ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, o } }, 10); } -} +}; /** * Asynchronously aquires the heading repeatedly at a given interval. @@ -747,22 +860,22 @@ Compass.prototype.watchHeading= function(successCallback, errorCallback, options } // Make sure compass timeout > frequency + 10 sec - var timeout = CompassHook.getTimeout(); + var timeout = com.phonegap.CompassListener.getTimeout(); if (timeout < (frequency + 10000)) { - CompassHook.setTimeout(frequency + 10000); // set to frequency + 10 sec + com.phonegap.CompassListener.setTimeout(frequency + 10000); // set to frequency + 10 sec } var id = PhoneGap.createUUID(); - CompassHook.start(); + com.phonegap.CompassListener.start(); // Start watch timer navigator.compass.timers[id] = setInterval(function() { - var status = CompassHook.getStatus(); + var status = com.phonegap.CompassListener.getStatus(); // If compass is running if (status == Compass.RUNNING) { try { - var heading = CompassHook.getHeading(); + var heading = com.phonegap.CompassListener.getHeading(); successCallback(heading); } catch (e) { console.log("Compass Error in successCallback: " + e); @@ -784,7 +897,7 @@ Compass.prototype.watchHeading= function(successCallback, errorCallback, options }, (frequency ? frequency : 1)); return id; -} +}; /** @@ -799,123 +912,211 @@ Compass.prototype.clearWatch = function(id) { clearInterval(navigator.compass.timers[id]); delete navigator.compass.timers[id]; } -} +}; PhoneGap.addConstructor(function() { if (typeof navigator.compass == "undefined") navigator.compass = new Compass(); }); -var Contact = function(){ - this.name = new ContactName(); - this.emails = []; - this.phones = []; +com.phonegap.ContactManagerProxy = function() { + this.className = "com.phonegap.ContactManager"; +}; +com.phonegap.ContactManagerProxy.prototype.getContactsAndSendBack = function() { + return PhoneGap.exec(this.className, "getContactsAndSendBack", []); +}; +com.phonegap.ContactManagerProxy.prototype.search = function(name, npa, mail) { + return PhoneGap.exec(this.className, "search", [name, npa, mail]); +}; +com.phonegap.ContactManager = new com.phonegap.ContactManagerProxy(); + +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, published, updated, birthday, anniversary, gender, note, + preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) { + this.id = id || ''; + this.displayName = displayName || ''; + this.name = name || null; // ContactName + this.nickname = nickname || ''; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.published = published || ''; + this.updated = updated || ''; + this.birthday = birthday || ''; + this.anniversary = anniversary || ''; + this.gender = gender || ''; + this.note = note || ''; + this.preferredUsername = preferredUsername || ''; + this.photos = photos || null; // ContactField[] + this.tags = tags || null; // ContactField[] + this.relationships = relationships || null; // ContactField[] + this.urls = urls || null; // ContactField[] + this.accounts = accounts || null; // ContactAccount[] + this.utcOffset = utcOffset || ''; + this.connected = connected || ''; +}; + +var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { + this.formatted = formatted || ''; + this.familyName = familyName || ''; + this.givenName = givenName || ''; + this.middleName = middle || ''; + this.honorificPrefix = prefix || ''; + this.honorificSuffix = suffix || ''; +}; + +var ContactField = function(type, value, primary) { + this.type = type || ''; + this.value = value || ''; + this.primary = primary || ''; +}; + +var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) { + this.formatted = formatted || ''; + this.streetAddress = streetAddress || ''; + this.locality = locality || ''; + this.region = region || ''; + this.postalCode = postalCode || ''; + this.country = country || ''; +}; + +var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) { + this.name = name || ''; + this.department = dept || ''; + this.title = title || ''; + this.startDate = startDate || ''; + this.endDate = endDate || ''; + this.location = location || ''; + this.description = desc || ''; +}; + +var ContactAccount = function(domain, username, userid) { + this.domain = domain || ''; + this.username = username || ''; + this.userid = userid || ''; } -var ContactName = function() -{ - this.formatted = ""; - this.familyName = ""; - this.givenName = ""; - this.additionalNames = []; - this.prefixes = []; - this.suffixes = []; +var Contacts = function() { + this.inProgress = false; + this.records = []; } +Contacts.prototype.find = function(obj, win, fail) { + if(obj.name != null) { + // Build up the search term that we'll use in SQL, based on the structure/contents of the contact object passed into find. + var searchTerm = ''; + if (obj.name.givenName && obj.name.givenName.length > 0) { + searchTerm = obj.name.givenName.split(' ').join('%'); + } + if (obj.name.familyName && obj.name.familyName.length > 0) { + searchTerm += obj.name.familyName.split(' ').join('%'); + } + if (!obj.name.familyName && !obj.name.givenName && obj.name.formatted) { + searchTerm = obj.name.formatted; + } + com.phonegap.ContactManager.search(searchTerm, "", ""); + } + this.win = win; + this.fail = fail; +}; -var ContactEmail = function() -{ - this.types = []; - this.address = ""; -} +Contacts.prototype.droidFoundContact = function(name, npa, email) { + this.records = new Array(); + var contact = new Contact(); + contact.name = new ContactName(); + contact.name.formatted = name; + contact.name.givenName = name; + contact.emails = new Array(); + var mail = new ContactField(); + mail.type = "home"; + mail.value = email; + mail.primary = true; + contact.emails.push(mail); + contact.phones = new Array(); + phone = new ContactField(); + phone.type = "home"; + phone.value = npa; + contact.phones.push(phone); + this.records.push(contact); +}; -var ContactPhoneNumber = function() -{ - this.types = []; - this.number = ""; -} +Contacts.prototype.droidDone = function() { + this.win(this.records); +}; +Contacts.prototype.remove = function(contact) { + +}; -var Contacts = function() -{ - this.records = []; -} +Contacts.prototype.save = function(contact) { + +}; -Contacts.prototype.find = function(obj, win, fail) -{ - if(obj.name != null) - { - // Build up the search term that we'll use in SQL, based on the structure/contents of the contact object passed into find. - var searchTerm = ''; - if (obj.name.givenName && obj.name.givenName.length > 0) { - searchTerm = obj.name.givenName.split(' ').join('%'); - } - if (obj.name.familyName && obj.name.familyName.length > 0) { - searchTerm += obj.name.familyName.split(' ').join('%'); - } - if (!obj.name.familyName && !obj.name.givenName && obj.name.formatted) { - searchTerm = obj.name.formatted; - } - ContactHook.search(searchTerm, "", ""); - } - this.win = win; - this.fail = fail; -} +Contacts.prototype.create = function(contact) { + +}; -Contacts.prototype.droidFoundContact = function(name, npa, email) -{ - var contact = new Contact(); - contact.name = new ContactName(); - contact.name.formatted = name; - contact.name.givenName = name; - var mail = new ContactEmail(); - mail.types.push("home"); - mail.address = email; - contact.emails.push(mail); - phone = new ContactPhoneNumber(); - phone.types.push("home"); - phone.number = npa; - contact.phones.push(phone); - this.records.push(contact); -} +Contacts.prototype.m_foundContacts = function(win, contacts) { + this.inProgress = false; + win(contacts); +}; -Contacts.prototype.droidDone = function() -{ - this.win(this.records); -} +var ContactFindOptions = function() { + this.filter = ''; + this.multiple = true; + this.limit = 0; + this.updatedSince = 0; +}; + +var ContactError = function() { +}; + +ContactError.INVALID_ARGUMENT_ERROR = 0; +ContactError.IO_ERROR = 1; +ContactError.NOT_FOUND_ERROR = 2; +ContactError.NOT_SUPPORTED_ERROR = 3; +ContactError.PENDING_OPERATION_ERROR = 4; +ContactError.PERMISSION_DENIED_ERROR = 5; +ContactError.TIMEOUT_ERROR = 6; +ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { - if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); + if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); }); -var Crypto = function() -{ -} +com.phonegap.CryptoHandlerProxy = function() { + this.className = "com.phonegap.CryptoHandler"; +}; +com.phonegap.CryptoHandlerProxy.prototype.encrypt = function(pass, text) { + return PhoneGap.exec(this.className, "encrypt", [pass, text]); +}; +com.phonegap.CryptoHandlerProxy.prototype.decrypt = function(pass, text) { + return PhoneGap.exec(this.className, "decrypt", [pass, text]); +}; +com.phonegap.CryptoHandler = new com.phonegap.CryptoHandlerProxy(); -Crypto.prototype.encrypt = function(seed, string, callback) -{ - GapCrypto.encrypt(seed, string); - this.encryptWin = callback; -} +var Crypto = function() { +}; -Crypto.prototype.decrypt = function(seed, string, callback) -{ - GapCrypto.decrypt(seed, string); - this.decryptWin = callback; -} +Crypto.prototype.encrypt = function(seed, string, callback) { + com.phonegap.CryptoHandler.encrypt(seed, string); + this.encryptWin = callback; +}; -Crypto.prototype.gotCryptedString = function(string) -{ - this.encryptWin(string); -} +Crypto.prototype.decrypt = function(seed, string, callback) { + com.phonegap.CryptoHandler.decrypt(seed, string); + this.decryptWin = callback; +}; -Crypto.prototype.getPlainString = function(string) -{ - this.decryptWin(string); -} +Crypto.prototype.gotCryptedString = function(string) { + this.encryptWin(string); +}; + +Crypto.prototype.getPlainString = function(string) { + this.decryptWin(string); +}; PhoneGap.addConstructor(function() { - if (typeof navigator.Crypto == "undefined") - { - navigator.Crypto = new Crypto(); - } + if (typeof navigator.Crypto == "undefined") navigator.Crypto = new Crypto(); }); /** @@ -1304,11 +1505,42 @@ if (document.keyEvent == null || typeof document.keyEvent == 'undefined') { window.keyEvent = document.keyEvent = new KeyEvent(); } +com.phonegap.AudioHandlerProxy = function() { + this.className = "com.phonegap.AudioHandler"; +}; +com.phonegap.AudioHandlerProxy.prototype.startRecordingAudio = function(id, file) { + return PhoneGap.exec(this.className, "startRecordingAudio", [id, file]); +}; +com.phonegap.AudioHandlerProxy.prototype.stopRecordingAudio = function(id) { + return PhoneGap.exec(this.className, "stopRecordingAudio", [id]); +}; +com.phonegap.AudioHandlerProxy.prototype.startPlayingAudio = function(id, file) { + return PhoneGap.exec(this.className, "startPlayingAudio", [id, file]); +}; +com.phonegap.AudioHandlerProxy.prototype.pausePlayingAudio = function(id) { + return PhoneGap.exec(this.className, "pausePlayingAudio", [id]); +}; +com.phonegap.AudioHandlerProxy.prototype.stopPlayingAudio = function(id) { + return PhoneGap.exec(this.className, "stopPlayingAudio", [id]); +}; +com.phonegap.AudioHandlerProxy.prototype.getCurrentPositionAudio = function(id) { + return PhoneGap.exec(this.className, "getCurrentPositionAudio", [id]); +}; +com.phonegap.AudioHandlerProxy.prototype.getDurationAudio = function(id, file) { + return PhoneGap.exec(this.className, "getDurationAudio", [id, file]); +}; +com.phonegap.AudioHandler = new com.phonegap.AudioHandlerProxy(); + /** * List of media objects. + * PRIVATE */ PhoneGap.mediaObjects = {}; +/** + * Object that receives native callbacks. + * PRIVATE + */ PhoneGap.Media = function() {}; /** @@ -1358,13 +1590,32 @@ PhoneGap.Media.onStatus = function(id, msg, value) { * * @param src The file name or url to play * @param successCallback The callback to be called when the file is done playing or recording. - * successCallback() + * successCallback() - OPTIONAL * @param errorCallback The callback to be called if there is an error. - * errorCallback(int errorCode) + * errorCallback(int errorCode) - OPTIONAL * @param statusCallback The callback to be called when media status has changed. - * statusCallback(int statusCode) + * statusCallback(int statusCode) - OPTIONAL */ Media = function(src, successCallback, errorCallback, statusCallback) { + + // successCallback optional + if (successCallback && (typeof successCallback != "function")) { + console.log("Media Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Media Error: errorCallback is not a function"); + return; + } + + // statusCallback optional + if (statusCallback && (typeof statusCallback != "function")) { + console.log("Media Error: statusCallback is not a function"); + return; + } + this.id = PhoneGap.createUUID(); PhoneGap.mediaObjects[this.id] = this; this.src = src; @@ -1406,21 +1657,21 @@ MediaError.MEDIA_ERR_NONE_SUPPORTED = 4; * Start or resume playing audio file. */ Media.prototype.play = function() { - GapAudio.startPlayingAudio(this.id, this.src); + com.phonegap.AudioHandler.startPlayingAudio(this.id, this.src); }; /** * Stop playing audio file. */ Media.prototype.stop = function() { - GapAudio.stopPlayingAudio(this.id); + com.phonegap.AudioHandler.stopPlayingAudio(this.id); }; /** * Pause playing audio file. */ Media.prototype.pause = function() { - GapAudio.pausePlayingAudio(this.id); + com.phonegap.AudioHandler.pausePlayingAudio(this.id); }; /** @@ -1439,34 +1690,50 @@ Media.prototype.getDuration = function() { * @return */ Media.prototype.getCurrentPosition = function() { - return GapAudio.getCurrentPositionAudio(this.id); + return com.phonegap.AudioHandler.getCurrentPositionAudio(this.id); }; /** * Start recording audio file. */ Media.prototype.startRecord = function() { - GapAudio.startRecordingAudio(this.id, this.src); + com.phonegap.AudioHandler.startRecordingAudio(this.id, this.src); }; /** * Stop recording audio file. */ Media.prototype.stopRecord = function() { - GapAudio.stopRecordingAudio(this.id); + com.phonegap.AudioHandler.stopRecordingAudio(this.id); }; +com.phonegap.NetworkManagerProxy = function() { + this.className = "com.phonegap.NetworkManager"; +}; +com.phonegap.NetworkManagerProxy.prototype.isAvailable = function() { + return PhoneGap.exec(this.className, "isAvailable", []); +}; +com.phonegap.NetworkManagerProxy.prototype.isWifiActive = function() { + return PhoneGap.exec(this.className, "isWifiActive", []); +}; +com.phonegap.NetworkManagerProxy.prototype.isReachable = function(uri) { + return PhoneGap.exec(this.className, "isReachable", [uri]); +}; +com.phonegap.NetworkManager = new com.phonegap.NetworkManagerProxy(); + /** * This class contains information about any NetworkStatus. * @constructor */ function NetworkStatus() { - this.code = null; - this.message = ""; -} + this.code = null; + this.message = ""; +}; + NetworkStatus.NOT_REACHABLE = 0; NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK = 1; NetworkStatus.REACHABLE_VIA_WIFI_NETWORK = 2; + /** * This class provides access to device Network data (reachability). * @constructor @@ -1479,6 +1746,7 @@ function Network() { */ this.lastReachability = null; }; + /** * Called by the geolocation framework when the reachability status has changed. * @param {Reachibility} reachability The current reachability status. @@ -1486,27 +1754,29 @@ function Network() { Network.prototype.updateReachability = function(reachability) { this.lastReachability = reachability; }; + /** * * @param {Object} uri * @param {Function} win * @param {Object} options (isIpAddress:boolean) */ -Network.prototype.isReachable = function(uri, win, options) -{ - var status = new NetworkStatus(); - if(NetworkManager.isReachable(uri)) - { - if (NetworkManager.isWifiActive()) { - status.code = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK; - } else { - status.code = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK; - } - } else { - status.code = NetworkStatus.NOT_REACHABLE; - } +Network.prototype.isReachable = function(uri, win, options) { + var status = new NetworkStatus(); + if(com.phonegap.NetworkManager.isReachable(uri)) { + if (com.phonegap.NetworkManager.isWifiActive()) { + status.code = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK; + } + else { + status.code = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK; + } + } + else { + status.code = NetworkStatus.NOT_REACHABLE; + } win(status); }; + PhoneGap.addConstructor(function() { if (typeof navigator.network == "undefined") navigator.network = new Network(); });/** @@ -1666,92 +1936,88 @@ 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 + * I was hoping that Android 2.0 would deprecate this, but given the fact that * most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required */ -var DroidDB = function() -{ - this.txQueue = []; -} +var DroidDB = function() { + this.txQueue = []; +}; -DroidDB.prototype.addResult = function(rawdata, tx_id) -{ - eval("var data = " + rawdata); - var tx = this.txQueue[tx_id]; - tx.resultSet.push(data); -} +DroidDB.prototype.addResult = function(rawdata, tx_id) { + eval("var data = " + rawdata); + var tx = this.txQueue[tx_id]; + tx.resultSet.push(data); +}; -DroidDB.prototype.completeQuery = function(tx_id) -{ - var tx = this.txQueue[tx_id]; - var r = new result(); - r.rows.resultSet = tx.resultSet; - r.rows.length = tx.resultSet.length; - tx.win(r); -} +DroidDB.prototype.completeQuery = function(tx_id) { + var tx = this.txQueue[tx_id]; + var r = new result(); + r.rows.resultSet = tx.resultSet; + r.rows.length = tx.resultSet.length; + tx.win(r); +}; -DroidDB.prototype.fail = function(reason, tx_id) -{ - var tx = this.txQueue[tx_id]; - tx.fail(reason); -} +DroidDB.prototype.fail = function(reason, tx_id) { + var tx = this.txQueue[tx_id]; + tx.fail(reason); +}; -var DatabaseShell = function() -{ - -} +var DatabaseShell = function() { +}; -DatabaseShell.prototype.transaction = function(process) -{ - tx = new Tx(); - process(tx); -} +DatabaseShell.prototype.transaction = function(process) { + tx = new Tx(); + process(tx); +}; -var Tx = function() -{ - droiddb.txQueue.push(this); - this.id = droiddb.txQueue.length - 1; - this.resultSet = []; -} +var Tx = function() { + droiddb.txQueue.push(this); + this.id = droiddb.txQueue.length - 1; + this.resultSet = []; +}; -Tx.prototype.executeSql = function(query, params, win, fail) -{ - droidStorage.executeSql(query, params, this.id); - tx.win = win; - tx.fail = fail; -} +Tx.prototype.executeSql = function(query, params, win, fail) { + com.phonegap.Storage.executeSql(query, params, this.id); + tx.win = win; + tx.fail = fail; +}; -var result = function() -{ - this.rows = new Rows(); -} +var result = function() { + this.rows = new Rows(); +}; -var Rows = function() -{ - this.resultSet = []; - this.length = 0; -} +var Rows = function() { + this.resultSet = []; + this.length = 0; +}; -Rows.prototype.item = function(row_id) -{ - return this.resultSet[id]; -} +Rows.prototype.item = function(row_id) { + return this.resultSet[id]; +}; -var dbSetup = function(name, version, display_name, size) -{ - droidStorage.openDatabase(name, version, display_name, size) +var dbSetup = function(name, version, display_name, size) { + com.phonegap.Storage.openDatabase(name, version, display_name, size) db_object = new DatabaseShell(); return db_object; -} +}; PhoneGap.addConstructor(function() { - if (typeof window.openDatabase == "undefined") - { - navigator.openDatabase = window.openDatabase = dbSetup; - window.droiddb = new DroidDB(); - } + if (typeof window.openDatabase == "undefined") { + navigator.openDatabase = window.openDatabase = dbSetup; + window.droiddb = new DroidDB(); + } }); - From b78896e5f07fa0de91f23a4e4ffa22ad8294f5d1 Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 10 Sep 2010 16:51:36 -0400 Subject: [PATCH 03/21] Modify ContactFindOptions to pass Mobile Spec tests --- framework/assets/js/contact.js | 10 +++++----- framework/assets/www/phonegap.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 721d228e..05be9341 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -132,11 +132,11 @@ Contacts.prototype.m_foundContacts = function(win, contacts) { win(contacts); }; -var ContactFindOptions = function() { - this.filter = ''; - this.multiple = true; - this.limit = 0; - this.updatedSince = 0; +var ContactFindOptions = function(filter, multiple, limit, updatedSince) { + this.filter = filter || ''; + this.multiple = multiple || true; + this.limit = limit || 0; + this.updatedSince = updatedSince || ''; }; var ContactError = function() { diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 64d7c73e..6cb55124 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -1061,11 +1061,11 @@ Contacts.prototype.m_foundContacts = function(win, contacts) { win(contacts); }; -var ContactFindOptions = function() { - this.filter = ''; - this.multiple = true; - this.limit = 0; - this.updatedSince = 0; +var ContactFindOptions = function(filter, multiple, limit, updatedSince) { + this.filter = filter || ''; + this.multiple = multiple || true; + this.limit = limit || 0; + this.updatedSince = updatedSince || ''; }; var ContactError = function() { From 3f24c63fc537262fca0790aea2f4f53d21832871 Mon Sep 17 00:00:00 2001 From: macdonst Date: Mon, 13 Sep 2010 16:14:33 -0400 Subject: [PATCH 04/21] Changing navigator.contacts to navigator.service.contacts --- example/index.html | 2 +- framework/assets/js/contact.js | 3 ++- framework/assets/www/phonegap.js | 3 ++- .../src/com/phonegap/ContactAccessorSdk3_4.java | 16 ++++++++-------- .../src/com/phonegap/ContactAccessorSdk5.java | 4 ++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/example/index.html b/example/index.html index dca39dd4..124e8101 100644 --- a/example/index.html +++ b/example/index.html @@ -105,7 +105,7 @@ var name = new ContactName(); name.givenName = ''; obj.name = name; - navigator.contacts.find(obj, count_contacts, fail); + navigator.service.contacts.find(obj, count_contacts, fail); } function count_contacts(contacts) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 05be9341..ac27140a 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -152,5 +152,6 @@ ContactError.TIMEOUT_ERROR = 6; ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { - if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); + if(typeof navigator.service == "undefined") navigator.service = new Object(); + if(typeof navigator.service.contacts == "undefined") navigator.service.contacts = new Contacts(); }); diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 6cb55124..543c3627 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -1081,7 +1081,8 @@ ContactError.TIMEOUT_ERROR = 6; ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { - if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts(); + if(typeof navigator.service == "undefined") navigator.service = new Object(); + if(typeof navigator.service.contacts == "undefined") navigator.service.contacts = new Contacts(); }); com.phonegap.CryptoHandlerProxy = function() { this.className = "com.phonegap.CryptoHandler"; diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index a806edf3..ec4a4d40 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -159,22 +159,22 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { // Code for backwards compatibility with the OLD Contacts API if (all) - mView.loadUrl("javascript:navigator.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"')"); + mView.loadUrl("javascript:navigator.service.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"')"); else - mView.loadUrl("javascript:navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"')"); + mView.loadUrl("javascript:navigator.service.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"')"); } while (cur.moveToNext()); if (all) - mView.loadUrl("javascript:navigator.ContactManager.droidDone()"); + mView.loadUrl("javascript:navigator.service.ContactManager.droidDone()"); else - mView.loadUrl("javascript:navigator.contacts.droidDone();"); + mView.loadUrl("javascript:navigator.service.contacts.droidDone();"); } else { if(all) - mView.loadUrl("javascript:navigator.ContactManager.fail()"); + mView.loadUrl("javascript:navigator.service.ContactManager.fail()"); else - mView.loadUrl("javascript:navigator.contacts.fail('None found!')"); + mView.loadUrl("javascript:navigator.service.contacts.fail('None found!')"); } } @@ -197,10 +197,10 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { if(data != null) { data.email = email; - mView.loadUrl("javascript:navigator.Contacts.droidFoundContact('" + data.name + "','" + data.phone + "','" + data.email +"')"); + mView.loadUrl("javascript:navigator.service.Contacts.droidFoundContact('" + data.name + "','" + data.phone + "','" + data.email +"')"); } } while (cur.moveToNext()); - mView.loadUrl("javascript:navigator.contacts.droidDoneContacts();"); + mView.loadUrl("javascript:navigator.service.contacts.droidDoneContacts();"); } } diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index a7d27d1e..e9353e76 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -98,11 +98,11 @@ public class ContactAccessorSdk5 extends ContactAccessor { emailAddress = "'" + emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)).replace('\'', '`') + "'"; } emails.close(); - String contactAddJS = "javascript:navigator.contacts.droidFoundContact('" + contactName.replace('\'', '`') + "'," + phoneNumber + "," + emailAddress +")"; + String contactAddJS = "javascript:navigator.service.contacts.droidFoundContact('" + contactName.replace('\'', '`') + "'," + phoneNumber + "," + emailAddress +")"; mView.loadUrl(contactAddJS); } cursor.close(); - mView.loadUrl("javascript:navigator.contacts.droidDone();"); + mView.loadUrl("javascript:navigator.service.contacts.droidDone();"); } } \ No newline at end of file From f606012c87e21cd67653243a230ca610500141ef Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 14 Sep 2010 14:43:46 -0400 Subject: [PATCH 05/21] Merge branches 'master' and 'contactSpec' From d955502ca2527eb4b88341719b1e77d65c753d35 Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 14 Sep 2010 14:51:31 -0400 Subject: [PATCH 06/21] Fixing whitespace --- framework/assets/js/contact.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index ac27140a..001ac633 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -62,9 +62,9 @@ var ContactOrganization = function(name, dept, title, startDate, endDate, locati }; var ContactAccount = function(domain, username, userid) { - this.domain = domain || ''; - this.username = username || ''; - this.userid = userid || ''; + this.domain = domain || ''; + this.username = username || ''; + this.userid = userid || ''; } var Contacts = function() { @@ -92,18 +92,18 @@ Contacts.prototype.find = function(obj, win, fail) { }; Contacts.prototype.droidFoundContact = function(name, npa, email) { - this.records = new Array(); + this.records = new Array(); var contact = new Contact(); contact.name = new ContactName(); contact.name.formatted = name; contact.name.givenName = name; - contact.emails = new Array(); + contact.emails = new Array(); var mail = new ContactField(); mail.type = "home"; mail.value = email; - mail.primary = true; + mail.primary = true; contact.emails.push(mail); - contact.phones = new Array(); + contact.phones = new Array(); phone = new ContactField(); phone.type = "home"; phone.value = npa; @@ -152,6 +152,6 @@ ContactError.TIMEOUT_ERROR = 6; ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { - if(typeof navigator.service == "undefined") navigator.service = new Object(); + if(typeof navigator.service == "undefined") navigator.service = new Object(); if(typeof navigator.service.contacts == "undefined") navigator.service.contacts = new Contacts(); }); From 8da131cc45d2866976a18c1a357ca0f5f4862cfb Mon Sep 17 00:00:00 2001 From: macdonst Date: Thu, 16 Sep 2010 11:35:49 -0400 Subject: [PATCH 07/21] Changed search function to take filter and option parameters --- example/index.html | 9 +- framework/assets/js/contact.js | 19 +- framework/assets/www/phonegap.js | 533 +++++------------- .../src/com/phonegap/ContactAccessor.java | 9 +- .../com/phonegap/ContactAccessorSdk3_4.java | 14 +- .../src/com/phonegap/ContactAccessorSdk5.java | 17 +- .../src/com/phonegap/ContactManager.java | 284 +--------- 7 files changed, 196 insertions(+), 689 deletions(-) diff --git a/example/index.html b/example/index.html index 124e8101..745856ce 100644 --- a/example/index.html +++ b/example/index.html @@ -101,11 +101,10 @@ function get_contacts() { - var obj = new Contact(); - var name = new ContactName(); - name.givenName = ''; - obj.name = name; - navigator.service.contacts.find(obj, count_contacts, fail); + var obj = new ContactFindOptions(); + obj.filter=""; + obj.multiple=true; + navigator.service.contacts.find(["name", "phone", "email"], count_contacts, fail, obj); } function count_contacts(contacts) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 001ac633..cdc8c97f 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -72,23 +72,12 @@ var Contacts = function() { this.records = []; } -Contacts.prototype.find = function(obj, win, fail) { +// Contacts.prototype.find = function(obj, win, fail) { +Contacts.prototype.find = function(fields, win, fail, options) { this.win = win; this.fail = fail; - if(obj.name != null) { - // Build up the search term that we'll use in SQL, based on the structure/contents of the contact object passed into find. - var searchTerm = ''; - if (obj.name.givenName && obj.name.givenName.length > 0) { - searchTerm = obj.name.givenName.split(' ').join('%'); - } - if (obj.name.familyName && obj.name.familyName.length > 0) { - searchTerm += obj.name.familyName.split(' ').join('%'); - } - if (!obj.name.familyName && !obj.name.givenName && obj.name.formatted) { - searchTerm = obj.name.formatted; - } - PhoneGap.execAsync(null, null, "Contacts", "search", [searchTerm, "", ""]); - } + + PhoneGap.execAsync(null, null, "Contacts", "search", [fields, options]); }; Contacts.prototype.droidFoundContact = function(name, npa, email) { diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 543c3627..7cc3f022 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -1,10 +1,7 @@ + if (typeof(DeviceInfo) != 'object') DeviceInfo = {}; -var com = {}; - -com.phonegap = {}; - /** * This represents the PhoneGap API itself, and provides a global namespace for accessing * information about the state of PhoneGap. @@ -256,19 +253,35 @@ PhoneGap.exec = function(clazz, action, args) { PhoneGap.execAsync = function(success, fail, clazz, action, args) { try { var callbackId = clazz + PhoneGap.callbackId++; - PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; + if (success || fail) { + PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; + } var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), true); + + // If a result was returned if (r) { eval("var v="+r+";"); // If status is OK, then return value back to caller if (v.status == 0) { + + // If there is a success callback, then call it now with returned value + if (success) { + success(v.message); + delete PhoneGap.callbacks[callbackId]; + } return v.message; } // If error, then display error else { console.log("Error: Status="+r.status+" Message="+v.message); + + // If there is a fail callback, then call it now with returned value + if (fail) { + fail(v.message); + delete PhoneGap.callbacks[callbackId]; + } return null; } } @@ -278,23 +291,31 @@ PhoneGap.execAsync = function(success, fail, clazz, action, args) { }; PhoneGap.callbackSuccess = function(callbackId, args) { - try { - PhoneGap.callbacks[callbackId].success(args.message); + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].success) { + PhoneGap.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + delete PhoneGap.callbacks[callbackId]; } - catch (e) { - console.log("Error in success callback: "+callbackId+" = "+e); - } - delete PhoneGap.callbacks[callbackId]; }; PhoneGap.callbackError = function(callbackId, args) { - try { - PhoneGap.callbacks[callbackId].fail(args.message); + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].fail) { + PhoneGap.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + delete PhoneGap.callbacks[callbackId]; } - catch (e) { - console.log("Error in error callback: "+callbackId+" = "+e); - } - delete PhoneGap.callbacks[callbackId]; }; @@ -425,38 +446,6 @@ PhoneGap.close = function(context, func, params) { } }; -com.phonegap.AccelListenerProxy = function() { - this.className = "com.phonegap.AccelListener"; - this.status = -1; // not set yet -}; -com.phonegap.AccelListenerProxy.prototype.getStatus = function() { - if (this.status == -1) { // if not set, then request status - this.status = PhoneGap.exec(this.className, "getStatus", []); - } - return this.status; -}; -com.phonegap.AccelListenerProxy.prototype.onStatus = function(status) { - console.log("AccelListener.onStatus("+status+")"); - this.status = status; -}; -com.phonegap.AccelListenerProxy.prototype.getAcceleration = function() { - var r = PhoneGap.exec(this.className, "getAcceleration", []); - var a = new Acceleration(r.x,r.y,r.z); - return a; -}; -com.phonegap.AccelListenerProxy.prototype.start = function() { - return PhoneGap.exec(this.className, "start", []); -}; -com.phonegap.AccelListenerProxy.prototype.stop = function() { - return PhoneGap.exec(this.className, "stop", []); -}; -com.phonegap.AccelListenerProxy.prototype.setTimeout = function(timeout) { - return PhoneGap.exec(this.className, "setTimeout", [timeout]); -}; -com.phonegap.AccelListenerProxy.prototype.getTimeout = function() { - return PhoneGap.exec(this.className, "getTimeout", []); -}; -com.phonegap.AccelListener = new com.phonegap.AccelListenerProxy(); function Acceleration(x, y, z) { this.x = x; @@ -482,20 +471,17 @@ function Accelerometer() { this.timers = {}; }; -Accelerometer.STOPPED = 0; -Accelerometer.STARTING = 1; -Accelerometer.RUNNING = 2; -Accelerometer.ERROR_FAILED_TO_START = 3; Accelerometer.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"]; /** * Asynchronously aquires the current acceleration. * * @param {Function} successCallback The function to call when the acceleration data is available - * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. - * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. + * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL) + * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL) */ Accelerometer.prototype.getCurrentAcceleration = function(successCallback, errorCallback, options) { + console.log("Accelerometer.getCurrentAcceleration()"); // successCallback required if (typeof successCallback != "function") { @@ -509,60 +495,16 @@ Accelerometer.prototype.getCurrentAcceleration = function(successCallback, error return; } - // Get current acceleration status - var status = com.phonegap.AccelListener.getStatus(); - - // If running, then call successCallback - if (status == Accelerometer.RUNNING) { - try { - var accel = com.phonegap.AccelListener.getAcceleration(); - successCallback(accel); - } catch (e) { - console.log("Accelerometer Error in successCallback: " + e); - } - } - - // If not running, then start it - else if (status >= 0) { - com.phonegap.AccelListener.start(); - - // Wait until started - var timer = setInterval(function() { - var status = com.phonegap.AccelListener.getStatus(); - - // If accelerometer is running - if (status == Accelerometer.RUNNING) { - clearInterval(timer); - try { - var accel = com.phonegap.AccelListener.getAcceleration(); - successCallback(accel); - } catch (e) { - console.log("Accelerometer Error in successCallback: " + e); - } - } - - // If accelerometer error - else if (status == Accelerometer.ERROR_FAILED_TO_START) { - clearInterval(timer); - console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); - try { - if (errorCallback) { - errorCallback(status); - } - } catch (e) { - console.log("Accelerometer Error in errorCallback: " + e); - } - } - }, 10); - } + // Get acceleration + PhoneGap.execAsync(successCallback, errorCallback, "Accelerometer", "getAcceleration", []); }; /** * Asynchronously aquires the acceleration repeatedly at a given interval. * * @param {Function} successCallback The function to call each time the acceleration data is available - * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. - * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. + * @param {Function} errorCallback The function to call when there is an error getting the acceleration data. (OPTIONAL) + * @param {AccelerationOptions} options The options for getting the accelerometer data such as timeout. (OPTIONAL) * @return String The watch id that must be passed to #clearWatch to stop watching. */ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallback, options) { @@ -583,40 +525,18 @@ Accelerometer.prototype.watchAcceleration = function(successCallback, errorCallb } // Make sure accelerometer timeout > frequency + 10 sec - var timeout = com.phonegap.AccelListener.getTimeout(); - if (timeout < (frequency + 10000)) { - com.phonegap.AccelListener.setTimeout(frequency + 10000); // set to frequency + 10 sec - } - - var id = PhoneGap.createUUID(); - com.phonegap.AccelListener.start(); + PhoneGap.execAsync( + function(timeout) { + if (timeout < (frequency + 10000)) { + PhoneGap.execAsync(null, null, "Accelerometer", "setTimeout", [frequency + 10000]); + } + }, + function(e) { }, "Accelerometer", "getTimeout", []); // Start watch timer + var id = PhoneGap.createUUID(); navigator.accelerometer.timers[id] = setInterval(function() { - var status = com.phonegap.AccelListener.getStatus(); - - // If accelerometer is running - if (status == Accelerometer.RUNNING) { - try { - var accel = com.phonegap.AccelListener.getAcceleration(); - successCallback(accel); - } catch (e) { - console.log("Accelerometer Error in successCallback: " + e); - } - } - - // If accelerometer had error - else if (status == Accelerometer.ERROR_FAILED_TO_START) { - console.log("Accelerometer Error: "+ Accelerometer.ERROR_MSG[status]); - try { - navigator.accelerometer.clearWatch(id); - if (errorCallback) { - errorCallback(status); - } - } catch (e) { - console.log("Accelerometer Error in errorCallback: " + e); - } - } + PhoneGap.execAsync(successCallback, errorCallback, "Accelerometer", "getAcceleration", []); }, (frequency ? frequency : 1)); return id; @@ -639,16 +559,6 @@ Accelerometer.prototype.clearWatch = function(id) { PhoneGap.addConstructor(function() { if (typeof navigator.accelerometer == "undefined") navigator.accelerometer = new Accelerometer(); }); -com.phonegap.CameraLauncherProxy = function() { - this.className = "com.phonegap.CameraLauncher"; -}; -com.phonegap.CameraLauncherProxy.prototype.setBase64 = function(b) { - return PhoneGap.exec(this.className, "setBase64", [b]); -}; -com.phonegap.CameraLauncherProxy.prototype.takePicture = function(quality) { - return PhoneGap.exec(this.className, "takePicture", [quality]); -}; -com.phonegap.CameraLauncher = new com.phonegap.CameraLauncherProxy(); /** * This class provides access to the device camera. @@ -685,12 +595,15 @@ Camera.prototype.getPicture = function(successCallback, errorCallback, options) this.successCallback = successCallback; this.errorCallback = errorCallback; this.options = options; + var capturetype = "base64"; + var quality = 80; + if (this.options.capturetype) { + capturetype = this.options.capturetype; + } if (options.quality) { - com.phonegap.CameraLauncher.takePicture(options.quality); - } - else { - com.phonegap.CameraLauncher.takePicture(80); + quality = this.options.quality; } + PhoneGap.execAsync(null, null, "Camera", "takePicture", [quality, capturetype]); }; /** @@ -719,28 +632,6 @@ Camera.prototype.error = function(err) { PhoneGap.addConstructor(function() { if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); }); -com.phonegap.CompassListenerProxy = function() { - this.className = "com.phonegap.CompassListener"; -}; -com.phonegap.CompassListenerProxy.prototype.start = function() { - return PhoneGap.exec(this.className, "start", []); -}; -com.phonegap.CompassListenerProxy.prototype.stop = function() { - return PhoneGap.exec(this.className, "stop", []); -}; -com.phonegap.CompassListenerProxy.prototype.getStatus = function() { - return PhoneGap.exec(this.className, "getStatus", []); -}; -com.phonegap.CompassListenerProxy.prototype.getHeading = function() { - return PhoneGap.exec(this.className, "getHeading", []); -}; -com.phonegap.CompassListenerProxy.prototype.setTimeout = function(timeout) { - return PhoneGap.exec(this.className, "setTimeout", [timeout]); -}; -com.phonegap.CompassListenerProxy.prototype.getTimeout = function() { - return PhoneGap.exec(this.className, "getTimeout", []); -}; -com.phonegap.CompassListener = new com.phonegap.CompassListenerProxy(); /** * This class provides access to device Compass data. @@ -758,18 +649,14 @@ function Compass() { this.timers = {}; }; -Compass.STOPPED = 0; -Compass.STARTING = 1; -Compass.RUNNING = 2; -Compass.ERROR_FAILED_TO_START = 3; Compass.ERROR_MSG = ["Not running", "Starting", "", "Failed to start"]; /** * Asynchronously aquires the current heading. * * @param {Function} successCallback The function to call when the heading data is available - * @param {Function} errorCallback The function to call when there is an error getting the heading data. - * @param {PositionOptions} options The options for getting the heading data such as timeout. + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + * @param {PositionOptions} options The options for getting the heading data such as timeout. (OPTIONAL) */ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, options) { @@ -785,61 +672,16 @@ Compass.prototype.getCurrentHeading = function(successCallback, errorCallback, o return; } - // Get current compass status - var status = com.phonegap.CompassListener.getStatus(); - - // If running, then call successCallback - if (status == Compass.RUNNING) { - try { - var heading = com.phonegap.CompassListener.getHeading(); - successCallback(heading); - } catch (e) { - console.log("Compass Error in successCallback: " + e); - } - } - - // If not running, then start it - else { - com.phonegap.CompassListener.start(); - - // Wait until started - var timer = setInterval(function() { - var status = com.phonegap.CompassListener.getStatus(); - if (status != Compass.STARTING) { - clearInterval(timer); - - // If compass is running - if (status == Compass.RUNNING) { - try { - var heading = com.phonegap.CompassListener.getHeading(); - successCallback(heading); - } catch (e) { - console.log("Compass Error in successCallback: " + e); - } - } - - // If compass error - else { - console.log("Compass Error: "+ Compass.ERROR_MSG[status]); - try { - if (errorCallback) { - errorCallback(status); - } - } catch (e) { - console.log("Compass Error in errorCallback: " + e); - } - } - } - }, 10); - } + // Get heading + PhoneGap.execAsync(successCallback, errorCallback, "Compass", "getHeading", []); }; /** * Asynchronously aquires the heading repeatedly at a given interval. * * @param {Function} successCallback The function to call each time the heading data is available - * @param {Function} errorCallback The function to call when there is an error getting the heading data. - * @param {HeadingOptions} options The options for getting the heading data such as timeout and the frequency of the watch. + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + * @param {HeadingOptions} options The options for getting the heading data such as timeout and the frequency of the watch. (OPTIONAL) * @return String The watch id that must be passed to #clearWatch to stop watching. */ Compass.prototype.watchHeading= function(successCallback, errorCallback, options) { @@ -860,41 +702,20 @@ Compass.prototype.watchHeading= function(successCallback, errorCallback, options } // Make sure compass timeout > frequency + 10 sec - var timeout = com.phonegap.CompassListener.getTimeout(); - if (timeout < (frequency + 10000)) { - com.phonegap.CompassListener.setTimeout(frequency + 10000); // set to frequency + 10 sec - } + PhoneGap.execAsync( + function(timeout) { + if (timeout < (frequency + 10000)) { + PhoneGap.execAsync(null, null, "Compass", "setTimeout", [frequency + 10000]); + } + }, + function(e) { }, "Compass", "getTimeout", []); + // Start watch timer to get headings var id = PhoneGap.createUUID(); - com.phonegap.CompassListener.start(); - - // Start watch timer - navigator.compass.timers[id] = setInterval(function() { - var status = com.phonegap.CompassListener.getStatus(); - - // If compass is running - if (status == Compass.RUNNING) { - try { - var heading = com.phonegap.CompassListener.getHeading(); - successCallback(heading); - } catch (e) { - console.log("Compass Error in successCallback: " + e); - } - } - - // If compass had error - else if (status != Compass.STARTING) { - console.log("Compass Error: "+ Compass.ERROR_MSG[status]); - try { - navigator.compass.clearWatch(id); - if (errorCallback) { - errorCallback(status); - } - } catch (e) { - console.log("Compass Error in errorCallback: " + e); - } - } - }, (frequency ? frequency : 1)); + navigator.compass.timers[id] = setInterval( + function() { + PhoneGap.execAsync(successCallback, errorCallback, "Compass", "getHeading", []); + }, (frequency ? frequency : 1)); return id; }; @@ -917,16 +738,6 @@ Compass.prototype.clearWatch = function(id) { PhoneGap.addConstructor(function() { if (typeof navigator.compass == "undefined") navigator.compass = new Compass(); }); -com.phonegap.ContactManagerProxy = function() { - this.className = "com.phonegap.ContactManager"; -}; -com.phonegap.ContactManagerProxy.prototype.getContactsAndSendBack = function() { - return PhoneGap.exec(this.className, "getContactsAndSendBack", []); -}; -com.phonegap.ContactManagerProxy.prototype.search = function(name, npa, mail) { - return PhoneGap.exec(this.className, "search", [name, npa, mail]); -}; -com.phonegap.ContactManager = new com.phonegap.ContactManagerProxy(); var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, ims, organizations, published, updated, birthday, anniversary, gender, note, @@ -991,9 +802,9 @@ var ContactOrganization = function(name, dept, title, startDate, endDate, locati }; var ContactAccount = function(domain, username, userid) { - this.domain = domain || ''; - this.username = username || ''; - this.userid = userid || ''; + this.domain = domain || ''; + this.username = username || ''; + this.userid = userid || ''; } var Contacts = function() { @@ -1001,38 +812,27 @@ var Contacts = function() { this.records = []; } -Contacts.prototype.find = function(obj, win, fail) { - if(obj.name != null) { - // Build up the search term that we'll use in SQL, based on the structure/contents of the contact object passed into find. - var searchTerm = ''; - if (obj.name.givenName && obj.name.givenName.length > 0) { - searchTerm = obj.name.givenName.split(' ').join('%'); - } - if (obj.name.familyName && obj.name.familyName.length > 0) { - searchTerm += obj.name.familyName.split(' ').join('%'); - } - if (!obj.name.familyName && !obj.name.givenName && obj.name.formatted) { - searchTerm = obj.name.formatted; - } - com.phonegap.ContactManager.search(searchTerm, "", ""); - } +// 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]); }; Contacts.prototype.droidFoundContact = function(name, npa, email) { - this.records = new Array(); + this.records = new Array(); var contact = new Contact(); contact.name = new ContactName(); contact.name.formatted = name; contact.name.givenName = name; - contact.emails = new Array(); + contact.emails = new Array(); var mail = new ContactField(); mail.type = "home"; mail.value = email; - mail.primary = true; + mail.primary = true; contact.emails.push(mail); - contact.phones = new Array(); + contact.phones = new Array(); phone = new ContactField(); phone.type = "home"; phone.value = npa; @@ -1081,31 +881,21 @@ ContactError.TIMEOUT_ERROR = 6; ContactError.UNKNOWN_ERROR = 7; PhoneGap.addConstructor(function() { - if(typeof navigator.service == "undefined") navigator.service = new Object(); + if(typeof navigator.service == "undefined") navigator.service = new Object(); if(typeof navigator.service.contacts == "undefined") navigator.service.contacts = new Contacts(); }); -com.phonegap.CryptoHandlerProxy = function() { - this.className = "com.phonegap.CryptoHandler"; -}; -com.phonegap.CryptoHandlerProxy.prototype.encrypt = function(pass, text) { - return PhoneGap.exec(this.className, "encrypt", [pass, text]); -}; -com.phonegap.CryptoHandlerProxy.prototype.decrypt = function(pass, text) { - return PhoneGap.exec(this.className, "decrypt", [pass, text]); -}; -com.phonegap.CryptoHandler = new com.phonegap.CryptoHandlerProxy(); var Crypto = function() { }; Crypto.prototype.encrypt = function(seed, string, callback) { - com.phonegap.CryptoHandler.encrypt(seed, string); this.encryptWin = callback; + PhoneGap.execAsync(null, null, "Crypto", "encrypt", [seed, string]); }; Crypto.prototype.decrypt = function(seed, string, callback) { - com.phonegap.CryptoHandler.decrypt(seed, string); this.decryptWin = callback; + PhoneGap.execAsync(null, null, "Crypto", "decrypt", [seed, string]); }; Crypto.prototype.gotCryptedString = function(string) { @@ -1506,31 +1296,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. @@ -1596,8 +1361,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")) { @@ -1617,19 +1384,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; @@ -1658,21 +1433,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]); }; /** @@ -1690,37 +1465,24 @@ 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. @@ -1752,35 +1514,58 @@ 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) { + + // callback required + if (typeof callback != "function") { + console.log("Network Error: callback is not a function"); + return; } - else { - status.code = NetworkStatus.NOT_REACHABLE; - } - win(status); + + PhoneGap.execAsync( + function(status) { + + // If reachable, the check for wifi vs carrier + if (status) { + PhoneGap.execAsync( + function(wifi) { + var s = new NetworkStatus(); + if (wifi) { + s.code = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK; + } + else { + s.code = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK; + } + callback(s); + }, null, "Network Status", "isWifiActive", []); + } + + // If not + else { + var s = new NetworkStatus(); + s.code = NetworkStatus.NOT_REACHABLE; + callback(s); + } + }, null, "Network Status", "isReachable", [uri]); }; PhoneGap.addConstructor(function() { if (typeof navigator.network == "undefined") navigator.network = new Network(); -});/** +}); + +/** * This class provides access to notifications on the device. */ function Notification() { @@ -1937,17 +1722,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 @@ -1992,7 +1767,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; }; @@ -2011,7 +1786,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/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java index 8f12f635..867fe5e1 100644 --- a/framework/src/com/phonegap/ContactAccessor.java +++ b/framework/src/com/phonegap/ContactAccessor.java @@ -21,12 +21,11 @@ package com.phonegap; import java.lang.reflect.Constructor; import android.app.Activity; -import android.content.ContentResolver; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; 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 @@ -94,5 +93,5 @@ public abstract class ContactAccessor { /** * Handles searching through SDK-specific contacts API. */ - public abstract void search(String name, String npa, String email); + 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 index ec4a4d40..acdbd8af 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -17,6 +17,9 @@ package com.phonegap; +import org.json.JSONArray; +import org.json.JSONObject; + import android.app.Activity; import android.content.AsyncQueryHandler; import android.database.Cursor; @@ -54,11 +57,12 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } @Override - public void search(String name, String npa, String email) { - if (email.length() > 0) - searchByEmail(email); - else - searchPeople(name, npa); + public void search(JSONArray filter, JSONObject options) { + //if (email.length() > 0) + // searchByEmail(email); + //else + // searchPeople(name, npa); + searchPeople("", ""); } private void searchByEmail(String email) diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index e9353e76..c16bc73a 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -17,6 +17,10 @@ package com.phonegap; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; @@ -57,8 +61,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } @Override - public void search(String name, String npa, String email) { - if (name.length()==0) name = "%"; + public void search(JSONArray filter, JSONObject options) { + String searchTerm = ""; + try { + searchTerm = options.getString("filter"); + if (searchTerm.length()==0) searchTerm = "%"; + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } // Get a cursor by creating the query. // TODO: parse name/number/email and dispatch to different query types. // Right now assumption is only name search. Lame but I'm on time constraints. @@ -67,7 +78,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { ContactsContract.Contacts.CONTENT_URI, new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts.DISPLAY_NAME}, ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", - new String[] {name}, + new String[] {searchTerm}, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); while (cursor.moveToNext()) { String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index d498fb82..6a915740 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -2,29 +2,19 @@ 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; -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 @@ -81,7 +71,12 @@ public class ContactManager implements Plugin { //else if (action.equals("search")) { if (action.equals("search")) { Log.d(LOG_TAG, "Executing search using accessor"); - contactAccessor.search(args.getString(0), args.getString(1), args.getString(2)); + JSONArray fields = args.getJSONArray(0); + for (int i=0; i 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.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"');"); -// } -// else { -// this.ctx.sendJavascript("navigator.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"');"); -// } -// } while (cur.moveToNext()); -// if (all) { -// this.ctx.sendJavascript("navigator.ContactManager.droidDone();"); -// } -// else { -// this.ctx.sendJavascript("navigator.contacts.droidDone();"); -// } -// } -// else -// { -// if (all) { -// this.ctx.sendJavascript("navigator.ContactManager.fail();"); -// } -// 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; -// } - - } From 0a2d7bf53602673805ff07ff9057bb0f7001dc18 Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 17 Sep 2010 10:24:22 -0400 Subject: [PATCH 08/21] reducing code --- framework/assets/js/contact.js | 26 +-- framework/assets/www/phonegap.js | 161 +++++++++--------- .../src/com/phonegap/ContactAccessorSdk5.java | 54 ++++-- .../src/com/phonegap/ContactManager.java | 8 +- 4 files changed, 128 insertions(+), 121 deletions(-) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index cdc8c97f..fa8275af 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -69,7 +69,7 @@ var ContactAccount = function(domain, username, userid) { var Contacts = function() { this.inProgress = false; - this.records = []; + this.records = new Array(); } // Contacts.prototype.find = function(obj, win, fail) { @@ -80,28 +80,8 @@ Contacts.prototype.find = function(fields, win, fail, options) { PhoneGap.execAsync(null, null, "Contacts", "search", [fields, options]); }; -Contacts.prototype.droidFoundContact = function(name, npa, email) { - this.records = new Array(); - var contact = new Contact(); - contact.name = new ContactName(); - contact.name.formatted = name; - contact.name.givenName = name; - contact.emails = new Array(); - var mail = new ContactField(); - mail.type = "home"; - mail.value = email; - mail.primary = true; - contact.emails.push(mail); - contact.phones = new Array(); - phone = new ContactField(); - phone.type = "home"; - phone.value = npa; - contact.phones.push(phone); - this.records.push(contact); -}; - -Contacts.prototype.droidDone = function() { - this.win(this.records); +Contacts.prototype.droidDone = function(contacts) { + this.win(eval('(' + contacts + ')')); }; Contacts.prototype.remove = function(contact) { diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 7cc3f022..669ecf2f 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -219,6 +219,36 @@ document.addEventListener = function(evt, handler, capture) { } }; +/** + * If JSON not included, use our own stringify. (Android 1.6) + * The restriction on ours is that it must be an array of simple types. + * + * @param args + * @return + */ +PhoneGap.stringify = function(args) { + if (typeof JSON == "undefined") { + var s = "["; + for (var i=0; i 0) { + s = s + ","; + } + var type = typeof args[i]; + if ((type == "number") || (type == "boolean")) { + s = s + args[i]; + } + else { + s = s + '"' + args[i] + '"'; + } + } + s = s + "]"; + return s; + } + else { + return JSON.stringify(args); + } +}; + PhoneGap.callbackId = 0; PhoneGap.callbacks = {}; @@ -232,7 +262,7 @@ PhoneGap.callbacks = {}; PhoneGap.exec = function(clazz, action, args) { try { var callbackId = 0; - var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), false); + var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), false); eval("var v="+r+";"); // If status is OK, then return value back to caller @@ -256,10 +286,10 @@ PhoneGap.execAsync = function(success, fail, clazz, action, args) { if (success || fail) { PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; } - var r = PluginManager.exec(clazz, action, callbackId, JSON.stringify(args), true); + var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), true); // If a result was returned - if (r) { + if ((typeof r == "string") && (r.length > 0)) { eval("var v="+r+";"); // If status is OK, then return value back to caller @@ -809,7 +839,7 @@ var ContactAccount = function(domain, username, userid) { var Contacts = function() { this.inProgress = false; - this.records = []; + this.records = new Array(); } // Contacts.prototype.find = function(obj, win, fail) { @@ -820,28 +850,16 @@ Contacts.prototype.find = function(fields, win, fail, options) { PhoneGap.execAsync(null, null, "Contacts", "search", [fields, options]); }; -Contacts.prototype.droidFoundContact = function(name, npa, email) { - this.records = new Array(); - var contact = new Contact(); - contact.name = new ContactName(); - contact.name.formatted = name; - contact.name.givenName = name; - contact.emails = new Array(); - var mail = new ContactField(); - mail.type = "home"; - mail.value = email; - mail.primary = true; - contact.emails.push(mail); - contact.phones = new Array(); - phone = new ContactField(); - phone.type = "home"; - phone.value = npa; - contact.phones.push(phone); - this.records.push(contact); +Contacts.prototype.droidFoundContact = function(contact) { + //console.log("this is what a contact looks like"); + //console.log(contact); + + //this.records.push(eval('(' + contact + ')')); + console.log("we should be called anymore."); }; -Contacts.prototype.droidDone = function() { - this.win(this.records); +Contacts.prototype.droidDone = function(contacts) { + this.win(eval('(' + contacts + ')')); }; Contacts.prototype.remove = function(contact) { @@ -911,59 +929,60 @@ PhoneGap.addConstructor(function() { }); /** - * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the * phone, etc. * @constructor */ function Device() { this.available = PhoneGap.available; this.platform = null; - this.version = null; - this.name = null; - this.gap = null; - this.uuid = null; - try { - if (window.DroidGap) { - this.available = true; - this.uuid = window.DroidGap.getUuid(); - this.version = window.DroidGap.getOSVersion(); - this.gapVersion = window.DroidGap.getVersion(); - this.platform = window.DroidGap.getPlatform(); - this.name = window.DroidGap.getProductName(); - this.line1Number = window.DroidGap.getLine1Number(); - this.deviceId = window.DroidGap.getDeviceId(); - this.simSerialNumber = window.DroidGap.getSimSerialNumber(); - this.subscriberId = window.DroidGap.getSubscriberId(); - } - } catch(e) { - this.available = false; - } + this.version = null; + this.name = null; + this.uuid = null; + this.phonegap = null; + + var me = this; + PhoneGap.execAsync( + function(info) { + me.available = true; + me.platform = info.platform; + me.version = info.version; + me.uuid = info.uuid; + me.phonegap = info.phonegap; + }, + function(e) { + me.available = false; + console.log("Error initializing PhoneGap: " + e); + alert("Error initializing PhoneGap: "+e); + }, + "Device", "getDeviceInfo", []); } /* - * You must explicitly override the back button. + * This is only for Android. + * + * You must explicitly override the back button. */ - -Device.prototype.overrideBackButton = function() -{ - BackButton.override(); +Device.prototype.overrideBackButton = function() { + BackButton.override(); } /* + * This is only for Android. + * * This resets the back button to the default behaviour */ - -Device.prototype.resetBackButton = function() -{ - BackButton.reset(); +Device.prototype.resetBackButton = function() { + BackButton.reset(); } /* + * This is only for Android. + * * This terminates the activity! */ -Device.prototype.exitApp = function() -{ - BackButton.exitApp(); +Device.prototype.exitApp = function() { + BackButton.exitApp(); } PhoneGap.addConstructor(function() { @@ -971,6 +990,7 @@ PhoneGap.addConstructor(function() { }); + PhoneGap.addConstructor(function() { if (typeof navigator.fileMgr == "undefined") navigator.fileMgr = new FileMgr();}); @@ -1569,7 +1589,6 @@ PhoneGap.addConstructor(function() { * This class provides access to notifications on the device. */ function Notification() { - } /** @@ -1601,7 +1620,7 @@ Notification.prototype.activityStop = function() { * @param {String} colour The colour of the light. */ Notification.prototype.blink = function(count, colour) { - + }; /** @@ -1609,16 +1628,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, "Device", "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, "Device", "beep", [count]); }; // TODO: of course on Blackberry and Android there notifications in the UI as well @@ -1627,21 +1647,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 diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index c16bc73a..2b744fec 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -79,41 +79,69 @@ public class ContactAccessorSdk5 extends ContactAccessor { new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts.DISPLAY_NAME}, ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", new String[] {searchTerm}, - ContactsContract.Contacts.DISPLAY_NAME + " ASC"); + ContactsContract.Contacts.DISPLAY_NAME + " ASC"); + JSONArray contacts = new JSONArray(); while (cursor.moveToNext()) { + JSONObject contact = new JSONObject(); + String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); if (contactName.trim().length() == 0) continue; - String phoneNumber = "null"; - String emailAddress = "null"; + try { + contact.put("displayName", contactName); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); - if (Boolean.parseBoolean(hasPhone)) { + //String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); + //if (Boolean.parseBoolean(hasPhone)) { Cursor phones = cr.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); - if (phones.moveToFirst()) { - phoneNumber = "'" + phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace('\'', '`') + "'"; + if (phones.moveToFirst()) { + Log.d(LOG_TAG, "We found a phone!"); + JSONArray phoneNumbers = new JSONArray(); + JSONObject phoneNumber = new JSONObject(); + try { + phoneNumber.put("primary", true); + phoneNumber.put("value", phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace('\'', '`')); + phoneNumbers.put(phoneNumber); + contact.put("phoneNumbers", phoneNumbers); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } phones.close(); - } + //} Cursor emails = cr.query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null); if (emails.moveToFirst()) { - // This would allow you get several email addresses - emailAddress = "'" + emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)).replace('\'', '`') + "'"; + Log.d(LOG_TAG, "We found an email!"); + JSONArray emailAddresses = new JSONArray(); + JSONObject email = new JSONObject(); + try { + email.put("primary", true); + email.put("value", emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)).replace('\'', '`')); + emailAddresses.put(email); + contact.put("emails", emailAddresses); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } emails.close(); - String contactAddJS = "javascript:navigator.service.contacts.droidFoundContact('" + contactName.replace('\'', '`') + "'," + phoneNumber + "," + emailAddress +")"; - mView.loadUrl(contactAddJS); + contacts.put(contact); } cursor.close(); - mView.loadUrl("javascript:navigator.service.contacts.droidDone();"); + mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');"); } } \ No newline at end of file diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index 6a915740..1c752c05 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -70,13 +70,7 @@ public class ContactManager implements Plugin { //} //else if (action.equals("search")) { if (action.equals("search")) { - Log.d(LOG_TAG, "Executing search using accessor"); - JSONArray fields = args.getJSONArray(0); - for (int i=0; i Date: Mon, 20 Sep 2010 14:52:02 -0400 Subject: [PATCH 10/21] Adding queries for IM, Note, Nickname, Website, Relationship, Birthday and Anniversary --- .../src/com/phonegap/ContactAccessorSdk5.java | 225 ++++++++++++++---- 1 file changed, 184 insertions(+), 41 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index f88aae49..01fa0071 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -23,14 +23,8 @@ import org.json.JSONObject; import android.app.Activity; import android.content.ContentResolver; -import android.content.Intent; import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.net.Uri; import android.provider.ContactsContract; -import android.provider.Contacts.People; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.CommonDataKinds.Phone; import android.util.Log; import android.webkit.WebView; @@ -80,8 +74,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { e.printStackTrace(); } // Get a cursor by creating the query. - // TODO: parse name/number/email and dispatch to different query types. - // Right now assumption is only name search. Lame but I'm on time constraints. ContentResolver cr = mApp.getContentResolver(); Cursor cursor = cr.query( ContactsContract.Contacts.CONTENT_URI, @@ -114,6 +106,13 @@ public class ContactAccessorSdk5 extends ContactAccessor { 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) { // TODO Auto-generated catch block e.printStackTrace(); @@ -127,16 +126,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray organizationQuery(ContentResolver cr, String contactId) { - // TODO Fix the query URI - Cursor cursor = cr.query( - ContactsContract.CommonDataKinds.Phone.CONTENT_URI, - null, - ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, - null, null); + String orgWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] orgWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, orgWhere, orgWhereParams, null); JSONArray organizations = new JSONArray(); JSONObject organization = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a phone!"); + Log.d(LOG_TAG, "We found a organization!"); try { organization.put("department", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DEPARTMENT))); organization.put("description", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION))); @@ -158,16 +156,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray addressQuery(ContentResolver cr, String contactId) { - // TODO Fix the query URI - Cursor cursor = cr.query( - ContactsContract.CommonDataKinds.Phone.CONTENT_URI, - null, - ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, - null, null); + String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] addrWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, addrWhere, addrWhereParams, null); JSONArray addresses = new JSONArray(); JSONObject address = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a phone!"); + Log.d(LOG_TAG, "We found a address!"); try { address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS))); address.put("streetAddress", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET))); @@ -186,26 +183,35 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONObject nameQuery(ContentResolver cr, String contactId) { - // TODO Fix the query URI - Cursor name = cr.query( - ContactsContract.CommonDataKinds.Phone.CONTENT_URI, - null, - ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, - null, null); + String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] addrWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}; + Cursor name = cr.query(ContactsContract.Data.CONTENT_URI, + null, addrWhere, addrWhereParams, null); JSONObject contactName = new JSONObject(); if (name.moveToFirst()) { Log.d(LOG_TAG, "We found a name!"); try { - contactName.put("familyName", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME))); - contactName.put("givenName", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME))); - contactName.put("middleName", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME))); - contactName.put("honorificPrefix", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX))); - contactName.put("honorificSuffix", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX))); - contactName.put("formatted", name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX)) - + " " + name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)) - + " " + name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME)) - + " " + name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)) - + " " + name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX))); + 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) { // TODO Auto-generated catch block e.printStackTrace(); @@ -227,7 +233,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { Log.d(LOG_TAG, "We found a phone!"); try { phoneNumber.put("primary", false); // Android does not store primary attribute - phoneNumber.put("value", phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace('\'', '`')); + 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) { @@ -251,7 +257,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { Log.d(LOG_TAG, "We found an email!"); try { email.put("primary", false); - email.put("value", emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)).replace('\'', '`')); + 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) { @@ -262,5 +268,142 @@ public class ContactAccessorSdk5 extends ContactAccessor { emails.close(); return emailAddresses; } - + + private JSONArray imQuery(ContentResolver cr, String contactId) { + String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] addrWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, addrWhere, addrWhereParams, null); + JSONArray ims = new JSONArray(); + JSONObject im = new JSONObject(); + while (cursor.moveToNext()) { + Log.d(LOG_TAG, "We found IM's!"); + try { + im.put("primary", false); + 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) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + cursor.close(); + return ims; + } + + private String noteQuery(ContentResolver cr, String contactId) { + String noteWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] noteWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, noteWhere, noteWhereParams, null); + String note = new String(""); + if (cursor.moveToFirst()) { + Log.d(LOG_TAG, "We found a note!"); + note = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE)); + } + cursor.close(); + return note; + } + + private String nicknameQuery(ContentResolver cr, String contactId) { + String nicknameWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] nicknameWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, nicknameWhere, nicknameWhereParams, null); + String nickname = new String(""); + if (cursor.moveToFirst()) { + Log.d(LOG_TAG, "We found a nickname!"); + nickname = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME)); + } + cursor.close(); + return nickname; + } + + private JSONArray websiteQuery(ContentResolver cr, String contactId) { + String websiteWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] websiteWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, websiteWhere, websiteWhereParams, null); + JSONArray websites = new JSONArray(); + JSONObject website = new JSONObject(); + while (cursor.moveToNext()) { + Log.d(LOG_TAG, "We found websites!"); + try { + website.put("primary", false); + 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) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + cursor.close(); + return websites; + } + + private JSONArray relationshipQuery(ContentResolver cr, String contactId) { + String relationshipWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] relationshipWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Relation.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, relationshipWhere, relationshipWhereParams, null); + JSONArray relationships = new JSONArray(); + JSONObject relationship = new JSONObject(); + while (cursor.moveToNext()) { + Log.d(LOG_TAG, "We found a relationship!"); + try { + relationship.put("primary", false); + 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) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + cursor.close(); + return relationships; + } + + private String birthdayQuery(ContentResolver cr, String contactId) { + String birthdayWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] birthdayWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, birthdayWhere, birthdayWhereParams, null); + String birthday = new String(""); + while (cursor.moveToNext()) { + Log.d(LOG_TAG, "We found a birthday!"); + if (ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY == + cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE))) { + birthday = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE)); + } + } + cursor.close(); + return birthday; + } + + private String anniversaryQuery(ContentResolver cr, String contactId) { + String anniversaryWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] anniversaryWhereParams = new String[]{contactId, + ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE}; + Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, + null, anniversaryWhere, anniversaryWhereParams, null); + String anniversary = new String(""); + while (cursor.moveToNext()) { + Log.d(LOG_TAG, "We found a anniversary!"); + if (ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY == + cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE))) { + anniversary = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE)); + } + } + cursor.close(); + return anniversary; + } } \ No newline at end of file From f68b75c1cf5e12e93ef614ed64221242224553fd Mon Sep 17 00:00:00 2001 From: macdonst Date: Mon, 20 Sep 2010 15:51:12 -0400 Subject: [PATCH 11/21] Small refactor on birthday and anniversary --- .../src/com/phonegap/ContactAccessorSdk5.java | 85 +++++++------------ 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index 01fa0071..cdcd256e 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -70,8 +70,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { System.out.println("Limit = " + limit); System.out.println("Multiple = " + multiple); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } // Get a cursor by creating the query. ContentResolver cr = mApp.getContentResolver(); @@ -82,25 +81,20 @@ public class ContactAccessorSdk5 extends ContactAccessor { new String[] {searchTerm}, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); JSONArray contacts = new JSONArray(); + JSONObject contact; int pos = 0; while (cursor.moveToNext() && (pos < limit)) { - JSONObject contact = new JSONObject(); + contact = new JSONObject(); String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); if (contactName.trim().length() == 0) continue; - - try { - contact.put("displayName", contactName); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); //String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); //if (Boolean.parseBoolean(hasPhone)) { //} try { + contact.put("displayName", contactName); contact.put("name", nameQuery(cr, contactId)); contact.put("phoneNumbers", phoneQuery(cr, contactId)); contact.put("emails", emailQuery(cr, contactId)); @@ -114,8 +108,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { contact.put("birthday",birthdayQuery(cr, contactId)); contact.put("anniversary",anniversaryQuery(cr, contactId)); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } contacts.put(contact); @@ -147,8 +140,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { organization.put("title", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE))); organizations.put(organization); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } cursor.close(); @@ -174,8 +166,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { address.put("country", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY))); addresses.put(address); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } cursor.close(); @@ -213,8 +204,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { contactName.put("honorificSuffix", honorificSuffix); contactName.put("formatted", formatted); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } name.close(); @@ -237,8 +227,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { phoneNumber.put("type", phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))); phoneNumbers.put(phoneNumber); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } phones.close(); @@ -261,8 +250,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { email.put("type", emails.getInt(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE))); emailAddresses.put(email); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } emails.close(); @@ -285,8 +273,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { im.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.TYPE))); ims.put(im); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } cursor.close(); @@ -339,8 +326,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { website.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.TYPE))); websites.put(website); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } cursor.close(); @@ -363,8 +349,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { relationship.put("type", cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Relation.TYPE))); relationships.put(relationship); } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + Log.e(LOG_TAG, e.getMessage(), e); } } cursor.close(); @@ -372,38 +357,34 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private String birthdayQuery(ContentResolver cr, String contactId) { - String birthdayWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] birthdayWhereParams = new String[]{contactId, - ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE}; - Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, birthdayWhere, birthdayWhereParams, null); - String birthday = new String(""); - while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a birthday!"); - if (ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY == - cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE))) { - birthday = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE)); - } - } - cursor.close(); + 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); + Log.d(LOG_TAG, birthday); return birthday; } private String anniversaryQuery(ContentResolver cr, String contactId) { - String anniversaryWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] anniversaryWhereParams = new String[]{contactId, - ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE}; + 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); + Log.d(LOG_TAG, anniversary); + return anniversary; + } + + private String conditionalStringQuery(ContentResolver cr, String contactId, String dataType, int type, String label, String data) { + String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + String[] whereParams = new String[]{contactId, dataType}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, anniversaryWhere, anniversaryWhereParams, null); - String anniversary = new String(""); + null, where, whereParams, null); + String retVal = new String(""); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a anniversary!"); - if (ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY == - cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE))) { - anniversary = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE)); + Log.d(LOG_TAG, "We found an event!"); + if (type == cursor.getInt(cursor.getColumnIndex(label))) { + retVal = cursor.getString(cursor.getColumnIndex(data)); } } cursor.close(); - return anniversary; + return retVal; } } \ No newline at end of file From fdca4c5ecb04cb2cce5d1bf3196bfdd69d7d83ab Mon Sep 17 00:00:00 2001 From: macdonst Date: Mon, 20 Sep 2010 21:38:29 -0400 Subject: [PATCH 12/21] First pass as pre 2.0 Android contacts --- .../com/phonegap/ContactAccessorSdk3_4.java | 180 +++++++++++++++++- 1 file changed, 174 insertions(+), 6 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index acdbd8af..f84fc0b4 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -18,15 +18,19 @@ package com.phonegap; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; -import android.content.AsyncQueryHandler; +import android.content.ContentResolver; import android.database.Cursor; import android.database.sqlite.SQLiteException; 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; @@ -58,13 +62,177 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { @Override public void search(JSONArray filter, JSONObject options) { - //if (email.length() > 0) - // searchByEmail(email); - //else - // searchPeople(name, npa); - searchPeople("", ""); + String searchTerm = ""; + int limit = Integer.MAX_VALUE; + boolean multiple = true; + try { + searchTerm = options.getString("filter"); + if (searchTerm.length()==0) searchTerm = "%"; + multiple = options.getBoolean("multiple"); + if (multiple) { + limit = options.getInt("limit"); + } + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + } + + + JSONArray contacts = new JSONArray(); + JSONObject contact; + + ContentResolver cr = mApp.getContentResolver(); + Cursor cur = cr.query(People.CONTENT_URI, + null, null, null, null); + + int pos = 0; + while (cur.moveToNext() && pos < limit) { + contact = new JSONObject(); + try { + String contactId = cur.getString(cur.getColumnIndex(People._ID)); + // name + contact.put("id", contactId); + contact.put("displayName", cur.getString(cur.getColumnIndex(People.DISPLAY_NAME))); + + // phone number + if (Integer.parseInt(cur.getString(cur.getColumnIndex(People.PRIMARY_PHONE_ID))) > 0) { + 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 + cur.getString(cur.getColumnIndex(People.NOTES)); + // nickname + // urls + // relationship + // birthdays + // anniversary + + pos++; + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + } + contacts.put(contact); + } } + 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("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("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("value", cursor.getString(cursor.getColumnIndex(ContactMethods.DATA))); + email.put("type", cursor.getString(cursor.getColumnIndex(ContactMethods.TYPE))); + emails.put(email); + } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); + } + } + return emails; + } + private void searchByEmail(String email) { String[] projection = new String[] { From 328bc106e549009e9024b530fcfc4db0ecf09494 Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 21 Sep 2010 22:08:45 -0400 Subject: [PATCH 13/21] Able to query contact DB on Android 1.6 --- framework/assets/js/phonegap.js.base | 22 +++++++++++++++++++ framework/assets/www/phonegap.js | 22 +++++++++++++++++++ .../com/phonegap/ContactAccessorSdk3_4.java | 6 ++++- .../src/com/phonegap/ContactManager.java | 14 +++++++----- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base index af0fb556..c6215128 100755 --- a/framework/assets/js/phonegap.js.base +++ b/framework/assets/js/phonegap.js.base @@ -237,6 +237,28 @@ PhoneGap.stringify = function(args) { if ((type == "number") || (type == "boolean")) { s = s + args[i]; } + else if (args[i] instanceof Array) { + s = s + "[" + args[i] + "]"; + } + else if (args[i] instanceof Object) { + var start = true; + s = s + '{'; + for (var name in args[i]) { + if (!start) { + s = s + ','; + } + s = s + '"' + name + '":'; + var nameType = typeof args[i][name]; + if ((nameType == "number") || (nameType == "boolean")) { + s = s + args[i][name]; + } + else { + s = s + '"' + args[i][name] + '"'; + } + start=false; + } + s = s + '}'; + } else { s = s + '"' + args[i] + '"'; } diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index c8791cbe..a98a68c2 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -237,6 +237,28 @@ PhoneGap.stringify = function(args) { if ((type == "number") || (type == "boolean")) { s = s + args[i]; } + else if (args[i] instanceof Array) { + s = s + "[" + args[i] + "]"; + } + else if (args[i] instanceof Object) { + var start = true; + s = s + '{'; + for (var name in args[i]) { + if (!start) { + s = s + ','; + } + s = s + '"' + name + '":'; + var nameType = typeof args[i][name]; + if ((nameType == "number") || (nameType == "boolean")) { + s = s + args[i][name]; + } + else { + s = s + '"' + args[i][name] + '"'; + } + start=false; + } + s = s + '}'; + } else { s = s + '"' + args[i] + '"'; } diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index f84fc0b4..927003f4 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -62,6 +62,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { @Override public void search(JSONArray filter, JSONObject options) { + Log.d(LOG_TAG, "in 1.5+ search"); String searchTerm = ""; int limit = Integer.MAX_VALUE; boolean multiple = true; @@ -98,7 +99,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { contact.put("phoneNumbers", phoneQuery(cr, contactId)); } // email - contact.put("emails", emailQuery(cr, contactId)); + //contact.put("emails", emailQuery(cr, contactId)); // addresses contact.put("addresses", addressQuery(cr, contactId)); // organizations @@ -119,6 +120,9 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } contacts.put(contact); } + cur.close(); + Log.d(LOG_TAG, "returning contacts string to javascript"); + mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');"); } private JSONArray imQuery(ContentResolver cr, String contactId) { diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index 1c752c05..2882cb60 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -2,7 +2,6 @@ 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; @@ -10,9 +9,7 @@ import com.phonegap.api.PluginResult; import android.util.Log; import android.webkit.WebView; import android.content.Intent; -import android.net.Uri; -@SuppressWarnings("deprecation") public class ContactManager implements Plugin { private static ContactAccessor contactAccessor; @@ -20,9 +17,6 @@ public class ContactManager implements Plugin { 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. @@ -70,10 +64,18 @@ public class ContactManager implements Plugin { //} //else if (action.equals("search")) { if (action.equals("search")) { + Log.d(LOG_TAG, "*** Calling search of " + contactAccessor.getClass().getName()); + Log.d(LOG_TAG, "what is 0 " + args.get(0).getClass().toString()); + Log.d(LOG_TAG, "what is 0 " + args.get(0).toString()); + Log.d(LOG_TAG, "what is 1 " + args.get(1).getClass().toString()); + Log.d(LOG_TAG, "what is 1 " + args.get(1).toString()); + Log.d(LOG_TAG, "Fields = " + args.getJSONArray(0).toString()); + Log.d(LOG_TAG, "Options = " + args.getJSONObject(1).toString()); contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1)); } return new PluginResult(status, result); } catch (JSONException e) { + Log.e(LOG_TAG, e.getMessage(), e); return new PluginResult(PluginResult.Status.JSON_EXCEPTION); } } From 1768b507f8a21871c4c9d05f5bba66b7c33b4f65 Mon Sep 17 00:00:00 2001 From: macdonst Date: Wed, 22 Sep 2010 11:37:12 -0400 Subject: [PATCH 14/21] Cleaning up logs from ContactAccessors --- .../com/phonegap/ContactAccessorSdk3_4.java | 236 +----------------- .../src/com/phonegap/ContactAccessorSdk5.java | 13 - 2 files changed, 2 insertions(+), 247 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index 927003f4..2f420963 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -24,8 +24,6 @@ import org.json.JSONObject; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.net.Uri; import android.provider.Contacts.ContactMethods; import android.provider.Contacts.ContactMethodsColumns; import android.provider.Contacts.Organizations; @@ -50,10 +48,6 @@ import android.webkit.WebView; @SuppressWarnings("deprecation") public class ContactAccessorSdk3_4 extends ContactAccessor { - private Uri mPeople = android.provider.Contacts.People.CONTENT_URI; - private Uri mPhone = android.provider.Contacts.Phones.CONTENT_URI; - private Uri mEmail = android.provider.Contacts.ContactMethods.CONTENT_URI; - public ContactAccessorSdk3_4(WebView view, Activity app) { mApp = app; @@ -62,7 +56,6 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { @Override public void search(JSONArray filter, JSONObject options) { - Log.d(LOG_TAG, "in 1.5+ search"); String searchTerm = ""; int limit = Integer.MAX_VALUE; boolean multiple = true; @@ -99,7 +92,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { contact.put("phoneNumbers", phoneQuery(cr, contactId)); } // email - //contact.put("emails", emailQuery(cr, contactId)); + contact.put("emails", emailQuery(cr, contactId)); // addresses contact.put("addresses", addressQuery(cr, contactId)); // organizations @@ -121,7 +114,6 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { contacts.put(contact); } cur.close(); - Log.d(LOG_TAG, "returning contacts string to javascript"); mView.loadUrl("javascript:navigator.service.contacts.droidDone('" + contacts.toString() + "');"); } @@ -228,7 +220,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { email = new JSONObject(); try{ email.put("value", cursor.getString(cursor.getColumnIndex(ContactMethods.DATA))); - email.put("type", cursor.getString(cursor.getColumnIndex(ContactMethods.TYPE))); + //email.put("type", cursor.getString(cursor.getColumnIndex(ContactMethods.TYPE))); emails.put(email); } catch (JSONException e) { Log.e(LOG_TAG, e.getMessage(), e); @@ -236,228 +228,4 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } return emails; } - - 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 = mApp.managedQuery(mEmail, projection, - "contact_methods." + ContactMethods.DATA + " = ?" + "AND contact_methods.kind = 1", variables , ContactMethods.DATA + " ASC"); - getMethodData(myCursor); - - } - catch (SQLiteException ex) - { - Log.d(this.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 = mApp.managedQuery(mPeople, projection, - conditions, variables , People.NAME + " ASC"); - processResults(myCursor, false); - } - catch (SQLiteException ex) - { - Log.d(this.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) - mView.loadUrl("javascript:navigator.service.ContactManager.droidAddContact('" + name + "','" + phoneNumber + "','" + email +"')"); - else - mView.loadUrl("javascript:navigator.service.contacts.droidFoundContact('" + name + "','" + phoneNumber + "','" + email +"')"); - - } while (cur.moveToNext()); - if (all) - mView.loadUrl("javascript:navigator.service.ContactManager.droidDone()"); - else - mView.loadUrl("javascript:navigator.service.contacts.droidDone();"); - } - else - { - if(all) - mView.loadUrl("javascript:navigator.service.ContactManager.fail()"); - else - mView.loadUrl("javascript:navigator.service.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; - mView.loadUrl("javascript:navigator.service.Contacts.droidFoundContact('" + data.name + "','" + data.phone + "','" + data.email +"')"); - } - } while (cur.moveToNext()); - mView.loadUrl("javascript:navigator.service.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 = mApp.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 = mApp.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; - } } \ No newline at end of file diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index cdcd256e..ee4d4ee3 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -127,7 +127,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray organizations = new JSONArray(); JSONObject organization = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a organization!"); try { organization.put("department", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DEPARTMENT))); organization.put("description", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION))); @@ -156,7 +155,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray addresses = new JSONArray(); JSONObject address = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a address!"); try { address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS))); address.put("streetAddress", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET))); @@ -181,7 +179,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { null, addrWhere, addrWhereParams, null); JSONObject contactName = new JSONObject(); if (name.moveToFirst()) { - Log.d(LOG_TAG, "We found a name!"); try { String familyName = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)); String givenName = name.getString(name.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)); @@ -220,7 +217,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray phoneNumbers = new JSONArray(); JSONObject phoneNumber = new JSONObject(); while (phones.moveToNext()) { - Log.d(LOG_TAG, "We found a phone!"); try { phoneNumber.put("primary", false); // Android does not store primary attribute phoneNumber.put("value", phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); @@ -243,7 +239,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray emailAddresses = new JSONArray(); JSONObject email = new JSONObject(); while (emails.moveToNext()) { - Log.d(LOG_TAG, "We found an email!"); try { email.put("primary", false); email.put("value", emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA))); @@ -266,7 +261,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray ims = new JSONArray(); JSONObject im = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found IM's!"); try { im.put("primary", false); im.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA))); @@ -288,7 +282,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { null, noteWhere, noteWhereParams, null); String note = new String(""); if (cursor.moveToFirst()) { - Log.d(LOG_TAG, "We found a note!"); note = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE)); } cursor.close(); @@ -303,7 +296,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { null, nicknameWhere, nicknameWhereParams, null); String nickname = new String(""); if (cursor.moveToFirst()) { - Log.d(LOG_TAG, "We found a nickname!"); nickname = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME)); } cursor.close(); @@ -319,7 +311,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray websites = new JSONArray(); JSONObject website = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found websites!"); try { website.put("primary", false); website.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL))); @@ -342,7 +333,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONArray relationships = new JSONArray(); JSONObject relationship = new JSONObject(); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found a relationship!"); try { relationship.put("primary", false); relationship.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Relation.NAME))); @@ -360,7 +350,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { 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); - Log.d(LOG_TAG, birthday); return birthday; } @@ -368,7 +357,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { 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); - Log.d(LOG_TAG, anniversary); return anniversary; } @@ -379,7 +367,6 @@ public class ContactAccessorSdk5 extends ContactAccessor { null, where, whereParams, null); String retVal = new String(""); while (cursor.moveToNext()) { - Log.d(LOG_TAG, "We found an event!"); if (type == cursor.getInt(cursor.getColumnIndex(label))) { retVal = cursor.getString(cursor.getColumnIndex(data)); } From a9f057c2784c2981d7f05ba32afaae085d4e6705 Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 24 Sep 2010 11:43:10 -0400 Subject: [PATCH 15/21] Cleaning up some accessor code --- framework/assets/js/contact.js | 74 +++++++++---------- framework/assets/www/phonegap.js | 74 +++++++++---------- .../src/com/phonegap/ContactAccessor.java | 7 -- .../com/phonegap/ContactAccessorSdk3_4.java | 6 +- .../src/com/phonegap/ContactAccessorSdk5.java | 41 ++++------ .../src/com/phonegap/ContactManager.java | 20 +++-- 6 files changed, 104 insertions(+), 118 deletions(-) diff --git a/framework/assets/js/contact.js b/framework/assets/js/contact.js index 0dda86e5..1d5eb4c0 100644 --- a/framework/assets/js/contact.js +++ b/framework/assets/js/contact.js @@ -2,69 +2,69 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, ims, organizations, published, updated, birthday, anniversary, gender, note, preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) { - this.id = id || ''; - this.displayName = displayName || ''; + this.id = id || null; + this.displayName = displayName || null; this.name = name || null; // ContactName - this.nickname = nickname || ''; + this.nickname = nickname || null; this.phoneNumbers = phoneNumbers || null; // ContactField[] this.emails = emails || null; // ContactField[] this.addresses = addresses || null; // ContactAddress[] this.ims = ims || null; // ContactField[] this.organizations = organizations || null; // ContactOrganization[] - this.published = published || ''; - this.updated = updated || ''; - this.birthday = birthday || ''; - this.anniversary = anniversary || ''; - this.gender = gender || ''; - this.note = note || ''; - this.preferredUsername = preferredUsername || ''; + this.published = published || null; + this.updated = updated || null; + this.birthday = birthday || null; + this.anniversary = anniversary || null; + this.gender = gender || null; + this.note = note || null; + this.preferredUsername = preferredUsername || null; this.photos = photos || null; // ContactField[] this.tags = tags || null; // ContactField[] this.relationships = relationships || null; // ContactField[] this.urls = urls || null; // ContactField[] this.accounts = accounts || null; // ContactAccount[] - this.utcOffset = utcOffset || ''; - this.connected = connected || ''; + this.utcOffset = utcOffset || null; + this.connected = connected || null; }; var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { - this.formatted = formatted || ''; - this.familyName = familyName || ''; - this.givenName = givenName || ''; - this.middleName = middle || ''; - this.honorificPrefix = prefix || ''; - this.honorificSuffix = suffix || ''; + this.formatted = formatted || null; + this.familyName = familyName || null; + this.givenName = givenName || null; + this.middleName = middle || null; + this.honorificPrefix = prefix || null; + this.honorificSuffix = suffix || null; }; var ContactField = function(type, value, primary) { - this.type = type || ''; - this.value = value || ''; - this.primary = primary || ''; + this.type = type || null; + this.value = value || null; + this.primary = primary || null; }; var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) { - this.formatted = formatted || ''; - this.streetAddress = streetAddress || ''; - this.locality = locality || ''; - this.region = region || ''; - this.postalCode = postalCode || ''; - this.country = country || ''; + this.formatted = formatted || null; + this.streetAddress = streetAddress || null; + this.locality = locality || null; + this.region = region || null; + this.postalCode = postalCode || null; + this.country = country || null; }; var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) { - this.name = name || ''; - this.department = dept || ''; - this.title = title || ''; - this.startDate = startDate || ''; - this.endDate = endDate || ''; - this.location = location || ''; - this.description = desc || ''; + this.name = name || null; + this.department = dept || null; + this.title = title || null; + this.startDate = startDate || null; + this.endDate = endDate || null; + this.location = location || null; + this.description = desc || null; }; var ContactAccount = function(domain, username, userid) { - this.domain = domain || ''; - this.username = username || ''; - this.userid = userid || ''; + this.domain = domain || null; + this.username = username || null; + this.userid = userid || null; } var Contacts = function() { diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index a98a68c2..609722aa 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -830,69 +830,69 @@ PhoneGap.addConstructor(function() { var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, ims, organizations, published, updated, birthday, anniversary, gender, note, preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) { - this.id = id || ''; - this.displayName = displayName || ''; + this.id = id || null; + this.displayName = displayName || null; this.name = name || null; // ContactName - this.nickname = nickname || ''; + this.nickname = nickname || null; this.phoneNumbers = phoneNumbers || null; // ContactField[] this.emails = emails || null; // ContactField[] this.addresses = addresses || null; // ContactAddress[] this.ims = ims || null; // ContactField[] this.organizations = organizations || null; // ContactOrganization[] - this.published = published || ''; - this.updated = updated || ''; - this.birthday = birthday || ''; - this.anniversary = anniversary || ''; - this.gender = gender || ''; - this.note = note || ''; - this.preferredUsername = preferredUsername || ''; + this.published = published || null; + this.updated = updated || null; + this.birthday = birthday || null; + this.anniversary = anniversary || null; + this.gender = gender || null; + this.note = note || null; + this.preferredUsername = preferredUsername || null; this.photos = photos || null; // ContactField[] this.tags = tags || null; // ContactField[] this.relationships = relationships || null; // ContactField[] this.urls = urls || null; // ContactField[] this.accounts = accounts || null; // ContactAccount[] - this.utcOffset = utcOffset || ''; - this.connected = connected || ''; + this.utcOffset = utcOffset || null; + this.connected = connected || null; }; var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) { - this.formatted = formatted || ''; - this.familyName = familyName || ''; - this.givenName = givenName || ''; - this.middleName = middle || ''; - this.honorificPrefix = prefix || ''; - this.honorificSuffix = suffix || ''; + this.formatted = formatted || null; + this.familyName = familyName || null; + this.givenName = givenName || null; + this.middleName = middle || null; + this.honorificPrefix = prefix || null; + this.honorificSuffix = suffix || null; }; var ContactField = function(type, value, primary) { - this.type = type || ''; - this.value = value || ''; - this.primary = primary || ''; + this.type = type || null; + this.value = value || null; + this.primary = primary || null; }; var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) { - this.formatted = formatted || ''; - this.streetAddress = streetAddress || ''; - this.locality = locality || ''; - this.region = region || ''; - this.postalCode = postalCode || ''; - this.country = country || ''; + this.formatted = formatted || null; + this.streetAddress = streetAddress || null; + this.locality = locality || null; + this.region = region || null; + this.postalCode = postalCode || null; + this.country = country || null; }; var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) { - this.name = name || ''; - this.department = dept || ''; - this.title = title || ''; - this.startDate = startDate || ''; - this.endDate = endDate || ''; - this.location = location || ''; - this.description = desc || ''; + this.name = name || null; + this.department = dept || null; + this.title = title || null; + this.startDate = startDate || null; + this.endDate = endDate || null; + this.location = location || null; + this.description = desc || null; }; var ContactAccount = function(domain, username, userid) { - this.domain = domain || ''; - this.username = username || ''; - this.userid = userid || ''; + this.domain = domain || null; + this.username = username || null; + this.userid = userid || null; } var Contacts = function() { diff --git a/framework/src/com/phonegap/ContactAccessor.java b/framework/src/com/phonegap/ContactAccessor.java index 867fe5e1..ac03c414 100644 --- a/framework/src/com/phonegap/ContactAccessor.java +++ b/framework/src/com/phonegap/ContactAccessor.java @@ -35,13 +35,6 @@ import org.json.JSONObject; */ public abstract class ContactAccessor { - public class ContactTriplet - { - public String name = ""; - public String email = ""; - public String phone = ""; - } - /** * Static singleton instance of {@link ContactAccessor} holding the * SDK-specific implementation of the class. diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index 2f420963..506e8147 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -100,7 +100,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { // ims contact.put("ims", imQuery(cr, contactId)); // note - cur.getString(cur.getColumnIndex(People.NOTES)); + contact.put("note", cur.getString(cur.getColumnIndex(People.NOTES))); // nickname // urls // relationship @@ -128,6 +128,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { 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( @@ -198,6 +199,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { 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); @@ -219,7 +221,9 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { 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) { diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index ee4d4ee3..f2a0ed96 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -48,6 +48,8 @@ import android.webkit.WebView; */ public class ContactAccessorSdk5 extends ContactAccessor { + private static final String WHERE_STRING = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; + public ContactAccessorSdk5(WebView view, Activity app) { mApp = app; @@ -90,10 +92,8 @@ public class ContactAccessorSdk5 extends ContactAccessor { if (contactName.trim().length() == 0) continue; String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); - //String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); - //if (Boolean.parseBoolean(hasPhone)) { - //} try { + contact.put("id", contactId); contact.put("displayName", contactName); contact.put("name", nameQuery(cr, contactId)); contact.put("phoneNumbers", phoneQuery(cr, contactId)); @@ -119,11 +119,10 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray organizationQuery(ContentResolver cr, String contactId) { - String orgWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] orgWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, orgWhere, orgWhereParams, null); + null, WHERE_STRING, orgWhereParams, null); JSONArray organizations = new JSONArray(); JSONObject organization = new JSONObject(); while (cursor.moveToNext()) { @@ -147,11 +146,10 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray addressQuery(ContentResolver cr, String contactId) { - String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] addrWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, addrWhere, addrWhereParams, null); + null, WHERE_STRING, addrWhereParams, null); JSONArray addresses = new JSONArray(); JSONObject address = new JSONObject(); while (cursor.moveToNext()) { @@ -172,11 +170,10 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONObject nameQuery(ContentResolver cr, String contactId) { - String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] addrWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}; Cursor name = cr.query(ContactsContract.Data.CONTENT_URI, - null, addrWhere, addrWhereParams, null); + null, WHERE_STRING, addrWhereParams, null); JSONObject contactName = new JSONObject(); if (name.moveToFirst()) { try { @@ -240,7 +237,7 @@ public class ContactAccessorSdk5 extends ContactAccessor { JSONObject email = new JSONObject(); while (emails.moveToNext()) { try { - email.put("primary", false); + 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); @@ -253,16 +250,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray imQuery(ContentResolver cr, String contactId) { - String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] addrWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, addrWhere, addrWhereParams, null); + null, WHERE_STRING, addrWhereParams, null); JSONArray ims = new JSONArray(); JSONObject im = new JSONObject(); while (cursor.moveToNext()) { try { - im.put("primary", false); + 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); @@ -275,11 +271,10 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private String noteQuery(ContentResolver cr, String contactId) { - String noteWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] noteWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, noteWhere, noteWhereParams, null); + null, WHERE_STRING, noteWhereParams, null); String note = new String(""); if (cursor.moveToFirst()) { note = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE)); @@ -289,11 +284,10 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private String nicknameQuery(ContentResolver cr, String contactId) { - String nicknameWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] nicknameWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, nicknameWhere, nicknameWhereParams, null); + null, WHERE_STRING, nicknameWhereParams, null); String nickname = new String(""); if (cursor.moveToFirst()) { nickname = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME)); @@ -303,16 +297,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray websiteQuery(ContentResolver cr, String contactId) { - String websiteWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] websiteWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, websiteWhere, websiteWhereParams, null); + null, WHERE_STRING, websiteWhereParams, null); JSONArray websites = new JSONArray(); JSONObject website = new JSONObject(); while (cursor.moveToNext()) { try { - website.put("primary", false); + 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); @@ -325,16 +318,15 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private JSONArray relationshipQuery(ContentResolver cr, String contactId) { - String relationshipWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] relationshipWhereParams = new String[]{contactId, ContactsContract.CommonDataKinds.Relation.CONTENT_ITEM_TYPE}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, relationshipWhere, relationshipWhereParams, null); + null, WHERE_STRING, relationshipWhereParams, null); JSONArray relationships = new JSONArray(); JSONObject relationship = new JSONObject(); while (cursor.moveToNext()) { try { - relationship.put("primary", false); + 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); @@ -361,10 +353,9 @@ public class ContactAccessorSdk5 extends ContactAccessor { } private String conditionalStringQuery(ContentResolver cr, String contactId, String dataType, int type, String label, String data) { - String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; String[] whereParams = new String[]{contactId, dataType}; Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, - null, where, whereParams, null); + null, WHERE_STRING, whereParams, null); String retVal = new String(""); while (cursor.moveToNext()) { if (type == cursor.getInt(cursor.getColumnIndex(label))) { diff --git a/framework/src/com/phonegap/ContactManager.java b/framework/src/com/phonegap/ContactManager.java index 2882cb60..9cf6a891 100755 --- a/framework/src/com/phonegap/ContactManager.java +++ b/framework/src/com/phonegap/ContactManager.java @@ -59,20 +59,18 @@ public class ContactManager implements Plugin { String result = ""; try { - //if (action.equals("getContactsAndSendBack")) { - // contactAccessor.getContactsAndSendBack(); - //} - //else if (action.equals("search")) { if (action.equals("search")) { - Log.d(LOG_TAG, "*** Calling search of " + contactAccessor.getClass().getName()); - Log.d(LOG_TAG, "what is 0 " + args.get(0).getClass().toString()); - Log.d(LOG_TAG, "what is 0 " + args.get(0).toString()); - Log.d(LOG_TAG, "what is 1 " + args.get(1).getClass().toString()); - Log.d(LOG_TAG, "what is 1 " + args.get(1).toString()); - Log.d(LOG_TAG, "Fields = " + args.getJSONArray(0).toString()); - Log.d(LOG_TAG, "Options = " + args.getJSONObject(1).toString()); contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1)); } + 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); From 2098436a2ceeabd473b0ea65c49f4b5f7a26bd16 Mon Sep 17 00:00:00 2001 From: macdonst Date: Fri, 24 Sep 2010 16:15:16 -0400 Subject: [PATCH 16/21] Fixing query so that it uses wildcards --- framework/assets/www/phonegap.js | 1029 +++++++++++------ .../com/phonegap/ContactAccessorSdk3_4.java | 18 +- .../src/com/phonegap/ContactAccessorSdk5.java | 12 +- 3 files changed, 723 insertions(+), 336 deletions(-) diff --git a/framework/assets/www/phonegap.js b/framework/assets/www/phonegap.js index 609722aa..94a90752 100644 --- a/framework/assets/www/phonegap.js +++ b/framework/assets/www/phonegap.js @@ -1,4 +1,25 @@ +/** + * The order of events during page load and PhoneGap startup is as follows: + * + * onDOMContentLoaded Internal event that is received when the web page is loaded and parsed. + * window.onload Body onload event. + * onNativeReady Internal event that indicates the PhoneGap native side is ready. + * onPhoneGapInit Internal event that kicks off creation of all PhoneGap JavaScript objects (runs constructors). + * onPhoneGapReady Internal event fired when all PhoneGap JavaScript objects have been created + * onPhoneGapInfoReady Internal event fired when device properties are available + * onDeviceReady User event fired to indicate that PhoneGap is ready + * onResume User event fired to indicate a start/resume lifecycle event + * + * The only PhoneGap events that user code should register for are: + * onDeviceReady + * onResume + * + * Listeners can be registered as: + * document.addEventListener("deviceready", myDeviceReadyListener, false); + * document.addEventListener("resume", myResumeListener, false); + */ + if (typeof(DeviceInfo) != 'object') DeviceInfo = {}; @@ -124,7 +145,7 @@ PhoneGap.available = DeviceInfo.uuid != undefined; * @param {Function} func The function callback you want run once PhoneGap is initialized */ PhoneGap.addConstructor = function(func) { - PhoneGap.onDeviceReady.subscribeOnce(function() { + PhoneGap.onPhoneGapInit.subscribeOnce(function() { try { func(); } catch(e) { @@ -162,6 +183,23 @@ PhoneGap.onDOMContentLoaded = new PhoneGap.Channel('onDOMContentLoaded'); */ PhoneGap.onNativeReady = new PhoneGap.Channel('onNativeReady'); +/** + * onPhoneGapInit channel is fired when the web page is fully loaded and + * PhoneGap native code has been initialized. + */ +PhoneGap.onPhoneGapInit = new PhoneGap.Channel('onPhoneGapInit'); + +/** + * onPhoneGapReady channel is fired when the JS PhoneGap objects have been created. + */ +PhoneGap.onPhoneGapReady = new PhoneGap.Channel('onPhoneGapReady'); + +/** + * onPhoneGapInfoReady channel is fired when the PhoneGap device properties + * has been set. + */ +PhoneGap.onPhoneGapInfoReady = new PhoneGap.Channel('onPhoneGapInfoReady'); + /** * onResume channel is fired when the PhoneGap native code * resumes. @@ -180,29 +218,44 @@ PhoneGap.onPause = new PhoneGap.Channel('onPause'); if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); } /** - * onDeviceReady is fired only after both onDOMContentLoaded and - * onNativeReady have fired. + * onDeviceReady is fired only after all PhoneGap objects are created and + * the device properties are set. */ PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady'); -PhoneGap.onDeviceReady.subscribeOnce(function() { - PhoneGap.JSCallback(); -}); +/** + * Create all PhoneGap objects once page has fully loaded and native side is ready. + */ +PhoneGap.Channel.join(function() { + + // Start listening for XHR callbacks + PhoneGap.JSCallback(); + + // Run PhoneGap constructors + PhoneGap.onPhoneGapInit.fire(); + + // Fire event to notify that all objects are created + PhoneGap.onPhoneGapReady.fire(); + +}, [ PhoneGap.onDOMContentLoaded, PhoneGap.onNativeReady ]); + +/** + * Fire onDeviceReady event once all constructors have run and PhoneGap info has been + * received from native side. + */ PhoneGap.Channel.join(function() { PhoneGap.onDeviceReady.fire(); // Fire the onresume event, since first one happens before JavaScript is loaded PhoneGap.onResume.fire(); -}, [ PhoneGap.onDOMContentLoaded, PhoneGap.onNativeReady ]); - +}, [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady]); // Listen for DOMContentLoaded and notify our channel subscribers document.addEventListener('DOMContentLoaded', function() { PhoneGap.onDOMContentLoaded.fire(); }, false); - // Intercept calls to document.addEventListener and watch for deviceready PhoneGap.m_document_addEventListener = document.addEventListener; @@ -281,6 +334,7 @@ PhoneGap.callbacks = {}; * @param {String} command Command to be run in PhoneGap, e.g. "ClassName.method" * @param {String[]} [args] Zero or more arguments to pass to the method */ +// TODO: Not used anymore, should be removed. PhoneGap.exec = function(clazz, action, args) { try { var callbackId = 0; @@ -302,16 +356,32 @@ PhoneGap.exec = function(clazz, action, args) { } }; -PhoneGap.execAsync = function(success, fail, clazz, action, args) { +/** + * Execute a PhoneGap command. It is up to the native side whether this action is synch or async. + * The native side can return: + * Synchronous: PluginResult object as a JSON string + * Asynchrounous: Empty string "" + * If async, the native side will PhoneGap.callbackSuccess or PhoneGap.callbackError, + * depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action Action to be run in PhoneGap + * @param {String[]} [args] Zero or more arguments to pass to the method + */ +PhoneGap.execAsync = function(success, fail, service, action, args) { try { - var callbackId = clazz + PhoneGap.callbackId++; + var callbackId = service + PhoneGap.callbackId++; if (success || fail) { PhoneGap.callbacks[callbackId] = {success:success, fail:fail}; } - var r = PluginManager.exec(clazz, action, callbackId, this.stringify(args), true); + + // Note: Device returns string, but for some reason emulator returns object - so convert to string. + var r = ""+PluginManager.exec(service, action, callbackId, this.stringify(args), true); // If a result was returned - if ((typeof r == "string") && (r.length > 0)) { + if (r.length > 0) { eval("var v="+r+";"); // If status is OK, then return value back to caller @@ -342,6 +412,12 @@ PhoneGap.execAsync = function(success, fail, clazz, action, args) { } }; +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + */ PhoneGap.callbackSuccess = function(callbackId, args) { if (PhoneGap.callbacks[callbackId]) { try { @@ -356,6 +432,12 @@ PhoneGap.callbackSuccess = function(callbackId, args) { } }; +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ PhoneGap.callbackError = function(callbackId, args) { if (PhoneGap.callbacks[callbackId]) { try { @@ -378,6 +460,7 @@ PhoneGap.callbackError = function(callbackId, args) { * url, which will be turned into a dictionary on the other end. * @private */ +// TODO: Is this used? PhoneGap.run_command = function() { if (!PhoneGap.available || !PhoneGap.queue.ready) return; @@ -417,6 +500,8 @@ PhoneGap.run_command = function() { }; /** + * This is only for Android. + * * Internal function that uses XHR to call into PhoneGap Java code and retrieve * any JavaScript code that needs to be run. This is used for callbacks from * Java to JavaScript. @@ -993,22 +1078,46 @@ function Device() { this.phonegap = null; var me = this; - PhoneGap.execAsync( + this.getInfo( function(info) { me.available = true; me.platform = info.platform; me.version = info.version; me.uuid = info.uuid; me.phonegap = info.phonegap; + PhoneGap.onPhoneGapInfoReady.fire(); }, function(e) { me.available = false; console.log("Error initializing PhoneGap: " + e); alert("Error initializing PhoneGap: "+e); - }, - "Device", "getDeviceInfo", []); + }); } +/** + * Get device info + * + * @param {Function} successCallback The function to call when the heading data is available + * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL) + */ +Device.prototype.getInfo = function(successCallback, errorCallback) { + + // successCallback required + if (typeof successCallback != "function") { + console.log("Device Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Device Error: errorCallback is not a function"); + return; + } + + // Get info + PhoneGap.execAsync(successCallback, errorCallback, "Device", "getDeviceInfo", []); +}; + /* * This is only for Android. * @@ -1039,319 +1148,608 @@ Device.prototype.exitApp = function() { PhoneGap.addConstructor(function() { navigator.device = window.device = new Device(); }); +/** + * This class provides generic read and write access to the mobile device file system. + * They are not used to read files from a server. + */ +/** + * List of files + */ +function FileList() { + this.files = {}; +}; +/** + * Describes a single file in a FileList + */ +function File() { + this.name = null; + this.type = null; + this.urn = null; +}; -PhoneGap.addConstructor(function() { if (typeof navigator.fileMgr == "undefined") navigator.fileMgr = new FileMgr();}); +/** + * Create an event object since we can't set target on DOM event. + * + * @param type + * @param target + * + */ +File._createEvent = function(type, target) { + // Can't create event object, since we can't set target (its readonly) + //var evt = document.createEvent('Events'); + //evt.initEvent("onload", false, false); + var evt = {"type": type}; + evt.target = target; + return evt; +}; + +function FileError() { + // File error codes + // Found in DOMException + this.NOT_FOUND_ERR = 8; + this.SECURITY_ERR = 18; + this.ABORT_ERR = 20; + + // Added by this specification + this.NOT_READABLE_ERR = 24; + this.ENCODING_ERR = 26; + + this.code = null; +}; + +//----------------------------------------------------------------------------- +// File manager +//----------------------------------------------------------------------------- + +function FileMgr() { +}; + +FileMgr.prototype.getFileBasePaths = function() { +}; + +FileMgr.prototype.testSaveLocationExists = function(successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "testSaveLocationExists", []); +}; + +FileMgr.prototype.testFileExists = function(fileName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "testFileExists", [fileName]); +}; + +FileMgr.prototype.testDirectoryExists = function(dirName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]); +}; + +FileMgr.prototype.createDirectory = function(dirName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "createDirectory", [dirName]); +}; + +FileMgr.prototype.deleteDirectory = function(dirName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "deleteDirectory", [dirName]); +}; + +FileMgr.prototype.deleteFile = function(fileName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "deleteFile", [fileName]); +}; + +FileMgr.prototype.getFreeDiskSpace = function(successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "getFreeDiskSpace", []); +}; + +FileMgr.prototype.writeAsText = function(fileName, data, append, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "writeAsText", [fileName, data, append]); +}; + +FileMgr.prototype.readAsText = function(fileName, encoding, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "readAsText", [fileName, encoding]); +}; + +FileMgr.prototype.readAsDataURL = function(fileName, successCallback, errorCallback) { + PhoneGap.execAsync(successCallback, errorCallback, "File", "readAsDataURL", [fileName]); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.fileMgr == "undefined") navigator.fileMgr = new FileMgr(); +}); + +//----------------------------------------------------------------------------- +// File Reader +//----------------------------------------------------------------------------- +// TODO: All other FileMgr function operate on the SD card as root. However, +// for FileReader & FileWriter the root is not SD card. Should this be changed? + +/** + * This class reads the mobile device file system. + * + * For Android: + * The root directory is the root of the file system. + * To read from the SD card, the file name is "sdcard/my_file.txt" + */ +function FileReader() { + this.fileName = ""; + + this.readyState = 0; + + // File data + this.result = null; + + // Error + this.error = null; + + // Event handlers + this.onloadstart = null; // When the read starts. + this.onprogress = null; // While reading (and decoding) file or fileBlob data, and reporting partial file data (progess.loaded/progress.total) + this.onload = null; // When the read has successfully completed. + this.onerror = null; // When the read has failed (see errors). + this.onloadend = null; // When the request has completed (either in success or failure). + this.onabort = null; // When the read has been aborted. For instance, by invoking the abort() method. +}; + +// States +FileReader.EMPTY = 0; +FileReader.LOADING = 1; +FileReader.DONE = 2; + +/** + * Abort reading file. + */ +FileReader.prototype.abort = function() { + this.readyState = FileReader.DONE; + + // If abort callback + if (typeof this.onabort == "function") { + var evt = File._createEvent("abort", this); + this.onabort(evt); + } + + // TODO: Anything else to do? Maybe sent to native? +}; + +/** + * Read text file. + * + * @param file The name of the file + * @param encoding [Optional] (see http://www.iana.org/assignments/character-sets) + */ +FileReader.prototype.readAsText = function(file, encoding) { + this.fileName = file; + + // LOADING state + this.readyState = FileReader.LOADING; + + // If loadstart callback + if (typeof this.onloadstart == "function") { + var evt = File._createEvent("loadstart", this); + this.onloadstart(evt); + } + + // Default encoding is UTF-8 + var enc = encoding ? encoding : "UTF-8"; + + var me = this; + + // Read file + navigator.fileMgr.readAsText(file, enc, + + // 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); + } + } + ); +}; /** - * This class provides iPhone read and write access to the mobile device file system. - * Based loosely on http://www.w3.org/TR/2009/WD-FileAPI-20091117/#dfn-empty - */ -function FileMgr() -{ - this.fileWriters = {}; // empty maps - this.fileReaders = {}; - - this.docsFolderPath = "../../Documents"; - this.tempFolderPath = "../../tmp"; - this.freeDiskSpace = -1; - this.getFileBasePaths(); -} - -// private, called from Native Code -FileMgr.prototype._setPaths = function(docs,temp) -{ - this.docsFolderPath = docs; - this.tempFolderPath = temp; -} - -// private, called from Native Code -FileMgr.prototype._setFreeDiskSpace = function(val) -{ - this.freeDiskSpace = val; -} - - -// FileWriters add/remove -// called internally by writers -FileMgr.prototype.addFileWriter = function(filePath,fileWriter) -{ - this.fileWriters[filePath] = fileWriter; -} - -FileMgr.prototype.removeFileWriter = function(filePath) -{ - this.fileWriters[filePath] = null; -} - -// File readers add/remove -// called internally by readers -FileMgr.prototype.addFileReader = function(filePath,fileReader) -{ - this.fileReaders[filePath] = fileReader; -} - -FileMgr.prototype.removeFileReader = function(filePath) -{ - this.fileReaders[filePath] = null; -} - -/******************************************* + * Read file and return data as a base64 encoded data url. + * A data url is of the form: + * data:[][;base64], * - * 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() { } @@ -1560,8 +1958,8 @@ Media.prototype.stopRecord = function() { * @constructor */ function NetworkStatus() { - this.code = null; - this.message = ""; + //this.code = null; + //this.message = ""; }; NetworkStatus.NOT_REACHABLE = 0; @@ -1598,38 +1996,11 @@ Network.prototype.updateReachability = function(reachability) { * @param {Object} options (isIpAddress:boolean) */ Network.prototype.isReachable = function(uri, callback, options) { - - // callback required - if (typeof callback != "function") { - console.log("Network Error: callback is not a function"); - return; + var isIpAddress = false; + if (options && options.isIpAddress) { + isIpAddress = options.isIpAddress; } - - PhoneGap.execAsync( - function(status) { - - // If reachable, the check for wifi vs carrier - if (status) { - PhoneGap.execAsync( - function(wifi) { - var s = new NetworkStatus(); - if (wifi) { - s.code = NetworkStatus.REACHABLE_VIA_WIFI_NETWORK; - } - else { - s.code = NetworkStatus.REACHABLE_VIA_CARRIER_DATA_NETWORK; - } - callback(s); - }, null, "Network Status", "isWifiActive", []); - } - - // If not - else { - var s = new NetworkStatus(); - s.code = NetworkStatus.NOT_REACHABLE; - callback(s); - } - }, null, "Network Status", "isReachable", [uri]); + PhoneGap.execAsync(callback, null, "Network Status", "isReachable", [uri, isIpAddress]); }; PhoneGap.addConstructor(function() { diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index 506e8147..704139ed 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -24,6 +24,7 @@ import org.json.JSONObject; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; +import android.provider.ContactsContract; import android.provider.Contacts.ContactMethods; import android.provider.Contacts.ContactMethodsColumns; import android.provider.Contacts.Organizations; @@ -61,7 +62,12 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { boolean multiple = true; try { searchTerm = options.getString("filter"); - if (searchTerm.length()==0) searchTerm = "%"; + if (searchTerm.length()==0) { + searchTerm = "%"; + } + else { + searchTerm = "%" + searchTerm + "%"; + } multiple = options.getBoolean("multiple"); if (multiple) { limit = options.getInt("limit"); @@ -75,9 +81,15 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { JSONObject contact; ContentResolver cr = mApp.getContentResolver(); - Cursor cur = cr.query(People.CONTENT_URI, - null, null, null, null); + // Right now we are just querying the displayName + Cursor cur = cr.query(People.CONTENT_URI, + null, + People.DISPLAY_NAME + " LIKE ?", + new String[] {searchTerm}, + People.DISPLAY_NAME + " ASC"); + + int pos = 0; while (cur.moveToNext() && pos < limit) { contact = new JSONObject(); diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index f2a0ed96..ed49c5e5 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -63,19 +63,23 @@ public class ContactAccessorSdk5 extends ContactAccessor { boolean multiple = true; try { searchTerm = options.getString("filter"); - if (searchTerm.length()==0) searchTerm = "%"; + if (searchTerm.length()==0) { + searchTerm = "%"; + } + else { + searchTerm = "%" + searchTerm + "%"; + } multiple = options.getBoolean("multiple"); if (multiple) { limit = options.getInt("limit"); } - - System.out.println("Limit = " + limit); - System.out.println("Multiple = " + multiple); } catch (JSONException e) { Log.e(LOG_TAG, e.getMessage(), e); } // Get a cursor by creating the query. ContentResolver cr = mApp.getContentResolver(); + + // Right now we are just querying the displayName Cursor cursor = cr.query( ContactsContract.Contacts.CONTENT_URI, new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts.DISPLAY_NAME}, From c13c0c37e3e45074fc06ee44f6e49f3b5fb53d24 Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 28 Sep 2010 14:19:40 -0400 Subject: [PATCH 17/21] Only query what is required as passed by filter --- .../com/phonegap/ContactAccessorSdk3_4.java | 189 +++++++++++++-- .../src/com/phonegap/ContactAccessorSdk5.java | 224 ++++++++++++++++-- 2 files changed, 374 insertions(+), 39 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index 704139ed..b4803aeb 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -17,6 +17,12 @@ 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; @@ -24,6 +30,7 @@ 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.provider.Contacts.ContactMethods; import android.provider.Contacts.ContactMethodsColumns; @@ -48,6 +55,23 @@ import android.webkit.WebView; */ @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) { @@ -77,32 +101,51 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { } - JSONArray contacts = new JSONArray(); - JSONObject contact; - - ContentResolver cr = mApp.getContentResolver(); - - // Right now we are just querying the displayName - Cursor cur = cr.query(People.CONTENT_URI, - null, - People.DISPLAY_NAME + " LIKE ?", - new String[] {searchTerm}, - People.DISPLAY_NAME + " ASC"); - - - int pos = 0; - while (cur.moveToNext() && pos < limit) { - contact = new JSONObject(); - try { - String contactId = cur.getString(cur.getColumnIndex(People._ID)); - // name +// JSONArray contacts = new JSONArray(); +// JSONObject contact; +// +// ContentResolver cr = mApp.getContentResolver(); +// +// // Right now we are just querying the displayName +// Cursor cur = cr.query(People.CONTENT_URI, +// null, +// People.DISPLAY_NAME + " LIKE ?", +// new String[] {searchTerm}, +// People.DISPLAY_NAME + " ASC"); +// +// +// int pos = 0; +// while (cur.moveToNext() && pos < limit) { + // 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(); + try { + contactId = it.next(); contact.put("id", contactId); - contact.put("displayName", cur.getString(cur.getColumnIndex(People.DISPLAY_NAME))); + // 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 - if (Integer.parseInt(cur.getString(cur.getColumnIndex(People.PRIMARY_PHONE_ID))) > 0) { - contact.put("phoneNumbers", phoneQuery(cr, contactId)); - } + contact.put("phoneNumbers", phoneQuery(cr, contactId)); // email contact.put("emails", emailQuery(cr, contactId)); // addresses @@ -120,15 +163,113 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { // anniversary pos++; + cur.close(); } catch (JSONException e) { Log.e(LOG_TAG, e.getMessage(), e); } contacts.put(contact); } - cur.close(); 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()) { + Log.d(LOG_TAG, "ID = " + cursor.getString(cursor.getColumnIndex(projection))); + contactIds.add(cursor.getString(cursor.getColumnIndex(projection))); + } + cursor.close(); + } + private JSONArray imQuery(ContentResolver cr, String contactId) { String imWhere = ContactMethods.PERSON_ID + " = ? AND " + ContactMethods.KIND + " = ?"; diff --git a/framework/src/com/phonegap/ContactAccessorSdk5.java b/framework/src/com/phonegap/ContactAccessorSdk5.java index ed49c5e5..8cbcafb8 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk5.java +++ b/framework/src/com/phonegap/ContactAccessorSdk5.java @@ -17,6 +17,12 @@ 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; @@ -24,6 +30,7 @@ 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; @@ -49,8 +56,58 @@ import android.webkit.WebView; 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) + public ContactAccessorSdk5(WebView view, Activity app) { mApp = app; mView = view; @@ -79,26 +136,22 @@ public class ContactAccessorSdk5 extends ContactAccessor { // Get a cursor by creating the query. ContentResolver cr = mApp.getContentResolver(); - // Right now we are just querying the displayName - Cursor cursor = cr.query( - ContactsContract.Contacts.CONTENT_URI, - new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts.DISPLAY_NAME}, - ContactsContract.Contacts.DISPLAY_NAME + " LIKE ?", - new String[] {searchTerm}, - ContactsContract.Contacts.DISPLAY_NAME + " ASC"); + Set contactIds = buildSetOfContactIds(filter, searchTerm); + + Iterator it = contactIds.iterator(); + JSONArray contacts = new JSONArray(); JSONObject contact; + String contactId; int pos = 0; - while (cursor.moveToNext() && (pos < limit)) { + while (it.hasNext() && (pos < limit)) { contact = new JSONObject(); + contactId = it.next(); + Log.d(LOG_TAG, "Contact ID = " + contactId); - String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); - if (contactName.trim().length() == 0) continue; - - String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); try { contact.put("id", contactId); - contact.put("displayName", contactName); + contact.put("displayName", displayNameQuery(cr, contactId)); contact.put("name", nameQuery(cr, contactId)); contact.put("phoneNumbers", phoneQuery(cr, contactId)); contact.put("emails", emailQuery(cr, contactId)); @@ -118,9 +171,150 @@ public class ContactAccessorSdk5 extends ContactAccessor { contacts.put(contact); pos++; } - cursor.close(); 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()) { + Log.d(LOG_TAG, "ID = " + cursor.getString(cursor.getColumnIndex(projection))); + 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, From f85f4e6b69534d0315df921719fe7f246e2fe879 Mon Sep 17 00:00:00 2001 From: Bryce Curtis Date: Wed, 29 Sep 2010 11:10:08 -0500 Subject: [PATCH 18/21] Update notification service to implement plugin class. --- framework/assets/js/notification.js | 4 +- framework/src/com/phonegap/Device.java | 52 ------ framework/src/com/phonegap/DroidGap.java | 1 + framework/src/com/phonegap/Notification.java | 157 +++++++++++++++++++ 4 files changed, 160 insertions(+), 54 deletions(-) mode change 100644 => 100755 framework/src/com/phonegap/Device.java create mode 100755 framework/src/com/phonegap/Notification.java diff --git a/framework/assets/js/notification.js b/framework/assets/js/notification.js index e80c3e40..e78e9a5e 100644 --- a/framework/assets/js/notification.js +++ b/framework/assets/js/notification.js @@ -41,7 +41,7 @@ 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, "Device", "vibrate", [mills]); + PhoneGap.execAsync(null, null, "Notification", "vibrate", [mills]); }; /** @@ -51,7 +51,7 @@ Notification.prototype.vibrate = function(mills) { * @param {Integer} count The number of beeps. */ Notification.prototype.beep = function(count) { - PhoneGap.execAsync(null, null, "Device", "beep", [count]); + PhoneGap.execAsync(null, null, "Notification", "beep", [count]); }; // TODO: of course on Blackberry and Android there notifications in the UI as well 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); + } + +} From 7bfe94ffc7331e7b428b01a7dd8e8867716c9c4d Mon Sep 17 00:00:00 2001 From: macdonst Date: Wed, 29 Sep 2010 15:35:57 -0400 Subject: [PATCH 19/21] Removing commented out code --- .../com/phonegap/ContactAccessorSdk3_4.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index b4803aeb..dd6e2721 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -31,7 +31,6 @@ import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; -import android.provider.ContactsContract; import android.provider.Contacts.ContactMethods; import android.provider.Contacts.ContactMethodsColumns; import android.provider.Contacts.Organizations; @@ -100,23 +99,6 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { Log.e(LOG_TAG, e.getMessage(), e); } - -// JSONArray contacts = new JSONArray(); -// JSONObject contact; -// -// ContentResolver cr = mApp.getContentResolver(); -// -// // Right now we are just querying the displayName -// Cursor cur = cr.query(People.CONTENT_URI, -// null, -// People.DISPLAY_NAME + " LIKE ?", -// new String[] {searchTerm}, -// People.DISPLAY_NAME + " ASC"); -// -// -// int pos = 0; -// while (cur.moveToNext() && pos < limit) { - // Get a cursor by creating the query. ContentResolver cr = mApp.getContentResolver(); Set contactIds = buildSetOfContactIds(filter, searchTerm); From c2240966efdc2be031d6cb66c6664b1920b653ec Mon Sep 17 00:00:00 2001 From: macdonst Date: Thu, 30 Sep 2010 05:43:00 +0800 Subject: [PATCH 20/21] Removing extra log calls --- example/index.html | 2 +- .../src/com/phonegap/ContactAccessorSdk3_4.java | 8 -------- framework/src/com/phonegap/ContactAccessorSdk5.java | 13 ------------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/example/index.html b/example/index.html index 745856ce..bdfee7c3 100644 --- a/example/index.html +++ b/example/index.html @@ -104,7 +104,7 @@ var obj = new ContactFindOptions(); obj.filter=""; obj.multiple=true; - navigator.service.contacts.find(["name", "phone", "email"], count_contacts, fail, obj); + navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], count_contacts, fail, obj); } function count_contacts(contacts) diff --git a/framework/src/com/phonegap/ContactAccessorSdk3_4.java b/framework/src/com/phonegap/ContactAccessorSdk3_4.java index dd6e2721..086e1052 100644 --- a/framework/src/com/phonegap/ContactAccessorSdk3_4.java +++ b/framework/src/com/phonegap/ContactAccessorSdk3_4.java @@ -162,7 +162,6 @@ public class ContactAccessorSdk3_4 extends ContactAccessor { for (int i=0; i