1

I started to learn Mobile App Development with Android Studios. I want to create a simple app(for testing) where I display all cellphone contacts in a ListView.

I have the main activity and its xml file where I have added a ListView element, I want to display all contacts there.

This is the code of the main activity class:

package com.example.contactlist;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
   }
}

this is the code of the main activity XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="66dp"
    android:background="@color/colorPrimaryDark"
    android:minHeight="?attr/actionBarSize"
    android:theme="?attr/actionBarTheme"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:title="Contact Lists" />

<TextView
    android:id="@+id/subtitulo_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Contact Lists"
    android:textColor="@android:color/black"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.087"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.119" />

<ListView
    android:id="@+id/listado_contactos"
    android:layout_width="346dp"
    android:layout_height="644dp"
    android:layout_marginStart="24dp"
    android:layout_marginLeft="24dp"
    android:layout_marginTop="21dp"
    android:layout_marginEnd="23dp"
    android:layout_marginRight="23dp"
    android:layout_marginBottom="29dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/subtitulo_container"
    tools:listitem="@android:layout/simple_list_item_multiple_choice" />

 </androidx.constraintlayout.widget.ConstraintLayout>

and this is the code of the AndroidManifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.contactlist">
<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/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

What I want to know is how can I get all contacts data from the cellphone and display them in my ListView?

aminography
  • 21,986
  • 13
  • 70
  • 74
Carmen B.
  • 349
  • 7
  • 22

4 Answers4

3

Here is a function from which you can get contacts

private void getContactList() {
  ContentResolver cr = getContentResolver();
  Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
          null, null, null, null);

  if ((cur != null ? cur.getCount() : 0) > 0) {
      while (cur != null && cur.moveToNext()) {
          String id = cur.getString(
                  cur.getColumnIndex(ContactsContract.Contacts._ID));
          String name = cur.getString(cur.getColumnIndex(
                  ContactsContract.Contacts.DISPLAY_NAME));

          if (cur.getInt(cur.getColumnIndex(
                  ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0) {
              Cursor pCur = cr.query(
                      ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                      null,
                      ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                      new String[]{id}, null);
              while (pCur.moveToNext()) {
                  String phoneNo = pCur.getString(pCur.getColumnIndex(
                          ContactsContract.CommonDataKinds.Phone.NUMBER));
                  Log.i(TAG, "Name: " + name);
                  Log.i(TAG, "Phone Number: " + phoneNo);
              }
              pCur.close();
          }
      }
  }
  if(cur!=null){
    cur.close();
  }
}

Reference android-get-all-contacts

Jyotish Biswas
  • 674
  • 5
  • 11
1

you must push or set list to your adapter

public List<String> getNumber(ContentResolver cr)
{
    List<String> phonebook = new ArrayList<>();
    Cursor phones = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
    // use the cursor to access the contacts
    while (phones.moveToNext())
    {
        String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        phonebook.add(phoneNumber);
    }
    return phonebook;
}
hosein moradi
  • 444
  • 3
  • 7
1

I've developed a utility class to retrieve device contacts. It's available on GitHub:

ContactUtils.kt

Since handling all situations that might happen in retrieving contacts is a bit time consuming, I suggest you get this file and add it to your project. It's written in kotlin, but if you are using java, also it's possible to get the list of contacts like the following:

List<ContactData> contacts = ContactUtilsKt.retrieveAllContacts(context);

// or to retrieve all contacts matching specific search pattern:
List<ContactData> contacts = ContactUtilsKt.retrieveAllContacts(context, "John");
aminography
  • 21,986
  • 13
  • 70
  • 74
  • 1
    Cool, Thanks, I'll test this function. So, I'm using Java for create the app, Can I create a kotlin file with your class and call it in Main Activity with the code you post above in this answer? – Carmen B. Aug 17 '20 at 19:22
  • You're welcome :) Sure, Java and kotlin are fully interoperable, so if you are writing in Java, no problem, it's just needed to add the kotlin dependency in `build.gradle` then use the kotlin class in the Java code. – aminography Aug 17 '20 at 19:41
  • @RolandF: Would it be successful? – aminography Aug 18 '20 at 10:28
  • It doesn't work, the app never open if use the kotlin class – Carmen B. Aug 19 '20 at 06:15
  • Too weird problem! Do you mean that it crashes? – aminography Aug 19 '20 at 06:21
  • yes, it crashes. It's something weird. I haven't found a way to make it works – Carmen B. Aug 19 '20 at 06:36
  • It'd be great if you share with me the logcat content about the crash. However, I've written a test activity class that shows the contacts list. It works fine. Please compare your code with it: https://github.com/aminography/CommonUtils/blob/master/java-sample-app/src/main/java/com/aminography/commonutils/sample/ContactUtilsTestActivity.java – aminography Aug 19 '20 at 06:45
  • 1
    This finally work! Thank you. I did check the main code once and once again and I did realize that I had an error in two variables. – Carmen B. Aug 20 '20 at 19:07
  • If I want, for example, update the phone number from a contact, I can do it only with the ID of the Contact? – Carmen B. Aug 20 '20 at 19:13
  • You're welcome :) I'm grateful to see the issue has been solved. Yes, by having contact Id, it's possible to update contact details easily. – aminography Aug 20 '20 at 19:43
  • cool, Thanks to you. Is there a way to convert the List in Array of data. ? – Carmen B. Aug 20 '20 at 20:26
  • Yes, here is the solution to convert a list to an array: https://stackoverflow.com/a/9572820/1631967 – aminography Aug 22 '20 at 05:50
  • 1
    Awesome! Thank you so much. – Carmen B. Aug 22 '20 at 06:56
0

I tried with the aceepted answer, but everytime i used to get my list of particluar contactId as 0

val result: MutableList<ContactData> = mutableListOf()
contentResolver.query(
    ContactsContract.Contacts.CONTENT_URI,
    CONTACT_PROJECTION,
    if (searchPattern.isNotBlank()) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} LIKE '%?%'" else null,
    if (searchPattern.isNotBlank()) arrayOf(searchPattern) else null,
    if (limit > 0 && offset > -1) "${ContactsContract.Contacts.DISPLAY_NAME_PRIMARY} ASC LIMIT $limit OFFSET $offset"
    else ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " ASC"
)?.use {
    if (it.moveToFirst()) {
        do {
            val contactId = it.getLong(it.getColumnIndex(CONTACT_PROJECTION[0]))
            val name = it.getString(it.getColumnIndex(CONTACT_PROJECTION[2])) ?: ""
            val hasPhoneNumber = it.getString(it.getColumnIndex(CONTACT_PROJECTION[3])).toInt()
            val phoneNumber: List<String> = if (hasPhoneNumber > 0) {
                retrievePhoneNumber(contactId)
            } else mutableListOf()

            val avatar = if (retrieveAvatar) retrieveAvatar(contactId) else null
            result.add(ContactData(contactId, name, phoneNumber, avatar))
        } while (it.moveToNext())
    }
}
return result

for this first part of code as it internally calls retrivePhoneNumber(contactId)

val result: MutableList<String> = mutableListOf()
contentResolver.query(
    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
    null,
    "${ContactsContract.CommonDataKinds.Phone.CONTACT_ID} =?",
    arrayOf(contactId.toString()),
    null
)?.use {
    if (it.moveToFirst()) {
        do {
            result.add(it.getString(it.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)))
        } while (it.moveToNext())
    }
}
return result

here in this block of code it.moveToFirst() always false, so returned list is always zero

Here is the working code which will return all list number as list excluding those number who is the same number but space in it like +91123 344 55

val contactsNumberMap = HashMap<String, HashSet<String>>()
val result: MutableList<String> = mutableListOf()
    withContext(Dispatchers.IO) {
        context.contentResolver.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null,
            null,
            null,
            null
        )?.use { c ->
            val contactIdIndex =
                c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)
            val numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
            while (c.moveToNext()) {
                val contactId = c.getString(contactIdIndex)
                val number: String = c.getString(numberIndex)
                if (number.contains(' ').not()) {
                    if (contactsNumberMap.containsKey(contactId)) {
                        contactsNumberMap[contactId]?.add(number)
                    } else {
                        contactsNumberMap[contactId] = hashSetOf(number)
                    }
                }
            }
            contactsNumberMap.map { m ->
                m.apply {
                    value.forEach {
                        result.add(it)
                    }
                }
            }
        }
        return@withContext result
    }
    return result
Neil
  • 31
  • 3