3

I have these codes which basically use a ListView to display the names in the contact list and I want to get their phone number when click each single name:

final ContentResolver cr = getContentResolver();

final Cursor c = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] {ContactsContract.Contacts.DISPLAY_NAME}, new int[]{R.id.TVRow}, 0);
myPhoneList.setAdapter(myCursorAdapter);

myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id){
        c.moveToPosition(position);
        Toast.makeText(getApplicationContext(), c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Toast.LENGTH_SHORT).show();
    }
});

In the onItemClick Method the

    GetColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)

returns -1 and therefore I cannot get the phone number with this method.

I've also tried to print out all the columns of the cursor c and it returns 34 columns but the only column which seems to be related to the phone number is HasPhoneNumber.

So where's the problem and how can I fix it? Thanks!


The updated version, where the String array passed to construct myCursorAdapter is changed:

final ContentResolver cr = getContentResolver();

    final Cursor c = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER}, new int[]{R.id.TVRow}, 0);
    myPhoneList.setAdapter(myCursorAdapter);

    myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id){
            c.moveToPosition(position);
            Toast.makeText(getApplicationContext(), c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Toast.LENGTH_SHORT).show();
        }
    });

I suppose the updated code will show the phone numbers in the ListView but I got an error says "column 'data1' does not exist".

T. Yu
  • 53
  • 1
  • 1
  • 6

5 Answers5

4

First of all add this line in AndroidManifest.xml to take permission from user.

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

implement the button of contact

        phoneContactsButtton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
            // The below two line is needed to open the contact list of  mobile
                Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
                startActivityForResult(contactPickerIntent,1);

            }
        });

you have to override the onActivityResult() which will be written to the outside of onCreate() mehtod similar to this

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


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode){
        case 1 :
            if (resultCode == Activity.RESULT_OK) {
                Uri contactData = data.getData();

                Cursor cur =  getContentResolver().query(contactData, null, null, null, null);
                if (cur.getCount() > 0) {// thats mean some resutl has been found
                    if(cur.moveToNext()) {
                        String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                        String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                        Log.e("Names", name);

                        if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
                        {

                            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ id,null, null);
                            while (phones.moveToNext()) {
                                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                Log.e("Number", phoneNumber);
                            }
                            phones.close();
                        }

                    }
                }
                cur.close();
            }
            break;
    }

}
4

You can use below code for getting contact list in Recyclerview;

  List<ContactVO> contactVOList = new ArrayList();

  String[] projection = new String[]{ContactsContract.Contacts._ID, ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.PHOTO_URI};
    Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null,
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
    List<ContactVO> userList = new ArrayList<>();

    String lastPhoneName = " ";
    if (phones.getCount() > 0) {
        while (phones.moveToNext()) {
            String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            String contactId = phones.getString(phones.getColumnIndex(ContactsContract.Contacts._ID));
            String photoUri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
            if (!name.equalsIgnoreCase(lastPhoneName)) {
                lastPhoneName = name;
                ContactVO user = new ContactVO();
                user.setContactName(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
                user.setContactNumber(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                userList.add(user);
                Log.d("getContactsList", name + "---" + phoneNumber + " -- " + contactId + " -- " + photoUri);
            }
        }
    }
    phones.close();

    AllContactsAdapter contactAdapter = new AllContactsAdapter(userList, getApplicationContext());
    rvContacts.setLayoutManager(new LinearLayoutManager(PhoneDirectoryActivity.this));
    rvContacts.setAdapter(contactAdapter);

Below ContactVO class file;

public class ContactVO
{
private String ContactImage;
private String ContactName;
private String ContactNumber;

public String getContactImage() {
    return ContactImage;
}

public void setContactImage(String contactImage) {
    this.ContactImage = ContactImage;
}

public String getContactName() {
    return ContactName;
}

public void setContactName(String contactName) {
    ContactName = contactName;
}

public String getContactNumber() {
    return ContactNumber;
}

public void setContactNumber(String contactNumber) {
    ContactNumber = contactNumber;
}
}

and below is AllContactsAdapter file

    public class AllContactsAdapter extends RecyclerView.Adapter<AllContactsAdapter.ContactViewHolder> {

    private List<ContactVO> contactVOList;
    private Context mContext;
    private SparseBooleanArray itemStateArray = new SparseBooleanArray();

    public AllContactsAdapter(List<ContactVO> contactVOList, Context mContext) {
        this.contactVOList = contactVOList;
        this.mContext = mContext;
    }

    @Override
    public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.single_contact_view, null);
        ContactViewHolder contactViewHolder = new ContactViewHolder(view);
        return contactViewHolder;
    }

    @Override
    public void onBindViewHolder(ContactViewHolder holder, int position) {
        ContactVO contactVO = contactVOList.get(position);
        holder.tvContactName.setText(contactVO.getContactName());
        holder.tvPhoneNumber.setText(contactVO.getContactNumber());

        holder.bind(position);

        holder.cbContact.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int adapterPosition = position;
                if (!itemStateArray.get(adapterPosition, false)) {
                    holder.cbContact.setChecked(true);
                    contactsList.add(holder.tvPhoneNumber.getText().toString());
                    itemStateArray.put(adapterPosition, true);
                } else {
                    holder.cbContact.setChecked(false);
                    itemStateArray.put(adapterPosition, false);
                    contactsList.remove(holder.tvPhoneNumber.getText().toString());
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return contactVOList.size();
    }

    public class ContactViewHolder extends RecyclerView.ViewHolder {

        ImageView ivContactImage;
        TextView tvContactName;
        TextView tvPhoneNumber;
        CheckBox cbContact;

        public ContactViewHolder(View itemView) {
            super(itemView);
            ivContactImage = itemView.findViewById(R.id.ivContactImage);
            tvContactName = itemView.findViewById(R.id.tvContactName);
            tvPhoneNumber = itemView.findViewById(R.id.tvPhoneNumber);
            cbContact = itemView.findViewById(R.id.cbContact);
        }
        void bind(int arg1) {
            // use the sparse boolean array to check
            if (!itemStateArray.get(arg1, false)) {
                cbContact.setChecked(false);
            } else {
                cbContact.setChecked(true);
            }
        }
    }
}
Vishal Vaishnav
  • 3,346
  • 3
  • 26
  • 57
1

The ContactsContract Android API stores data about contacts like phone number in the Data table, not the Contacts table.

Read this carefully: https://developer.android.com/reference/android/provider/ContactsContract.html.

Update - here's a fixed version of your code (untested):

final ContentResolver cr = getContentResolver();
String[] projection = new String[] {Contacts.DISPLAY_NAME, Phone.NUMBER};
final Cursor c = cr.query(Data.CONTENT_URI, projection, null, null, null);
myCursorAdapter = new SimpleCursorAdapter(this, R.layout.list_item, c, new String[] {Phone.NUMBER}, new int[]{R.id.TVRow}, 0);
myPhoneList.setAdapter(myCursorAdapter);

myPhoneList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id){
        c.moveToPosition(position);
        Toast.makeText(getApplicationContext(), c.getString(1), Toast.LENGTH_SHORT).show();
    }
});
marmor
  • 27,641
  • 11
  • 107
  • 150
0

it returns -1 because you don't request the column ContactsContract.CommonDataKinds.Phone.NUMBER from DB:

new String[] {ContactsContract.Contacts.DISPLAY_NAME}

ContactsContract.Contacts.DISPLAY_NAME is the only field you request.

To be able to get the phone number, you firstly need to include it into list of columns you want to get from DB:

new String[] {ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}

Now you have to override adapter's getView so it sets the name into the textView of the list row. After that your onItemClick will work as expected

Vladyslav Matviienko
  • 10,610
  • 4
  • 33
  • 52
  • I tried with only ContactsContract.CommonDataKinds.Phone.NUMBER in the String[] and get the error: column 'data1' does not exist. I think since I have already included all the fields in the query, the cursor should contain the field about phone number, and the adapter should not be the cause? – T. Yu Nov 29 '16 at 09:56
  • @T.Yu, I did not understand what you changed and what is a problem now – Vladyslav Matviienko Nov 29 '16 at 10:47
  • I changed new String[] {ContactsContract.Contacts.DISPLAY_NAME} to new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER} and I suppose it will show the phone numbers in the ListView but I got an error says "column 'data1' does not exist". – T. Yu Nov 29 '16 at 11:46
  • @T.Yu, ok, `ContactsContract.CommonDataKinds.Phone.NUMBER` might be a wrong column name. Let me check it – Vladyslav Matviienko Nov 29 '16 at 11:48
  • It should be. Almost all the relative posts on the Internet I've visited so far use this column. – T. Yu Nov 29 '16 at 12:14
0

This Answer just a small update from above answers. It may help to someone.

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)
    }
Thirumalvalavan
  • 2,660
  • 1
  • 30
  • 32