Hardik Trivedi
Hardik Trivedi

Reputation: 6112

Pick contact directly from contact picker intent

Hello I want to pick a contact from our default contact book intent. I tried several ways to do it. Please find the code below. The problem with all those code is that they open one intermediate documents screen with few options there user has to select contact and than it opens contact book.

private void openContactIntent() {
     Intent intent = new Intent(Intent.ACTION_GET_CONTENT, ContactsContract.Contacts.CONTENT_URI);
     intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
     startActivityForResult(intent, REQ_CONTACT_DIRECTORY);
}

I also tried

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);

and

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
startActivityForResult(intent, PICK_CONTACT); 

What I see as an intermediate screen is enter image description here

Upvotes: 24

Views: 24346

Answers (8)

Thirumalvalavan
Thirumalvalavan

Reputation: 2768

StarActivityForResult is deprecated. So we can use below model in Kotlin.

In Manifest:

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

Please implement run-time permission also. I haven't done in my code.

Below lines used to handle the result:

    private val openContacts = registerForActivityResult(ActivityResultContracts.PickContact()) {

    val contactData: Uri = it
    val phone: Cursor? = contentResolver.query(contactData!!, null, null, null, null)
    if (phone!!.moveToFirst()) {
        val contactName: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))

        // To get number - runtime permission is mandatory.
        val id: String = phone.getString(phone.getColumnIndex(ContactsContract.Contacts._ID))
        if (phone.getString(phone.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)).toInt() > 0) {
            val phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null)
            while (phones!!.moveToNext()) {
                val phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                Log.d("## Number", phoneNumber)
            }
            phones!!.close()
        }

        Log.d("## Contact Name", contactName)
    }

}

To open the contacts:

button.setOnClickListener {
        openContacts.launch(null)
    }

Upvotes: 3

Somnath Kadam
Somnath Kadam

Reputation: 6387

For Android 11+, need to add below code in AndroidManifest

......
</application>
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="vnd.android.cursor.dir/contact" />
        </intent>
    </queries>
</manifest>

Upvotes: 3

shadowpath
shadowpath

Reputation: 39

This is just a nice to have implementation (in Kotlin) that I'll add here to help getting the contact info from the cursor. You will also need to grant permissions and request runtime permission

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

    @SuppressLint("Recycle")
    private fun getContactDataFrom(
        contentResolver: ContentResolver,
        contactUri: Uri
    ): ContactModel? {
        val projection = arrayOf(
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME,
            ContactsContract.Contacts.HAS_PHONE_NUMBER
        )

        try {
            val cursor = contentResolver.query(contactUri, projection, null, null, null) ?: return null
            if (!cursor.moveToFirst()) {
                return null
            }

            val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
            val name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
            val hasNumber = (cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))
            cursor.close()

            val email = getEmail(contentResolver, id)

            val phoneNumber = if (hasNumber > 0) {
                getPhoneNumber(contentResolver, id)
            } else {
                ""
            }
            return ContactModel(name, phoneNumber, email)
        } catch (e: Exception) {
            Log.e("Contacts", "Could not get contact info.", e)
            return null
        }
    }

    @SuppressLint("Recycle")
    private fun getPhoneNumber(contentResolver: ContentResolver, id: String?): String {
        var phoneNumber = ""

        val cursor = contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null,
            ContactsContract.Contacts._ID + " = ?",
            arrayOf(id),
            null
        ) ?: return phoneNumber

        if (cursor.moveToFirst()) {
            phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA))
        }

        cursor.close()
        return phoneNumber
    }

    @SuppressLint("Recycle")
    private fun getEmail(contentResolver: ContentResolver, id: String?): String {
        var email = ""

        val cursor = contentResolver.query(
            ContactsContract.CommonDataKinds.Email.CONTENT_URI,
            null,
            ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
            arrayOf(id),
            null
        ) ?: return email

        if (cursor.moveToFirst()) {
            email = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA))
        }

        cursor.close()
        return email
    }

Trigger:

    val intent = Intent(this, PickLabelActivity::class.java)               
    startActivityForResult(intent, PickLabelActivity.REQ_CODE_PICK_LABEL)

Usage in onActivityResult should be something like:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

         if (resultCode == RESULT_OK && requestCode == ConstantsHandler.INTENT_CODE_PICK_CONTACT) {
            val contactUri = data?.data ?: return
            val contactModel = getContactDataFrom(contentResolver, contactUri)

            inputName.setText(contactModel?.name)
            inputPhone.setText(contactModel?.phone)
            inputEmail.setText(contactModel?.email)
        }
    }

And that ContactModel is just a simple data class.

data class ContactModel(
    var name: String? = null,
    var phone: String? = null,
    var email: String? = null
) : Serializable

Upvotes: 0

Android Geek
Android Geek

Reputation: 9225

Try the below code to pick contact:

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
            startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT);

You can fetch the required information in onActivityResult as follows:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case RESULT_PICK_CONTACT:
                  Cursor cursor = null;
    try {
        String phoneNo = null;
        String name = null;

        Uri uri = data.getData();
        cursor = getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        int  phoneIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
        int  nameIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
        phoneNo = cursor.getString(phoneIndex);
        name = cursor.getString(nameIndex);

       Log.e("Name and Contact number is",name+","+phoneNo);

    } catch (Exception e) {
        e.printStackTrace();
    }
                break;
        }
    } else {
        Log.e("Failed", "Not able to pick contact");
    }
}

Upvotes: 14

Linh
Linh

Reputation: 61039

Here is a way to pick name, phone number from Contact in Kotlin

private fun pickEmergencyFromContacts() {
    val i = Intent(Intent.ACTION_PICK)
    i.type = ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE
    startActivityForResult(i, SELECT_PHONE_NUMBER)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == SELECT_PHONE_NUMBER && resultCode == Activity.RESULT_OK) {
        val contactUri = data?.data ?: return
        val projection = arrayOf(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER)
        val cursor = requireContext().contentResolver.query(contactUri, projection,
                null, null, null)

        if (cursor != null && cursor.moveToFirst()) {
            val nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
            val numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
            val name = cursor.getString(nameIndex)
            val number = cursor.getString(numberIndex)

            // do something with name and phone
        }
        cursor?.close()
    }
}

companion object {

    private const val SELECT_PHONE_NUMBER = 111    
    ...
}

Hope it help

Upvotes: 8

Bibin Johny
Bibin Johny

Reputation: 3197

 private static final int RESULT_PICK_CONTACT1= 1;
 public void pickContact1 (View v)
      {
        Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT1);
      }
 @Override
    protected void onActivityResult ( int requestCode, int resultCode, Intent data){
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case RESULT_PICK_CONTACT1:
                    contactPicked1(data);
                    break;
            }
        } else {
            Log.e("SetupActivity", "Failed to pick contact");
        }
    }

 private void contactPicked1 (Intent data){
        Cursor cursor = null;
        try {
            String phoneNo = null;
            String name = null;
            Uri uri = data.getData();
            cursor = getContentResolver().query(uri, null, null, null, null);
            cursor.moveToFirst();
            int phoneIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
            int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
            name = cursor.getString(nameIndex);
            phoneNo = cursor.getString(phoneIndex);
            ed11.setText(name);
            ed12.setText(phoneNo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

This will surely work.

Upvotes: 1

schnill
schnill

Reputation: 955

I also had the same problem. Finally, I got rid of intermediate picker screen using below code,

Intent i=new Intent(Intent.ACTION_PICK);
i.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE);
startActivityForResult(i, SELECT_PHONE_NUMBER);

In onActivityResult get phone number as below

if (requestCode == SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
  // Get the URI and query the content provider for the phone number
  Uri contactUri = data.getData();
  String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
  Cursor cursor = getContext().getContentResolver().query(contactUri, projection,
      null, null, null);

  // If the cursor returned is valid, get the phone number
  if (cursor != null && cursor.moveToFirst()) {
    int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
    String number = cursor.getString(numberIndex);
    // Do something with the phone number
    ... 
  } 

  cursor.close();
}

Upvotes: 21

Foram Shah
Foram Shah

Reputation: 191

This works for me:

Intent it= new Intent(Intent.ACTION_PICK, 
     ContactsContract.Contacts.CONTENT_URI); 
startActivityForResult(it, requestCode);

Upvotes: 1

Related Questions