Find the contact name to a phone number on Android #1

In the previous blog posts, I showed you how to detect incoming phone calls, and retrieve the caller’s phone number and invoke custom business logic when the phone rings. Today, we will look at how to map this phone number to an actual name!

Let’s recall the requirement: When the phone rings, check if the caller is a known contact to be able to retrieve their name and read it out aloud. So, how do we access contacts in Android?

Data like calendar items, contacts, etc. is stored in an Android-internal database. To access this database, Android provides the CursorLoader. To instruct it which data to access, we need to pass certain URIs – in our case, for the contacts, we need the URI available as ContactsContract.CommonDataKinds.Phone.ContentUri. In addition, the CursorLoader accepts a bunch of additional attributes, most of which are optional – we’ll look at them in a second! First, let’s build the skeleton structure of our ContactsHelper helper class:

static IEnumerable<string> FindCallerName(Context context, string number)
{
	var uri = ContactsContract.CommonDataKinds.Phone.ContentUri;
	
	// TODO: specify selection details
	
	var loader = new CursorLoader(context, uri, projection, selection, selectionArgs, sortOrder);
	var cursor = (ICursor) loader.LoadInBackground();
	
	if (cursor.MoveToFirst())
	{
		do
		{
			// TODO: access data set and return name
		} while (cursor.MoveToNext());
	}
}

This code snippet is not yet runnable since some major parts are missing – I just wanted to show the basic setup of any kind of phone number lookup, the missing details depend on the exact lookup you’re trying to implement. Let’s analyse it step by step:

  1. Method signature: The idea is to create a static helper method that can be called from any activity, service, etc., and that must be passed the context (we’ll need to pass that on to the CursorLoader), and of course the filter criteria, in our case the incoming phone number. The method returns an enumerable because, in theory, several contacts might be stored in the system that share the same phone number (obviously, we’d need to decide which contact’s name to use for dictation – but that discussion is out of scope of this blog post).
  2. Retrieve the URI that specifies we’re looking for phone contact data sets, as described above.
  3. Instantiate the CursorLoader: Both context and target URI need to be specified, among a bunch of other options – as mentioned before, I’ll cover most of them in detail later on.
  4. Open the internal database and perform the desired searching, filtering, sorting, etc. (as specified in the CursorLoader’s additional parameters, as promised we’ll shortly have a look at them!). This is done in a worker thread (thus the method is called LoadInBackground) – when it’s finished, it returns the actual cursor we can use to access the result data items.
  5. Iterate through the resulting contacts: Do this only if the cursor has at least one (first) item, meaning if the search returned some results, and one by one, moving from each item to the next one, until the end is reached. (Ideally, in our case we’ll get exactly one matching result: The one contact the phone number belongs to.)

For finding all contacts that belong to a given phone number, there are (as always…) two alternative approaches. We will look at them one by one – starting with the option of directly filtering by number in the following blog post!