Open In App

Contact Picker in Android

Improve
Improve
Like Article
Like
Save
Share
Report

Contact Picker is a feature in android that a developer can use to ask users to select a particular contact. The developer can then query details related to the selected contact and perform the required action. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language.

To have the user select a contact and provide your app access to all the contact information, we can use the ACTION_PICK action and pass ContactsContract.Contacts.CONTENT_URI to the Intent which will be used to create the app. Here is the constructor for Intent –

Intent(String action, Uri uri)

The result Intent is delivered to your onActivityResult(int requestCode, int resultCode, Intent data) callback contains the content: URI pointing to the selected contact. The response grants your app temporary permissions to read that contact using the Contacts Provider API even if your app does not include the READ_CONTACTS permission. We can query display name, has a phone number, id, and many other details related to the Contacts table of android using the returned URI. 

Notes: 

  • Contact phone number or email address cannot be obtained using Contacts table since contact number is not stored in this table.
  • Even though the documentation states that we do not require READ_CONTACTS permission when using ACTION_PICK. There has been a bug reported by few developers who state that in few versions of android, READ_CONTACTS permission is required when using ACTION_PICK. Check issue.

Example Project

Create a new project in Android Studio. Select Phone and Tablet and choose Empty Activity from templates. In the next screen, you will be asked to provide details related to your project. You can name the application and package anything you want. Here we have named the application ContactPicker and package com.geekforgeeks.android.contactpicker. Choose language as Java and select minimum SDK to API 21. Click finish.

Android Manifest

We will be needing READ_CONTACTS permission. We need to declare this permission in main/AndroidManifest.xml

AndroidManifest.xml

XML




<?xml version="1.0" encoding="utf-8"?>
    package="com.geekforgeeks.android.contactpicker">
  
      <!-- add READ_CONTACTS permission here  -->
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
      
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ContactPicker">
        <activity
            android:name=".ContactPickerActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
  
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
  
</manifest>


Layout

The layout will consist of two buttons. The first button will open the contacts app and the second button will display the name of the selected contact. Following is a picture of the final layout. 

strings.xml

Before creating a layout, add the following strings in your res/values/strings.xml.

XML




<resources>
    <string name="app_name">ContactPicker</string>
      
      <!-- add the following constants -->
    <string name="contact_pick_text">Pick Contact</string>
    <string name="contact_name_text">Contact Name</string>
</resources>


activity_contact_picker.xml

Now delete all the contents from res/layout/activity_contact_picker.xml and add this.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ContactPickerActivity">
  
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
  
        <Button
            android:id="@+id/contact_pick"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/contact_pick_text" />
  
        <Button
            android:id="@+id/contact_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/contact_name_text" />
        
    </LinearLayout>
    
</androidx.constraintlayout.widget.ConstraintLayout>


Activity

We first need to request READ_CONTACTS permission. Add a method hasContactsPermission() and requestContactsPermission() in java/com/geekforgeeks/android/contactpicker/ContactPickerActivity.java. For more details related to how to request permission visit here.

Java




public class ContactPickerActivity extends AppCompatActivity
{
    private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
   
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        ...
    }
  
    private boolean hasContactsPermission()
    {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
                PackageManager.PERMISSION_GRANTED;
    }
  
    // Request contact permission if it 
    // has not been granted already
    private void requestContactsPermission()
    {
        if (!hasContactsPermission())
        {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
        }
    }
}


In the onCreate(Bundle savedInstanceState) method we need to do 4 things:

  1. Retrieve both the buttons by id.
  2. Create the Intent to open the contacts app.
  3. Add a listener to the mPickContact button which starts the contacts app.
  4. Call the requestContactsPermission() method.

Java




public class ContactPickerActivity extends AppCompatActivity
{
    ...
        
    private static final int REQUEST_CONTACT = 1;
  
    private Button mContactPick;
    private Button mContactName;
  
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contact_picker);
  
        // Intent to pick contacts
        final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
  
        mContactPick = findViewById(R.id.contact_pick);
        mContactName = findViewById(R.id.contact_name);
  
        mContactPick.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                startActivityForResult(pickContact, REQUEST_CONTACT);
            }
        });
  
        requestContactsPermission();
    }
    
    ...
}


Add another method updateButton(boolean enable) which will enable or disable both the buttons depending on if the app has read contacts permission or not. This will prevent any crashes in the app.

Java




public class ContactPickerActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        ...
            
        updateButton(hasContactsPermission());
    }
  
    public void updateButton(boolean enable)
    {
        mContactPick.setEnabled(enable);
        mContactName.setEnabled(enable);
    }
  
    ...
}


Override onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) which will be automatically invoked by android when our user either accepts or denies the app permission to read contacts. It is necessary to do so since depending upon the result, we need to enable and disable both the buttons.

Java




public class ContactPickerActivity extends AppCompatActivity
{
    ...
  
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults)
    {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  
        if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
        {
            updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
        }
    }
  
    ...
}


For the final step, override onActivityResult(int requestCode, int resultCode, Intent data) which will be automatically invoked by android. We check if the method is invoked for REQUEST_CONTACT constant which we passed to the intent. We also check if the data returned is not empty. We retrieve the data and query the fields which we want to retrieve. The result is obtained in a form of a cursor. We pull the required data from the cursor and exit.

Java




public class ContactPickerActivity extends AppCompatActivity
{
    ...
      
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
  
        if (resultCode != Activity.RESULT_OK) return;
  
        if (requestCode == REQUEST_CONTACT && data != null)
        {
            Uri contactUri = data.getData();
  
            // Specify which fields you want 
            // your query to return values for
            String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
  
            // Perform your query - the contactUri
            // is like a "where" clause here
            Cursor cursor = this.getContentResolver()
                    .query(contactUri, queryFields, null, null, null);
            try
            {
                // Double-check that you 
                // actually got results
                if (cursor.getCount() == 0) return;
  
                // Pull out the first column of 
                // the first row of data 
                // that is your contact's name
                cursor.moveToFirst();
  
                String name = cursor.getString(0);
                mContactName.setText(name);
  
            }
            finally
            {
                cursor.close();
            }
        }
    }
      
    ...
}


ContactPickerActivity

Here is the complete ContactPickerActivity.java

Java




package com.geekforgeeks.android.contactpicker;
  
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.Button;
  
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
  
public class ContactPickerActivity extends AppCompatActivity
{
    private static final int REQUEST_READ_CONTACTS_PERMISSION = 0;
    private static final int REQUEST_CONTACT = 1;
  
    private Button mContactPick;
    private Button mContactName;
  
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults)
    {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  
        if (requestCode == REQUEST_READ_CONTACTS_PERMISSION && grantResults.length > 0)
        {
            updateButton(grantResults[0] == PackageManager.PERMISSION_GRANTED);
        }
    }
  
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
  
        if (resultCode != Activity.RESULT_OK) return;
  
        if (requestCode == REQUEST_CONTACT && data != null)
        {
            Uri contactUri = data.getData();
  
            // Specify which fields you want your
            // query to return values for
            String[] queryFields = new String[]{ContactsContract.Contacts.DISPLAY_NAME};
  
            // Perform your query - the contactUri 
            // is like a "where" clause here
            Cursor cursor = this.getContentResolver()
                    .query(contactUri, queryFields, null, null, null);
            try
            {
                // Double-check that you 
                // actually got results
                if (cursor.getCount() == 0) return;
  
                // Pull out the first column 
                // of the first row of data 
                // that is your contact's name
                cursor.moveToFirst();
  
                String name = cursor.getString(0);
                mContactName.setText(name);
  
            }
            finally
            {
                cursor.close();
            }
        }
    }
  
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contact_picker);
  
        // Intent to pick contacts
        final Intent pickContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
  
        mContactPick = findViewById(R.id.contact_pick);
        mContactName = findViewById(R.id.contact_name);
  
        mContactPick.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                startActivityForResult(pickContact, REQUEST_CONTACT);
            }
        });
  
        requestContactsPermission();
        updateButton(hasContactsPermission());
    }
  
    public void updateButton(boolean enable)
    {
        mContactPick.setEnabled(enable);
        mContactName.setEnabled(enable);
    }
  
    private boolean hasContactsPermission()
    {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) ==
                PackageManager.PERMISSION_GRANTED;
    }
  
    // Request contact permission if it
    // has not been granted already
    private void requestContactsPermission()
    {
        if (!hasContactsPermission())
        {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS_PERMISSION);
        }
    }
}


Output:



Last Updated : 28 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads