I have to read contacts from device which are having valid phone numbers. For that right now I'm using following query.
final Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
final String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '" + ("1") + "' AND LENGTH(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ") >= 10";
final String[] projection = null;
final String[] selectionArgs = null;
final String sortOrder = "upper(" + ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID + ") ASC";
Cursor phones = mContentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder);
As you can see in selection , im querying for entries with HAS_PHONE_NUMBER = 1 and length of phone number >= 10 , to avoid maximum junk contacts while retrieving from itself. It works fine , but the problem is , the saved phone numbers might have special characters like - , ( , )or a space etc.
Like +9191-91-22-22-55 , +9191-91-(22 22-55) . I need to get this string without non-digits and without country code (last 10 numbers).
For example : +9190-91-22-22-55 as 9091222255
is there any way to retrieve a string field as formatted like this in SQLite? Or is there any effective way to fulfill my requirement? Thanks in advance..
Related
I've been working on a block of code to let the user search (character by character using an AutoCompleteTextView) contacts by name, email or phone number. I've worked out the below code:
// General contact data, so we have to get the DATA1 attribute and use MIMETYPE
// to figure out what it is. Usually we'd query, say, ContactsContract.CommonDataKinds.Email.CONTENT_URI
Uri uri = ContactsContract.Data.CONTENT_URI;
// Limit the query results to only the columns we need for faster operations.
// Using a projection also seems to make the query DISTINCT
String[] projection = new String[] {ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Data.DATA1,
ContactsContract.Data.MIMETYPE};
// Find contact records with an email address or phone number
// Search the name and data1 field (which may contain an email or phone number)
// for user-entered search phrase
String filter = "(" + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=?)"
+ " AND (" + ContactsContract.Data.DATA1 + " LIKE ? OR " + ContactsContract.Data.DISPLAY_NAME + " LIKE ?)";
String wildcardedConstraint = "%" + constraintString + "%";
String[] filterParams = new String[]{ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, wildcardedConstraint, wildcardedConstraint};
// Sort contacts with the most recently contacted ones first. That's often 0 (unset)
// so do a sub-sort by last updated date, most recent contacts first
String orderBy = ContactsContract.Contacts.LAST_TIME_CONTACTED + " DESC, " + ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " DESC";
Cursor cursor = getContext().getContentResolver().query(uri, projection, filter, filterParams, orderBy);
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
String data1 = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DATA1));
String mimetype = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE));
String number = null;
String email = null;
if (mimetype.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
email = data1;
} else if (mimetype.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
number = data1;
}
items.add(new Person(name, number, email));
Log.e("temp", name + " " + data1 + " " + mimetype);
}
cursor.close();
}
There is a problem with the phone number search, however. In contacts, phone numbers are in many different formats:
+101234567890
(123) 456-7890
1234567890
123-456-7890
And so on.
How can I adapt my Contacts query filter so the user's input will find phone numbers in any format--preferably without making the entire query extremely slow?
Some solutions I've found rely on editing table data to standardize the phone numbers, which isn't an option with contacts. Maybe that normalized number field would work... if I could find a way to easily build it into this query on the Contacts Data table. I know I could do extra phone number searches for each record, or use Java to make the checks, but I think that would make it very slow. Perhaps a regexp SQL operator in the query--but I don't know how I could make it work for the user's character-by-character search where they may have only entered part of the phone number.
Any ideas?
You can do this with Android's built-in SQLite function PHONE_NUMBERS_EQUAL, which compares two numbers and will return 1 if they're identical enough for caller ID purposes.
You simply need to change your filter as follows:
String filter = "(" + ContactsContract.Data.MIMETYPE + "=? OR "
+ ContactsContract.Data.MIMETYPE + "=?) AND "
+ "(PHONE_NUMBERS_EQUAL(" + ContactsContract.Data.DATA1 + ", ?, 0) OR "
+ ContactsContract.Data.DATA1 + " LIKE ? OR "
+ ContactsContract.Data.DISPLAY_NAME + " LIKE ?)";
And add another wildcardedConstraint to your filterParams:
String[] filterParams = new String[] { ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
wildcardedConstraint,
wildcardedConstraint,
wildcardedConstraint };
The final INTEGER parameter in the PHONE_NUMBERS_EQUAL function indicates whether to use strict number comparation; 1 meaning do use strict, 0 meaning non-strict. Apparently this is a system-wide setting that can be retrieved from the system Resources, but I am uncertain as to what factors dictate how this is determined for a particular environment. The example above just uses non-strict comparation. However, if it is a concern, the actual resource value can be obtained like so:
private static final String STRICT_COMPARE = "config_use_strict_phone_number_comparation";
...
int strictResId = Resources.getSystem().getIdentifier(STRICT_COMPARE, "bool", "android");
boolean useStrict = Resources.getSystem().getBoolean(strictResId);
I have created a getContentResolver().query using the follwing
uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String projection[] = { android.provider.MediaStore.Audio.Media.DATA,
android.provider.MediaStore.Audio.Media.TITLE,
android.provider.MediaStore.Audio.Media.ARTIST,
android.provider.MediaStore.Audio.Media.ALBUM,
android.provider.MediaStore.Audio.Media.COMPOSER,
android.provider.MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media._ID,
android.provider.MediaStore.Audio.Media.ALBUM_ID };
String selection1 = MediaStore.Audio.Media._ID + "=?" ;
String[] selectionArgs = new String[] {"" + 19};
cursor = this.getContentResolver().query(uri, projection,
selection1, selectionArgs, null);
songs = new ArrayList<String>();
while (cursor.moveToNext()) {
songs.add(cursor.getString(1));
This works perfectly fine for selecting single song , however when I try to select multiple songs using
String selection1 = MediaStore.Audio.Media._ID + "IN(?,?)";
String[] selectionArgs = new String[] {"" + 12,"" + 19};
This query fails .
Is there a proper way to select multiple songs , what is wrong with the above query.
please explain the changes needed to be made.
I don't see anything wrong with your query using the IN operator. I suspect the query with IN has quirks and limitations. I did not use it however. Try just using the OR operator instead.
Example:
String selection1 = MediaStore.Audio.Media._ID + "=12" + " OR " + MediaStore.Audio.Media._ID + "=19";
And of course not use selectionArgs as the parameter.
Another good try is using raw query instead, documentation # SQL rawQuery. With a raw query, you can use the IN operator, and I think it's a good idea for simplifying queries. I should use it next time.
Thanks for this question!
I'm having a problem retrieving all phone contacts.
when using the following selection clause, I'm not getting contacts that not been saved in association to group (such google specific account group):
final static String SELECTION = (Utils.hasHoneycomb()
? Contacts.DISPLAY_NAME_PRIMARY
: Contacts.DISPLAY_NAME) + "<>''" + " AND " + Contacts.IN_VISIBLE_GROUP + "=1";
...
...
// onCreateLoader() code:
return new CursorLoader(getActivity(), Contacts.CONTENT_URI, ContactsQuery.PROJECTION,
ContactsQuery.SELECTION, null, ContactsQuery.SORT_ORDER);
got this snippet from one of the Google tutorials or demo projects.
following the documentation, I realized that Contacts.IN_VISIBLE_GROUP + "=1" causing the filtering of contacts that not belong to any group, so I simply removed this condition expecting to get also the contacts that don't belongs to any group:
final static String SELECTION = (Utils.hasHoneycomb()
? Contacts.DISPLAY_NAME_PRIMARY
: Contacts.DISPLAY_NAME) + "<>''";
after using this SELECTION clause - I got all the contacts includes the ones that not belongs to any group, but now I got duplication of all the contacts that does belongs to a group.
please help me understand how to perform query that returns all contacts without duplication
Thanks in advance
Uri contactUri = data.getData();
String[] projection = {ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.Contacts.DISPLAY_NAME};
Cursor cursor = activity.getContentResolver()
.query(contactUri, projection, null, null, null);
cursor.moveToFirst();
int column = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
String number = cursor.getString(column);
int column1 = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
String name = cursor.getString(column1);
I'm attempting to retrieve both email and phone via a single cursor described below. I'm using the Email.CONTENT_URI, hence I don't retrieve the phone number, so my phoneColumn is returning email. I tried using Phone.CONTENT_URI but it only returns a smaller subset of contacts (possibly because it only fetches ones that have phone numbers). Is there a way to get both email and phone with a specific Uri or how can I do it with two cursors?
Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
projection, null, null, order);
int idColumn = cursor.getColumnIndex(ContactsContract.Data._ID);
int nameColumn = cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
int emailColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
int phoneColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA);
where projection is:
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Email.DATA,
ContactsContract.CommonDataKinds.Phone.DATA, }
Please have a look here. You should find all the necessary examples for such kind of querying.
For an example, you can fetch all information of a contactId in this way:
Cursor data = context.getContentResolver().query(
Data.CONTENT_URI, new String[] { Data._ID,Data.MIMETYPE,
Email.ADDRESS, Photo.PHOTO},Data.CONTACT_ID
+ "=?" + " AND " + "(" + Data.MIMETYPE + "='"
+ Photo.CONTENT_ITEM_TYPE + "' OR " + Data.MIMETYPE
+ "='" + Email.CONTENT_ITEM_TYPE +"')",
new String[] {String.valueOf(contactId)}, null);
You can fetch info for all contacts in this way and then probably sort it according to your criteria. You can build queries like this based on your need.
I have created this library to solve all your queries. It will only save contacts with at least one email or phone number. Also it will remove duplicates from emails and phone numbers from same contacts (created by 3rd party apps like whatsapp).
Please have a look at it.
Link : https://github.com/raghavsatyadev/ContactFetcher/
I have a string content//com.android.contacts/contacts/contacts/2 ie aft the user has selected a particular number.
From this string, how do i get the phone number of this particular contact?
I am new to android environment, so my question might seem a bit primitive.
Cursor c = (Cursor)mAdapter.getItem(a.keyAt(i));
Long id = c.getLong(c.getColumnIndex(ContactsContract.Contacts._ID));
contacts.add(ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id));
chosenContacts = sb.toString();
chosenContacts is my string and that contains content//com.android.contacts/contacts/contacts/2
You need a second request. You can use the id of your snippet for it:
Cursor phoneNoCursor = contentResolver.query(
Data.CONTENT_URI,
new String[] {Phone.NUMBER, Phone.TYPE, Phone.LABEL},
Data.MIMETYPE + " = ? AND " + Data.CONTACT_ID + " = ? ",
new String[] {String.valueOf(Phone.CONTENT_ITEM_TYPE, id)},
null);
For the list of possible types see the description of the Phone class. But maybe the number itself and its label are enough anyway.