phoneNumberLookup(Context context, String number) {
//Log.e("PhoneNumberLookup", number);
@@ -111,5 +122,289 @@
try { output.close(); } catch(Exception ignored) { };
}
}
+
+ /**
+ * Return all the NAME_RAW_CONTACT_IDS which contribute an entry to a Contact in the database
+ *
+ * If the user has, for example, joined several contacts, on the phone, the IDs returned will
+ * be representative of the joined contact
+ *
+ * See here: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html
+ * for more information about the connection between contacts and raw contacts
+ *
+ * @param context android.content.Context running the request
+ * @return List of each NAME_RAW_CONTACT_ID in the Contacts database
+ */
+ public static List getAllContactRawContactIDs(Context context) {
+ ArrayList toReturn = new ArrayList();
+
+ // Define the columns we want to read from the Contacts database
+ final String[] projection = new String[]{
+ ContactsContract.Contacts.NAME_RAW_CONTACT_ID
+ };
+
+ Uri contactsUri = ContactsContract.Contacts.CONTENT_URI;
+ Cursor contactsCursor = context.getContentResolver().query(
+ contactsUri,
+ projection,
+ null, null, null);
+ if (contactsCursor != null && contactsCursor.moveToFirst()) {
+ do {
+ Long contactID;
+
+ int idIndex = contactsCursor.getColumnIndex(ContactsContract.Contacts.NAME_RAW_CONTACT_ID);
+ if (idIndex != -1) {
+ contactID = contactsCursor.getLong(idIndex);
+ } else {
+ // Something went wrong with this contact
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a contact which does not have a NAME_RAW_CONTACT_ID");
+ continue;
+ }
+
+ toReturn.add(contactID);
+ } while (contactsCursor.moveToNext());
+ try {
+ contactsCursor.close();
+ } catch (Exception e) {
+ }
+ }
+
+ return toReturn;
+ }
+
+ /**
+ * Return a mapping of raw contact IDs to a map of the requested data from the Contacts database
+ *
+ * If for some reason there is no row associated with the raw contact ID in the database,
+ * there will not be a corresponding field in the returned map
+ *
+ * @param context android.content.Context running the request
+ * @param IDs collection of raw contact IDs to look up
+ * @param contactsProjection List of column names to extract, defined in ContactsContract.Contacts
+ * @return mapping of raw contact IDs to desired values, which are a mapping of column names to the data contained there
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB) // Needed for Cursor.getType(..)
+ public static Map> getColumnsFromContactsForRawContactIDs(Context context, Set IDs, String[] contactsProjection) {
+ HashMap> toReturn = new HashMap<>();
+
+ // Define the columns we want to read from the RawContacts database
+ final String[] rawContactsProjection = new String[]{
+ ContactsContract.RawContacts._ID,
+ ContactsContract.RawContacts.CONTACT_ID
+ };
+
+ Uri rawContactsUri = ContactsContract.RawContacts.CONTENT_URI;
+ Uri contactsUri = ContactsContract.Contacts.CONTENT_URI;
+
+ Cursor rawContactsCursor = context.getContentResolver().query(
+ rawContactsUri,
+ rawContactsProjection,
+ null,
+ null,
+ null);
+
+ if (rawContactsCursor != null && rawContactsCursor.moveToFirst()) {
+ do {
+ Long rawContactID;
+ Long contactID;
+
+ int rawContactIDIndex = rawContactsCursor.getColumnIndex(ContactsContract.RawContacts._ID);
+ if (rawContactIDIndex != -1) {
+ rawContactID = rawContactsCursor.getLong(rawContactIDIndex);
+ } else {
+ // This raw contact didn't have an ID? Something is very wrong.
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a raw contact which does not have an _ID");
+ continue;
+ }
+
+ // Filter only for the rawContactIDs we were asked to look up
+ if (!IDs.contains(rawContactID)) {
+ // This should be achievable (and faster) by providing a selection
+ // and selectionArgs when fetching rawContactsCursor, but I can't
+ // figure that out
+ continue;
+ }
+
+ int contactIDIndex = rawContactsCursor.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID);
+ if (contactIDIndex != -1) {
+ contactID = rawContactsCursor.getLong(contactIDIndex);
+ } else {
+ // Something went wrong with this contact
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a raw contact which does not have a CONTACT_ID");
+ continue;
+ }
+
+ // Filter on only the contact we are interested in
+ final String contactsSelection = ContactsContract.Contacts._ID + " == ? ";
+ final String[] contactsArgs = new String[]{contactID.toString()};
+
+ Cursor contactsCursor = context.getContentResolver().query(
+ contactsUri,
+ contactsProjection,
+ contactsSelection,
+ contactsArgs, null
+ );
+
+ Map requestedData = new HashMap<>();
+
+ if (contactsCursor != null && contactsCursor.moveToFirst()) {
+ // For each column, collect the data from that column
+ for (String column : contactsProjection) {
+ int index = contactsCursor.getColumnIndex(column);
+ // Since we might be getting various kinds of data, Object is the best we can do
+ Object data;
+ int type;
+ if (index == -1) {
+ // This raw contact didn't have an ID? Something is very wrong.
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a raw contact which does not have an _ID");
+ continue;
+ }
+
+ type = contactsCursor.getType(index);
+ switch (type) {
+ case Cursor.FIELD_TYPE_INTEGER:
+ data = contactsCursor.getInt(index);
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ data = contactsCursor.getFloat(index);
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ data = contactsCursor.getString(index);
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ data = contactsCursor.getBlob(index);
+ break;
+ default:
+ Log.e("ContactsHelper", "Got an undefined type of column " + column);
+ continue;
+ }
+
+ requestedData.put(column, data);
+ }
+ }
+ contactsCursor.close();
+
+ toReturn.put(rawContactID, requestedData);
+ } while (rawContactsCursor.moveToNext());
+ rawContactsCursor.close();
+ }
+
+ return toReturn;
+ }
+
+ /**
+ * Return a mapping of raw contact IDs to a map of the requested data from the Data database
+ *
+ * If for some reason there is no row associated with the raw contact ID in the database,
+ * there will not be a corresponding field in the returned map
+ *
+ * For some types of data, there may be many entries in the Data database with the same raw contact ID,
+ * so a list of the relevant data is returned
+ *
+ * @param context android.content.Context running the request
+ * @param IDs collection of raw contact IDs to look up
+ * @param dataMimetype Mimetype of the column to look up, defined in ContactsContract.CommonDataKinds..CONTENT_ITEM_TYPE
+ * @param dataProjection List of column names to extract, defined in ContactsContract.CommonDataKinds.
+ * @return mapping of raw contact IDs to desired values, which are a mapping of column names to the data contained there
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB) // Needed for Cursor.getType(..)
+ public static Map>> getColumnsFromDataForRawContactIDs(Context context, Set IDs, String dataMimetype, String[] dataProjection) {
+ HashMap>> toReturn = new HashMap<>();
+
+ // Define a filter for the type of data we were asked to get
+ final String dataSelection = ContactsContract.Data.MIMETYPE + " == ?";
+ final String[] dataSelectionArgs = {dataMimetype};
+
+ Uri dataUri = ContactsContract.Data.CONTENT_URI;
+
+ // Regardless of what the user requested, we need the RAW_CONTACT_ID field
+ // This will not be returned to the user if it wasn't asked for
+ Set actualDataProjectionSet = new HashSet();
+ actualDataProjectionSet.addAll(Arrays.asList(dataProjection));
+ actualDataProjectionSet.add(ContactsContract.Data.RAW_CONTACT_ID);
+
+ String[] actualDataProjection = new String[0];
+ actualDataProjection = actualDataProjectionSet.toArray(actualDataProjection);
+
+ Cursor dataCursor = context.getContentResolver().query(
+ dataUri,
+ actualDataProjection,
+ dataSelection,
+ dataSelectionArgs,
+ null);
+
+ if (dataCursor != null && dataCursor.moveToFirst()) {
+ do {
+ Long rawContactID;
+
+ Map requestedData = new HashMap<>();
+
+ int rawContactIDIndex = dataCursor.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID);
+ if (rawContactIDIndex != -1) {
+ rawContactID = dataCursor.getLong(rawContactIDIndex);
+ } else {
+ // This didn't have a RAW_CONTACT_ID? Something is very wrong.
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a data contact which does not have a RAW_CONTACT_ID");
+ continue;
+ }
+
+ // Filter only for the rawContactIDs we were asked to look up
+ if (!IDs.contains(rawContactID)) {
+ // This should be achievable (and faster) by providing a selection
+ // and selectionArgs when fetching dataCursor, but I can't
+ // figure that out
+ continue;
+ }
+ // For each column, collect the data from that column
+ for (String column : dataProjection) {
+ int index = dataCursor.getColumnIndex(column);
+ // Since we might be getting various kinds of data, Object is the best we can do
+ Object data;
+ int type;
+ if (index == -1) {
+ // This raw contact didn't have an ID? Something is very wrong.
+ // TODO: Investigate why this would happen
+ Log.e("ContactsHelper", "Got a raw contact which does not have an _ID");
+ continue;
+ }
+
+ type = dataCursor.getType(index);
+ switch (type) {
+ case Cursor.FIELD_TYPE_INTEGER:
+ data = dataCursor.getInt(index);
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ data = dataCursor.getFloat(index);
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ data = dataCursor.getString(index);
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ data = dataCursor.getBlob(index);
+ break;
+ default:
+ Log.w("ContactsHelper", "Got an undefined type of column " + column + " -- Skipping");
+ continue;
+ }
+
+ requestedData.put(column, data);
+ }
+
+ // If we have not already stored some data for this contact, make a new list
+ if (!toReturn.containsKey(rawContactID)) {
+ toReturn.put(rawContactID, new ArrayList