Skip to content

Instantly share code, notes, and snippets.

@levibostian
Created June 20, 2019 14:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save levibostian/35d5f3f91dbcec090973593999a42155 to your computer and use it in GitHub Desktop.
Save levibostian/35d5f3f91dbcec090973593999a42155 to your computer and use it in GitHub Desktop.
Read contacts in Android
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
@Parcelize
data class Contact(val contact_name: String,
val emails: List<String>?,
val phone_numbers: List<String>?): Parcelable
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.os.AsyncTask
import android.provider.ContactsContract
import android.provider.ContactsContract.CommonDataKinds.Phone
import android.provider.ContactsContract.CommonDataKinds.Email
import androidx.core.content.ContextCompat
interface ContactsManager {
val isPermissionGrantedToReadContacts: Boolean
fun readContacts(done: (List<Contact>) -> Unit)
fun readContactsBackground(): List<Contact>
}
class AppContactsManger(private val context: Context): ContactsManager {
override val isPermissionGrantedToReadContacts: Boolean
get() = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED
override fun readContacts(done: (List<Contact>) -> Unit) {
LoadCursorAsyncTask().execute(object : LoadCursorAsyncTask.Listener {
override fun getContext(): Context = context
override fun contactsLoaded(contacts: List<Contact>) {
done(contacts)
}
})
}
override fun readContactsBackground(): List<Contact> {
return ContactsLoader().loadContacts(context)
}
class LoadCursorAsyncTask: AsyncTask<LoadCursorAsyncTask.Listener, Void, List<Contact>>() {
interface Listener {
fun getContext(): Context
fun contactsLoaded(contacts: List<Contact>)
}
private lateinit var listener: Listener
private val context: Context
get() = this.listener.getContext()
override fun doInBackground(vararg params: Listener?): List<Contact> {
this.listener = params[0]!!
return ContactsLoader().loadContacts(context)
}
override fun onPostExecute(result: List<Contact>) {
super.onPostExecute(result)
listener.contactsLoaded(result)
}
}
// Run from a background thread.
class ContactsLoader {
fun loadContacts(context: Context): List<Contact> {
val projection = arrayOf(ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME)
val cursor = context.contentResolver.query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null)!!
val contacts = getContacts(cursor, context)
cursor.close()
return contacts
}
private fun getContacts(cursor: Cursor, context: Context): List<Contact> {
val contacts: ArrayList<Contact> = arrayListOf()
if (cursor.moveToFirst()) {
val idIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID)
val nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)
do {
val contactId = cursor.getString(idIndex)
val contactDisplayName = cursor.getString(nameIndex)
val phoneNumbers = getPhoneNumbersForContact(contactId, context)
val emails = getEmailAddressesForContact(contactId, context)
contacts.add(Contact(contactDisplayName, emails, phoneNumbers))
} while (cursor.moveToNext())
}
return contacts
}
private fun getPhoneNumbersForContact(contactId: String, context: Context): List<String> {
val phoneNumbers: ArrayList<String> = arrayListOf()
val projection = arrayOf(Phone.NUMBER)
val selection = "${Phone.CONTACT_ID} = ?"
val phone = context.contentResolver.query(Phone.CONTENT_URI, projection, selection, arrayOf(contactId), null)!!
if (phone.moveToFirst()) {
val phoneNumberIndex = phone.getColumnIndex(Phone.NUMBER)
while (!phone.isAfterLast) {
val number = phone.getString(phoneNumberIndex)
phoneNumbers.add(number)
phone.moveToNext()
}
}
phone.close()
return phoneNumbers
}
private fun getEmailAddressesForContact(contactId: String, context: Context): List<String> {
val emails: ArrayList<String> = arrayListOf()
val projection = arrayOf(Email.DATA)
val selection = "${Email.CONTACT_ID} = ?"
val email = context.contentResolver.query(Email.CONTENT_URI, projection, selection, arrayOf(contactId), null)!!
if (email.moveToFirst()) {
val emailAddressIndex = email.getColumnIndex(Email.DATA)
while (!email.isAfterLast) {
val address = email.getString(emailAddressIndex)
emails.add(address)
email.moveToNext()
}
}
email.close()
return emails
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment