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);
Related
I am trying to get first name and last name in contact book by phone number.
Here is my code:
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cResolver.query(uri, null, null, null, null);
if(cursor != null && cursor.moveToFirst()) {
int idColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);
int firstNameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
int lastNameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
while (!cursor.isAfterLast()) {
long id = cursor.getLong(idColumnIndex);
contact = new MyContact();
contact.setId(id);
contact.setFirstName(cursor.getString(firstNameIndex));
contact.setLastName(cursor.getString(lastNameIndex));
}
cursor.close();
}
But firstNameIndex and lastNameIndex is always -1. What I am doing wrong ? Please help me.
PhoneLookup is a nice and quick way to get contact data by a phone number, but it returns a cursor limited to the columns mentioned in the docs.
You can see there's DISPLAY_NAME you can access, but not GIVEN_NAME, FAMILY_NAME.
GIVEN_NAME & FAMILY_NAME are fields stored in the Data table, which means you need to query that table separately to get to those fields.
So, you can just add another query using the contact ID you got from PhoneLookup (note that for each looked up phone there might be multiple contacts returned).
Here's a sample method to get first/last names from contact ID:
private void addNames(MyContact contact, long contactId) {
String[] projection = new String[] {StructuredName.GIVEN_NAME, StructuredName.FAMILY_NAME};
// filter to just StructuredName rows from the data table for the given contact
String selection = Data.CONTACT_ID + "=" + contactID + " AND " + Data.MIMETYPE + "=" + StructuredName.CONTENT_ITEM_TYPE;
Cursor cursor = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);
if (cursor.next()) {
contact.setFirstName(cursor.getString(0));
contact.setLastName(cursor.getString(1));
}
cursor.close();
}
I'm trying to get the information of my contacts using ContactsContract and what I need to do, is to get only the first name of the contact. I used ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME but this get the name and the last name too, and I only want the name.
I tried using ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME but instead of getting the name, this get a number.
I have not found an exact way to get only the first name of the contact. Any idea?
You haven't shared your code, but it sounds like you're querying over table Phone.CONTENT_URI and trying to get a field via StructuredName.GIVEN_NAME.
That's not possible, as Phone.CONTENT_URI will only return phone rows, not StructuredName rows.
Here's code snippet to get all given-names from the Contacts DB:
String[] projection = new String[]{StructuredName.CONTACT_ID, StructuredName.GIVEN_NAME};
String selection = Data.MIMETYPE + "='" + StructuredName.CONTENT_ITEM_TYPE + "'";
Cursor c = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);
DatabaseUtils.dumpCursor(c);
c.close();
UPDATE
Here's some sample code on how to query for multiple mimetypes in a single query.
In this example I created a mapping from to <given-name, phone> for each contact in the DB:
Map<Long, List<String>> contacts = new HashMap<Long, List<String>>();
String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, StructuredName.GIVEN_NAME, Phone.NUMBER };
// select all rows of type "name" or "phone"
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "', '" + StructuredName.CONTENT_ITEM_TYPE + "')";
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);
while (cur != null && cur.moveToNext()) {
long id = cur.getLong(0);
String name = cur.getString(1);
String mime = cur.getString(2); // type of row: phone / name
// get the existing <Given-name, Phone> list from the Map, or create a new one
List<String> infos;
if (contacts.containsKey(id)) {
infos = contacts.get(id);
} else {
infos = new ArrayList<String>(2);
contacts.put(id, infos);
}
// add either given-name or phone to the infos list
switch (mime) {
case Phone.CONTENT_ITEM_TYPE:
infos.set(1, cur.getString(4));
break;
case StructuredName.CONTENT_ITEM_TYPE:
infos.set(0, cur.getString(3));
break;
}
}
i am create an application which use contact to display. My problem is that i can show all conacts (from my email accounts,skype and other), but i want show only contacts from my device (with images like i am getting now), like when open native contacts app and go to Contacts->Menu->Settings->Contacts->Contact to display->Device contacts. I am not very well understand Contact content provider and need a help. There a lot of posts on stackoverflow, bu t i cant find post for my requirements.
For retreive all contact i am using this CursorLoader
CursorLoader cL = new CursorLoader(getActivity(),
contentUri,
ContactsQuery.PROJECTION,
ContactsQuery.SELECTION,
null,
ContactsQuery.SORT_ORDER
);
This is my criteria and projections:
final static int QUERY_ID = 1;
// A content URI for the Contacts table
final static Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
// The search/filter query Uri
final static Uri FILTER_URI = ContactsContract.Contacts.CONTENT_FILTER_URI;
// The selection clause for the CursorLoader query. The search criteria defined here
// restrict results to contacts that have a display name and are linked to visible groups.
// Notice that the search on the string provided by the user is implemented by appending
// the search string to CONTENT_FILTER_URI.
#SuppressLint("InlinedApi")
final static String SELECTION =
(Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME) +
"<>''" + " AND " + ContactsContract.Contacts.IN_VISIBLE_GROUP + "= 1 AND "+ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
// The desired sort order for the returned Cursor. In Android 3.0 and later, the primary
// sort key allows for localization. In earlier versions. use the display name as the sort
// key.
#SuppressLint("InlinedApi")
final static String SORT_ORDER =
Utils.hasHoneycomb() ? ContactsContract.Contacts.SORT_KEY_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME;
// The projection for the CursorLoader query. This is a list of columns that the Contacts
// Provider should return in the Cursor.
#SuppressLint("InlinedApi")
final static String[] PROJECTION = {
// The contact's row id
ContactsContract.Contacts._ID,
// A pointer to the contact that is guaranteed to be more permanent than _ID. Given
// a contact's current _ID value and LOOKUP_KEY, the Contacts Provider can generate
// a "permanent" contact URI.
ContactsContract.Contacts.LOOKUP_KEY,
// In platform version 3.0 and later, the Contacts table contains
// DISPLAY_NAME_PRIMARY, which either contains the contact's displayable name or
// some other useful identifier such as an email address. This column isn't
// available in earlier versions of Android, so you must use Contacts.DISPLAY_NAME
// instead.
Utils.hasHoneycomb() ? ContactsContract.Contacts.DISPLAY_NAME_PRIMARY : ContactsContract.Contacts.DISPLAY_NAME,
// In Android 3.0 and later, the thumbnail image is pointed to by
// PHOTO_THUMBNAIL_URI. In earlier versions, there is no direct pointer; instead,
// you generate the pointer from the contact's ID value and constants defined in
// android.provider.ContactsContract.Contacts.
Utils.hasHoneycomb() ? ContactsContract.Contacts.PHOTO_THUMBNAIL_URI : ContactsContract.Contacts._ID,
// The sort order column for the returned Cursor, used by the AlphabetIndexer
SORT_ORDER,
ContactsContract.Contacts.HAS_PHONE_NUMBER
};
After some time , i am return to search answer to thisquestion.
the answer maybe is not correct byt it helps me.
public static boolean getConnections(Context context, String contactId) {
// Read all data for contactId
String selection = ContactsContract.RawContacts.CONTACT_ID + " = ?";
String[] selectionArgs = new String[]{contactId};
Cursor c = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, selection, selectionArgs, null);
String accountType = null;
while (c.moveToNext()) {
accountType = c.getString(c.getColumnIndexOrThrow(ContactsContract.RawContacts.ACCOUNT_TYPE));
}
Log.e("getConnections", accountType + "");
c.close();
if (accountType.equals("SIM Account") || accountType.equals("vnd.sec.contact.phone"))
return true;
else
return false;
}
After my query posted in question i am filter contacts by contactId and check their ACCOUNT_TYPE , in my logs i see on samsung vnd.sec.contact.phone(means that is phone contact) and on my lg with 2 sim i found this SIM Account.
Perhaps there is better solution, but i figure it out this way.
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'm able to fetch all the contacts from Contact list in android(phone numbers and emails)
but fetching all of them takes long time.
To speed up this I have stored them once in my application. But now i can't get the updated contacts. How does they need to be synced with my application?
Problem arises when I try to display them in a list because a user database of phone numbers and emails exceeds the 2000. I'm currently using base adapter implementation for this.
Can somebody help me out for large contact database?
Application like GroupMe n Viber show all user contacts very fast can somebody tell me brief explanation to achieve it.
String KEY_NAME = "Name";
String KEY_NO = "No";
String selection = ContactsContract.CommonDataKinds.Phone.IN_VISIBLE_GROUP + " = 1";
String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
String data="";
String name="";
ContactEntry contactObj;
String id;
String index="";
final String[] projection = new String[]{ContactsContract.Contacts._ID , ContactsContract.Contacts.DISPLAY_NAME , ContactsContract.Contacts.HAS_PHONE_NUMBER};
final String[] email_projection = new String[] {ContactsContract.CommonDataKinds.Email.DATA , ContactsContract.CommonDataKinds.Email.TYPE};
final String[] phone_projection = new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.TYPE};
ContentResolver cr = context.getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI , projection , selection , null , sortOrder);
if(cur.getCount()>0){
while(cur.moveToNext()){
id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
// get the phone number
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI , phone_projection ,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",new String[]{id}, null);
while (pCur.moveToNext()){
data = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
if(!temp.contains(data) && !data.equals(null)){
//Adding PhoneNumbers in List
}
}
pCur.close();
}
Cursor emailCur = cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, email_projection,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{id}, null);
while (emailCur.moveToNext()){
data = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
if(!temp.contains(data) && !data.equals(null)){
//Adding Email in List
}
}
emailCur.close();
}
}
I have used the above code
How can i pass the Curser in CurosrAdaper for all Emails and Phonenumbers.
please help me i havn't found any solution.
Android provides a sync adapter to solve this problem. you may refer to this example for the implementation.
http://developer.android.com/resources/samples/SampleSyncAdapter/index.html
i had same issue , i have used ResourceCursorAdapter which fetches contacts as fast as Contact API from android....
I think you need to have a service (or) Asynch task something like that which periodically updates contacts from phone to your local app. Otherwise you can't synch.