How to read phone contact book in Android Android 01.12.2017

How to read phone contact book in Android

Contacts is one of the most important feature in every mobile phone whether its Android device or not because its help us to store our related persons mobile phone number into device. By default Android device has its own contact showing application but some times when android app developer needs so specific functionality in his project then you can easily display all the contact list into app. So here is the complete step by step tutorial for get all phone contacts programmatically.

Read contacts via ContentResolver

Before an application can query the contact records access must be granted through the AndroidManifest.xml file stored in the root of the project. Add the following uses-permission belows the uses-sdk statement.

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

Basic contact information stored in Contacts table with detailed information stored in individual tables for normalization. In Android to query the base contact records the URI to query is stored in ContactsContract.Contacts.CONTENT_URI.

public class ContactsActivity extends AppCompatActivity {
    String TAG = "ContactsActivityTAG";
    Activity activity = ContactsActivity.this;
    String wantPermission = Manifest.permission.READ_CONTACTS;
    private static final int PERMISSION_REQUEST_CODE = 1;

    Cursor crContacts;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contacts);

        if (!checkPermission(wantPermission)) {
            requestPermission(wantPermission);
        } else {
            readContacts();
        }
    }

    private void readContacts() {
        Bitmap photo;
        String id, name, photoUri;
        String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
        ContentResolver cr = getContentResolver();
        crContacts = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null,null, null, order);

        while (crContacts.moveToNext()) {
            id = crContacts.getString(crContacts.getColumnIndex(ContactsContract.Contacts._ID));
            name = crContacts.getString(crContacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            photoUri = crContacts.getString(crContacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));

            if (Integer.parseInt(crContacts.getString(crContacts.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                Cursor crPhones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID
                                + " = ?", new String[]{id}, null);

                Log.d(TAG, "NAME: " + name);

                while (crPhones.moveToNext()) {
                    String phone = crPhones.getString(crPhones
                                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    Log.d(TAG, "\tPHONE: " + phone);
                }
                crPhones.close();
            }

            Cursor crEmails = cr.query(
                    ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
                    ContactsContract.CommonDataKinds.Email.CONTACT_ID
                            + " = ?", new String[] { id }, null);
            while (crEmails.moveToNext()) {
                String email = crEmails.getString(crEmails
                                .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                Log.d(TAG, "\tEMAIL: " + email);
            }
            crEmails.close();

            if (photoUri != null) {
                try {
                    photo = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(photoUri));
                    Log.d(TAG, "\tPHOTO: " + photo);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        crContacts.close();
    }

    private String getPhone() {
        TelephonyManager phoneMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(activity, wantPermission) != PackageManager.PERMISSION_GRANTED) {
            return "";
        }
        return phoneMgr.getLine1Number();
    }

    private void requestPermission(String permission){
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)){
            Toast.makeText(activity, "Read contacts permission allows us to read your contacts. Please allow it for additional functionality.", Toast.LENGTH_LONG).show();
        }
        ActivityCompat.requestPermissions(activity, new String[]{permission},PERMISSION_REQUEST_CODE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    readContacts();
                } else {
                    Toast.makeText(activity,"Permission Denied. We can't read contacts.", Toast.LENGTH_LONG).show();
                }
                break;
        }
    }

    private boolean checkPermission(String permission){
        if (Build.VERSION.SDK_INT >= 23) {
            int result = ContextCompat.checkSelfPermission(activity, permission);
            if (result == PackageManager.PERMISSION_GRANTED){
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }
}

This application starts off as any other Android application. First create a ContentResolver isntance in cr. Then use the ContentResolver instance to query the database and return a Cursor with the contacts list. The query is perofrmed against the URI stored in ContactsContract.Contacts.CONTENT_URI.

Phone numbers are stored in their own table and need to be queried separately. To query the phone number table use the URI stored in the SDK variable ContactsContract.CommonDataKinds.Phone.CONTENT_URI.

Querying email addresses is similar to phone numbers. A query must be performed to get email addresses from the database. Query the URI stored in ContactsContract.CommonDataKinds.Email.CONTENT_URI to query the email address table.

Custom notes can be attached to each contact record. As before these are stored in a separate table and are related based on the contact ID.

Android can store multiple postal addresses per contact. Addresses are also stored in the data table like notes and queried via the URI stored in ContactsContract.Data.CONTENT_URI.

The instant messenger query performs just as the notes and address queries. Important field names for IM related data are stored in ContactsContract.CommonDataKinds.Im.

The last part of the contact record to be covered is the organizations data. The Android contact record can contain information about employment, professional, and social memberships as well as roles and titles. These records are queried from the URI stored in ContactsContract.Data.CONTENT_URI.

Result

android_phone_contacts_cr.png

If you have big amount of items in your contacts you may have problem with slow representation. To solve this issue you can use following snippet

String selection = "HAS_PHONE_NUMBER <> 0";
String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
String[] projection = new String[] {
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Phone.PHOTO_URI,
        ContactsContract.CommonDataKinds.Phone.NUMBER
};

Cursor crContacts = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, selection, null, order);

while (crContacts.moveToNext()) {
    String name = crContacts.getString(crContacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
    String phone = crContacts.getString(crContacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
    String photoUri = crContacts.getString(crContacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));

    Log.d(Constants.TAG, "readContacts: " + name);
    Log.d(Constants.TAG, "readContacts: " + phone);
    Log.d(Constants.TAG, "readContacts: " + photoUri);
}

crContacts.close();

Read contacts via Contact Picker

In this snippet I'm going to show how to pick contacts from default People application and display the Name and Phone Number using startActivityForResult and Intent.

See flowing steps

  1. Create a new Intent with action type ACTION_PICK.
  2. Set target as ContactsContract.CommonDataKinds.Phone.CONTENT_URI.
  3. Launch the intent using startActivityForResult with the predefined request code.
  4. Override onActivityResult method to handle the result of the picker action.
  5. Query the received contact uri to get the phone number and display name.
  6. Display the values.
public class ContactsActivity extends AppCompatActivity {
    String TAG = "ContactsActivityTAG";
    Activity activity = ContactsActivity.this;
    private static final int RESULT_PICK_CONTACT = 1234;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contacts);
    }

    public void clickPickContacts(View v) {
        Intent cp = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        startActivityForResult(cp, RESULT_PICK_CONTACT);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case RESULT_PICK_CONTACT:
                    contactPicked(data);
                    break;
            }
        } else {
            Log.e(TAG, "Failed to pick contact");
        }
    }

    private void contactPicked(Intent data) {
        Cursor cursor = null;
        try {
            String phone, name;
            Uri uri = data.getData();
            cursor = getContentResolver().query(uri, null, null, null, null);
            cursor.moveToFirst();
            phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

            Log.d(TAG, "ContactPicked NAME: " + name);
            Log.d(TAG, "ContactPicked NUMBER: " + phone);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Result

android_phone_contacts_intent.png