Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read contacts on Android 2.0

I'm working on Android 2.0 and am trying to receive a list of all contacts.

Since android.provider.Contacts.People is deprecated, I have to use android.provider.ContactsContract, But I can't find a proper example of how to use it (ex: retrieve a list of all contacts on the phonebook).

Anyone knows where to find such an example?

like image 264
appme up Avatar asked Nov 12 '09 10:11

appme up


People also ask

What is ContactsContract?

ContactsContract defines an extensible database of contact-related information. Contact information is stored in a three-tier data model: A row in the Data table can store any kind of personal data, such as a phone number or email addresses. The set of data kinds that can be stored in this table is open-ended.


4 Answers

First, ensure that you have added

<uses-permission android:name="android.permission.READ_CONTACTS"/> 

to your AndroidManifest.xml file, then you can loop through your phone contacts like this:

Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);  while (cursor.moveToNext()) {     String contactId = cursor.getString(cursor.getColumnIndex(     ContactsContract.Contacts._ID));     String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));     if (Boolean.parseBoolean(hasPhone)) {        // You know it has a number so now query it like this       Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null);        while (phones.moveToNext()) {           String phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));                        }        phones.close();     }     Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null);     while (emails.moveToNext()) {        // This would allow you get several email addresses        String emailAddress = emails.getString(        emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));     }     emails.close(); } cursor.close();  

Additionally, you can loop through your contacts and simply get the name and phone number like this:

Cursor people = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);  while(people.moveToNext()) {    int nameFieldColumnIndex = people.getColumnIndex(PhoneLookup.DISPLAY_NAME);    String contact = people.getString(nameFieldColumnIndex);    int numberFieldColumnIndex = people.getColumnIndex(PhoneLookup.NUMBER);    String number = people.getString(numberFieldColumnIndex); }  people.close(); 

Furthermore, if you need to get things like notes from a contact then you will need to use a different URI, like the following (feel free to use this method):

private String getNote(long contactId) {     String note = null;     String[] columns = new String[] { ContactsContract.CommonDataKinds.Note.NOTE };     String where = ContactsContract.Data.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";     String[] whereParameters = new String[]{Long.toString(contactId), ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE};     Cursor contacts = getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, where, whereParameters, null);     if (contacts.moveToFirst()) {        rv = contacts.getString(0);     }     contacts.close();     return note;  }  

Notice this time I used not only the contact id but the mime type for the query.

like image 185
7 revs, 6 users 67% Avatar answered Sep 22 '22 23:09

7 revs, 6 users 67%


Great to see some useful info, it is frustrating how poorly this important topic is covered by docs and such. After too much hacking about I thought I would share a little code also. The following code is a little prettier and get the same thing done more efficiently.

Uri contactUri = ContactsContract.Contacts.CONTENT_URI;      String[] PROJECTION = new String[] {              ContactsContract.Contacts._ID,              ContactsContract.Contacts.DISPLAY_NAME,              ContactsContract.Contacts.HAS_PHONE_NUMBER,      };  String SELECTION = ContactsContract.Contacts.HAS_PHONE_NUMBER + "='1'";  Cursor contacts = managedQuery(contactUri, PROJECTION, SELECTION, null, null ); 

The above chunk of code returns a Cursor that points to the resulting query that only contains those rows that have a phone number. This is nice since you typically have many contacts without numbers. Furthermore, the PROJECTION limits the amount of data that is returned.

String key, value, phoneNumber;   Hashtable contactPhoneInfo = new Hashtable<String, String>();  Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;   String [] PHONES_PROJECTION = new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER };  String PHONE_SELECTION = null;           contacts.moveToFirst();          do{           long contactId = contacts.getLong(idColumnIndex);            PHONE_SELECTION = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId;            Cursor phones = managedQuery(phoneUri,            PHONES_PROJECTION,            null,             null,                     ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY + " DESC");            phones.moveToFirst();            key = phones.getString(0).replaceAll("\\D", "");           value = contacts.getString(nameColumnIndex);            contactPhoneInfo.put(key, value);           }while(contacts.moveToNext());           contacts.close();  } 

The above chunk gets the phone number associated with each contact id that has a phone number. I store all the info in a hash table and with a key value of the phone number. I stripped the phone number of all none digit info also. For some reason even though ContactsContract.CommonDataKinds.Phone.HAS_PHONE_NUMBER is valid if you include that in the projection argument it breaks the query, I don't know why and it is frustrating that it does.

The second part of the code above is too slow, all the query calls just bog everything down. The following code is much faster. Just grab all the rows for the phone content and use the contact_ids to sort the data you want.

Cursor phones = managedQuery(phoneUri,                 PHONES_PROJECTION,                 PHONE_SELECTION,                  null,                 ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY + " DESC");  contacts.moveToFirst();          do{              value = "";               key = contacts.getString(idColumnIndex);               contactPhoneInfo.put(key, value);          }while(contacts.moveToNext());  phones.moveToFirst();          Set keySet = contactPhoneInfo.keySet();           idColumnIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);          int numColumnIndex = phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);           do{              key = phones.getString(idColumnIndex);                if(keySet.contains(key)){                  value = phones.getString(numColumnIndex).replaceAll("\\D", "");                   contactPhoneInfo.put(key, value);               }           }while(phones.moveToNext());  

You end up with a hashtable with all the info you want in it. Of course you could put whatever info you want into the data structure. The second way of doing it is much much faster.

like image 43
thisnamagain Avatar answered Sep 26 '22 23:09

thisnamagain


Just want to add, when you are retrieving the contacts you might get a lot of "garbage" contacts - for example some email addresses that a user has at some point send an email to, but are not aggregated... If you want only the contacts visible to the user, as in the Androids own contacts application you need to restrict the selection to only IN_VISIBLE_GROUP.

    String where = ContactsContract.Contacts.IN_VISIBLE_GROUP + "= ? ";
    String[] selectionArgs = new String[] { "1" };
like image 35
stoilkov Avatar answered Sep 25 '22 23:09

stoilkov


I think it is important to have the code from this URL http://coderzheaven.com/2011/06/get-all-details-from-contacts-in-android/ on StackOverflow cause at times links like that go down.

 public void readContacts(){
         ContentResolver cr = getContentResolver();
         Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                null, null, null, null);

         if (cur.getCount() > 0) {
            while (cur.moveToNext()) {
                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                    System.out.println("name : " + name + ", ID : " + id);

                    // get the phone number
                    Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
                                           ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
                                           new String[]{id}, null);
                    while (pCur.moveToNext()) {
                          String phone = pCur.getString(
                                 pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                          System.out.println("phone" + phone);
                    }
                    pCur.close();

                    // get email and type

                   Cursor emailCur = cr.query(
                            ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                            null,
                            ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
                            new String[]{id}, null);
                    while (emailCur.moveToNext()) {
                        // This would allow you get several email addresses
                            // if the email addresses were stored in an array
                        String email = emailCur.getString(
                                      emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                        String emailType = emailCur.getString(
                                      emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));

                      System.out.println("Email " + email + " Email Type : " + emailType);
                    }
                    emailCur.close();

                    // Get note.......
                    String noteWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                    String[] noteWhereParams = new String[]{id,
                    ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE};
                            Cursor noteCur = cr.query(ContactsContract.Data.CONTENT_URI, null, noteWhere, noteWhereParams, null);
                    if (noteCur.moveToFirst()) {
                        String note = noteCur.getString(noteCur.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
                      System.out.println("Note " + note);
                    }
                    noteCur.close();

                    //Get Postal Address....

                    String addrWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                    String[] addrWhereParams = new String[]{id,
                        ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE};
//               Cursor addrCur = cr.query(ContactsContract.Data.CONTENT_URI,
//                       null, null, null, null);
               Cursor addrCur = cr.query(ContactsContract.Data.CONTENT_URI,
                       null, addrWhere, addrWhereParams, null);

                    while(addrCur.moveToNext()) {
                        String poBox = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
                        String street = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
                        String city = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
                        String state = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
                        String postalCode = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
                        String country = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
                        String type = addrCur.getString(
                                     addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));

                        // Do something with these....

                    }
                    addrCur.close();

                    // Get Instant Messenger.........
                    String imWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                    String[] imWhereParams = new String[]{id,
                        ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE};
                    Cursor imCur = cr.query(ContactsContract.Data.CONTENT_URI,
                            null, imWhere, imWhereParams, null);
                    if (imCur.moveToFirst()) {
                        String imName = imCur.getString(
                                 imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA));
                        String imType;
                        imType = imCur.getString(
                                 imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.TYPE));
                    }
                    imCur.close();

                    // Get Organizations.........

                    String orgWhere = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
                    String[] orgWhereParams = new String[]{id,
                        ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE};
                    Cursor orgCur = cr.query(ContactsContract.Data.CONTENT_URI,
                                null, orgWhere, orgWhereParams, null);
                    if (orgCur.moveToFirst()) {
                        String orgName = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
                        String title = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
                    }
                    orgCur.close();
                }
            }
       }
    }

emphasized text

like image 21
Ajibola Avatar answered Sep 23 '22 23:09

Ajibola