Contact Store

Access to contacts is one of the most frequent use cases in Android applications. Even if your app is
not a contact management app, there are various cases where you might need access to the device
contacts (such as referring other users to the app).

For developers to access the device
contacts, they need to use ContentProviders. This introduces a lot of frustrations and complications. For someone that has never worked with
ContentProviders before, the documentation can be tedious to go through. The lack of a type-safe
API leads to repeated errors, developer frustration, along with a waste of time and resources for
the developer and the team.

Contact Store is a modern contacts Android API written in Kotlin. It utilises Coroutine’s Flow to
notify the developer for updates happening to the Contacts database.

Installation

Using Gradle:

repositories {
  ...
  mavenCentral()
}

dependencies {
    implementation 'com.alexstyl:contactstore:0.2.0'
}

How to fetch contacts using Contact Store?

The following sample returns a list of all contacts in the device. Each contact will contain an id,
a display name and whether they are starred or not:

val store = ContactStore.newInstance(application)

store.fetchContacts()
    .collect { contacts ->
        val contactString = contacts.joinToString(", ") {
            "DisplayName = ${it.displayName}, isStarred = ${it.isStarred}, id = ${it.contactId}"
        }
        println("Contacts emitted: $contactString")
    }

⚠️ The user must have already granted
the READ_CONTACTS
permission before collecting the flow.

If you need to query specific details about a contact (commonly used in contact detail screens), the
following sample returns a
contact’s Structured Names
and phone numbers:

val store = ContactStore.newInstance(application)

store.fetchContacts(
    predicate = ContactLookup(
        inContactIds = listOf(contactId)
    ),
    columnsToFetch = listOf(
        ContactColumn.NAMES,
        ContactColumn.PHONES
    )
)
    .collect { contacts ->
        val contact = contacts.firstOrNull()
        if (contact == null) {
            println("Contact not found")
        } else {
            val phones = contact.phones
            val contactString = contacts.joinToString(", ") { contact ->
                "Names = ${contact.firstName} ${contact.middleName} ${contact.lastName} " +
                        "phones = ${phones.map { "${it.value} (${it.label})" }}"
            }
            println("Contacts emitted: $contactString")
        }
    }

Always make sure to query only the columns that you need. In the case where a property is accessed
which was not queried, an Exception is thrown.

How to edit contacts using Contact Store?

The following snippets show how to edit contacts in the device. ⚠️ The user must have already
granted
the WRITE_CONTACTS
permission before calling execute().

Insert a new contact

val store = ContactStore.newInstance(application)

store.execute(SaveRequest().apply {
    insert(MutableContact().apply {
        firstName = "Paolo"
        lastName = "Melendez"
        phones.add(
            LabeledValue(
                value = PhoneNumber("555"),
                label = Label.PhoneNumberMobile
            )
        )
    })
})

Update an existing contact

In order to update a contact, you first need to get a reference to the contact from the store. Only
the values queried will be updated. This is by design, in order to prevent accidental value
overrides.

The following code modifies a contact’s note:

val foundContacts = store.fetchContacts(
    predicate = ContactLookup(inContactIds = listOf(5L)),
    columnsToFetch = listOf(ContactColumn.NOTE)
).first()
if (foundContacts.isEmpty()) return // the contact was not found

val contact = foundContacts.first()

store.execute(SaveRequest().apply {
    update(contact.mutableCopy().apply {
        note = Note("To infinity and beyond!")
    })
})

Deleting a contact

The following code shows how to delete a contact by id:

store.execute(SaveRequest().apply {
    delete(contactId = 5L)
})

Getting Help

To report a specific problem or feature request, open a new issue on Github.

License

Apache 2.0. See the LICENSE file for details.

Author

Made by Alex Styl. Follow @alexstyl on Twitter for future updates.

GitHub

https://github.com/alexstyl/contactstore