ZOFTINO.COM android and web dev tutorials

Android Contacts Provider

In android data about people is stored in a central repository. This repository is managed by contacts provider. Adding, modifying and retrieving data about people can be done using contacts provider. Contacts app in your android device shows data from contacts provider.

With central database for contacts and easy accessibility of contacts data using contacts provider, android allows device users to download contacts data from multiple sources and apps to integrate with contacts app. This capability helps device users in viewing or modifying contacts data from different sources on a new device.

Android users don’t need to create contacts information from scratch. Instead, users need to just add accounts of service where contacts data is available and enable the data synchronization with contacts provider. With contacts provider, user can download contact data on new device and upload from device to a service so that data can be accessed from anywhere.

If you are planning to create an app that needs to access contacts information, you can access contacts data by using contacts provider. Like any other operations on a device, you need to request for required permissions to make your app feature that access contacts data work on the device.

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

If your app has a service which stores people data in your apps repository and you want to provide a feature in your android app to allow users to download or synchronize your app’s data with contacts provider, you can do so by creating sync adapter in your app.

Three main tables in contacts data model are data, raw contacts and contacts. Raw contacts table holds data coming from accounts. Actual data of raw contacts is stored in Data table. Contacts provider manager aggregates and creates a contact in contacts table using all rows in raw contacts for each person.

Since each person’s data is stored in multiple tables and in multiple rows, accessing data for each person requires multiple queries. To make each person data accessible easily, contract provider offers entities. Entity is similar to result of joins in relational database.

How to Display List of Contacts in Your App from Contacts Provider

Below code searches by display name and gets all contacts that match to search criteria. Then it displays all fetched contacts as list view in UI using simple cursor.

 public void getListOfContactNames(View v) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, MY_CONTACT_REQ);
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, MY_CONTACT_REQ);
    }

    Cursor cur = null;
    ContentResolver cr = getContentResolver();

    String[] mProjection =
            {
                    ContactsContract.Contacts._ID,
                    ContactsContract.Contacts.LOOKUP_KEY,
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    Uri uri = ContactsContract.Contacts.CONTENT_URI;

    String selection = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?";
    String[] selectionArgs = new String[]{"%A%"};

    cur = cr.query(uri, mProjection, selection, selectionArgs, null);


    String[] cursorColumns =
            {
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    int[] viewIds = {R.id.cont_row};
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(
            this,
            R.layout.contacts_row,
            cur,
            cursorColumns,
            viewIds,
            0);

    contactLst.setAdapter(simpleCursorAdapter);
}
 

Get List of Contacts by Email Address

public void getListOfContactsByEmail(View v) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, MY_CONTACT_REQ);
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, MY_CONTACT_REQ);
    }

    Cursor cur = null;
    ContentResolver cr = getContentResolver();

    String[] mProjection =
            {
                    ContactsContract.Contacts._ID,
                    ContactsContract.Contacts.LOOKUP_KEY,
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    Uri uri = ContactsContract.Data.CONTENT_URI;

    String selection = ContactsContract.CommonDataKinds.Email.ADDRESS + " LIKE ?" + " AND " +
                                ContactsContract.Contacts.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'";;
    String[] selectionArgs = new String[]{"%M%"};

    cur = cr.query(uri, mProjection, selection, selectionArgs, null);


    String[] cursorColumns =
            {
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    int[] viewIds = {R.id.cont_row};
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(
            this,
            R.layout.contacts_row,
            cur,
            cursorColumns,
            viewIds,
            0);

    contactLst.setAdapter(simpleCursorAdapter);
}

Search Contacts by Any Data Type

You can search for contacts by sending any search string. To do the search, you need to use CONTENT_FILTER_URI and append the search string to it, contacts providers automatically creates search pattern using search string passed with CONTENT_FILTER_URI.

 public void searchContactByAnyType(View v) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, MY_CONTACT_REQ);
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, MY_CONTACT_REQ);
    }

    Cursor cur = null;
    ContentResolver cr = getContentResolver();

    String[] mProjection =
            {
                    ContactsContract.Contacts._ID,
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    String searchStr = "8%";
    Uri contentUri = Uri.withAppendedPath(
            ContactsContract.Contacts.CONTENT_FILTER_URI,
            Uri.encode(searchStr));

    cur = cr.query(contentUri, mProjection, null, null, null);

    String[] cursorColumns =
            {
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };

    int[] viewIds = {R.id.cont_row};
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(
            this,
            R.layout.contacts_row,
            cur,
            cursorColumns,
            viewIds,
            0);

    contactLst.setAdapter(simpleCursorAdapter);
}

How to Get Contact Details

If there is a need to get complete contact data from content provider for a selected contact, it can be done using entity content uri as shown below.

public void getContactDetails(View v) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, MY_CONTACT_REQ);
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, MY_CONTACT_REQ);
    }

    Cursor cur = null;
    ContentResolver cr = getContentResolver();

    String[] projection =
            {
                    ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
                    ContactsContract.Contacts.Entity.DATA1,
                    ContactsContract.Contacts.Entity.DATA2,
                    ContactsContract.Contacts.Entity.DATA3,
                    ContactsContract.Contacts.Entity.MIMETYPE
            };

    int contactId= 23;
    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);

    uri = Uri.withAppendedPath(
            uri,
            ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);

    cur = cr.query(uri, projection, null, null, null);

    while (cur.moveToNext()) {
        String dataone = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.Entity.DATA1));

        TextView tv1 = new TextView(this);
        tv1.setText(dataone);
        cont.addView(tv1);
    }
}

Adding Contacts Using Intents

The best way to add or modify contacts is by using intents. You can use intents without permission and contact app that handles intents makes sure that all contact modification rules are followed.

public void addContact(View v) {
    Intent intent = new Intent(ContactsContract.Intents.Insert.ACTION);
    intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

    intent.putExtra(ContactsContract.Intents.Insert.PHONE, "575757577777");
    intent.putExtra(ContactsContract.Intents.Insert.PHONE_TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);

    intent.putExtra(ContactsContract.Intents.Insert.EMAIL, "test@zoftino.com");
    intent.putExtra(ContactsContract.Intents.Insert.EMAIL_TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);

    intent.putExtra(ContactsContract.Intents.Insert.EMAIL_ISPRIMARY, "1");
    intent.putExtra(ContactsContract.Intents.Insert.COMPANY, "zoftino");
    startActivity(intent);
}

How to Modify Contact Using Intent

Contact app handles ContactsContract.RawContacts.CONTENT_TYPE type of intents and processes contact modification request. DataAndType is used for identifying a contact.

public void modifyContact(View v) {
    Intent intent = new Intent(Intent.ACTION_EDIT);
    intent.setType(ContactsContract.RawContacts.CONTENT_TYPE);

                                            //contact id and lookup key
    Uri uri = ContactsContract.Contacts.getLookupUri(23, "AKJ8");

    intent.setDataAndType(uri, ContactsContract.Contacts.CONTENT_ITEM_TYPE);

    intent.putExtra(ContactsContract.Intents.Insert.EMAIL_ISPRIMARY, "1");
    intent.putExtra(ContactsContract.Intents.Insert.COMPANY, "zoftino");
    intent.putExtra("finishActivityOnSaveCompleted", true);

    startActivity(intent);
}