On one of my Android apps, I added a trivial option to select a contact from the phone’s contact list. This was working fine until SDK version 5, which changed the way the contacts are represented in the phone’s SQLite database. It is using the “newer” class called ContactsContract instead of the deprecated People class
I have spent quite time in order to figure out which was the best way that will fit my needs. If you are in the same position, feel free to use the code below
My example below is will display a two row list of all the contacts, with alphabetical indexing. It is a mixture of code snippets I have found on the net, while may not be optimized; it will definitely give you the hang of things.
If you are only interested in the contact reading procedure, skip to the method named fillContactsList below, on ContactListDemo.java line nr. 28. This method demonstrates how contacts are accessed.
The rest of the projects also provides:
- Reading of all contacts and phone numbers with SDK5+ compliancy
- Displaying it in Two Row List Item
- Automatically created alphabetical Indexing with FastScrolling
This app must have android.permission.READ_CONTACTS in the AndroidManifest.xml
Here we go:
First, the data type Contact which will be used to store Name and Number:
Contact.java
public class Contact implements Comparable{ private String Name; private String number; public String getName() { return Name; } public void setName(String Name) { this.Name = Name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public int compareTo(Object arg0) { Contact newCont = (Contact)arg0; return this.Name.compareTo(newCont.getName()); } }
Second: the adapter. This will be used to transfer the data to the ListActivity with indexing.
ContactArrayAdapter.java
public class ContactArrayAdapter extends ArrayAdapter<Contact> implements SectionIndexer{ private final int resourceId; ArrayList<Contact> myElements; HashMap<String, Integer> alphaIndexer; String[] sections; @SuppressWarnings({ "unchecked" }) public ContactArrayAdapter(Context context, int textViewResourceId, List objects) { super(context, textViewResourceId, objects); resourceId = textViewResourceId; myElements = (ArrayList<Contact>) objects; alphaIndexer = new HashMap<String, Integer>(); int size = objects.size(); for (int i = size - 1; i >= 0; i--) { Contact element = myElements.get(i); alphaIndexer.put(element.getName().substring(0, 1), i); } Set<String> keys = alphaIndexer.keySet(); Iterator<String> it = keys.iterator(); ArrayList<String> keyList = new ArrayList<String>(); while (it.hasNext()) { String key = it.next(); keyList.add(key); } Collections.sort(keyList); sections = new String[keyList.size()]; keyList.toArray(sections); } @Override public View getView(int position, View convertView, ViewGroup parent) { Contact c = (Contact) getItem(position); // if the array item is null, nothing to display, just return null if (c == null) { return null; } // We need the layoutinflater to pick up the view from xml LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); // Pick up the TwoLineListItem defined in the xml file TwoLineListItem view; if (convertView == null) { view = (TwoLineListItem) inflater.inflate(resourceId, parent, false); } else { view = (TwoLineListItem) convertView; } // Set value for the first text field if (view.getText1() != null) { view.getText1().setText(c.getName()); } // set value for the second text field if (view.getText2() != null) { view.getText2().setText(c.getNumber()); } return view; } public int getPositionForSection(int section) { String letter = sections[section]; return alphaIndexer.get(letter); } public int getSectionForPosition(int position) { // TODO Auto-generated method stub return 0; } public Object[] getSections() { return sections; } }
Third: the Layout. This will define how the name and number will be displayed:
listitemlayout.xml (should be under /res/layout):
<?xml version="1.0" encoding="utf-8"?> <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@android:id/text1" android:layout_marginTop="1dip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="15sp" android:textStyle="bold" /> <TextView android:id="@android:id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@android:id/text1" android:layout_alignLeft="@android:id/text1" android:paddingBottom="4dip" android:includeFontPadding="false" android:textSize="15sp" android:textStyle="normal" /> </TwoLineListItem>
And finally – the activity itself:
ContactListDemo.java
public class ContactListDemo extends ListActivity implements Runnable{ private List<Contact> contacts = null; private Contact con; private ContactArrayAdapter cAdapter; private ProgressDialog prog = null; private Context thisContext = this; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prog = ProgressDialog.show(this, "ContactListDemo", "Getting Contacts", true, false); Thread thread = new Thread(this); thread.start(); } public void run() { if (contacts == null) { contacts = fillContactsList(); } handler.sendEmptyMessage(0); } private List<Contact> fillContactsList() { List<Contact> tmpList = new ArrayList<Contact>(); Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while(c.moveToNext()){ String ContactID = c.getString(c.getColumnIndex(ContactsContract.Contacts._ID)); String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); String hasPhone =c.getString( c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)); if(Integer.parseInt(hasPhone) == 1){ Cursor phoneCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"='"+ContactID+"'", null, null); while(phoneCursor.moveToNext()){ String number = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); con = new Contact(); con.setName(name); con.setNumber(number); tmpList.add(con); } phoneCursor.close(); } } c.close(); Collections.sort(tmpList); return tmpList; } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { prog.dismiss(); cAdapter = new ContactArrayAdapter(thisContext, R.layout.listitemlayout, contacts); getListView().setFastScrollEnabled(true); setListAdapter(cAdapter); } }; @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); TextView label = ((TwoLineListItem) v).getText2(); String phoneNumber = label.getText().toString(); Toast.makeText(this, "Selected " + phoneNumber, Toast.LENGTH_SHORT).show(); } }
For your convenience, you can find the full project in our SVN repository
Hope this info was helpful.
Last note – I’m not giving credits to some websites I got the snippets from, just because it took so much time, and research to get this code working, and i don’t remember which snipped belong to which website. If one of the owners/readers of a website is reading this… Give me a shout and I’ll be glad to add credits
6 replies on “Reading contacts in Android 2.0+”
great work, extremely helpful.
Thanks Arnon!
[…] Reading contacts in Android 2.0+ | More Than TechnicalIf you are only interested in the contact reading procedure, skip to the method named fillContactsList below, on ContactListDemo.java line nr. 28. This method demonstrates how contacts are accessed. […]
Nice tutorial..
its help me lot..
sir can plzz give me a link of the whole project code !! it will realy useful for my project !!
thank u in advance ….plzz
You can get the full project in our SVN repository in googlecode
https://code.google.com/p/morethantechnical/
(Or browse it online with this link)
https://code.google.com/p/morethantechnical/source/browse/#svn%2Ftrunk%2FContactListDemo
great work, extremely helpful.
Thanks a lot.