How do I get the device owner Contact profile?

Android Contacts API Library written in Kotlin with Java interoperability. No more ContentProviders and cursors. Say goodbye to ContactsContract. Build your own contacts app!

How do I get the device owner Contact profile?

This library provides the ProfileQuery API that allows you to get the device owner Profile Contact.

Note that there can be only one device owner Contact, which is either set (not null) or not yet set (null). However, like other regular Contacts, the Profile Contact may have one or more RawContacts.

An instance of the ProfileQuery API is obtained by,

val query = Contacts(context).profile().query()

If you want to get non-Profile Contacts, read How do I get a list of contacts in the simplest way? and How do I get a list of contacts in a more advanced way?

A basic query

To get the profile Contact,

val profileContact = Contacts(context).profile().query().find().contact

Including blank (raw) contacts

The API allows you to specify if you want to include blank (raw) contacts or not,

.includeBlanks(true|false)

For more info, read How do I learn more about “blank” contacts?

Specifying Accounts

To only include RawContacts associated with one of the given accounts,

.accounts(accounts)

For example, to include only RawContacts belonging to only one account,

.accounts(Account("john.doe@gmail.com", "com.google"))

For more info, read How do I query for Accounts?

The RawContacts returned will only belong to the specified accounts.

If no accounts are specified (this function is not called or called with no Accounts), then all RawContacts are included in the returned Contact.

A null Account may be provided here, which results in RawContacts with no associated Account to be included. RawContacts without an associated account are considered local contacts or device-only contacts, which are not synced.

For more info, read How do I learn more about “local” (device-only) contacts?

Note that this may affect performance. This may require one or more additional queries, internally performed in this function, which increases the time required for the search. Therefore, you should only specify this if you actually need it.

Including only specific data

To include only the given set of fields (data) in each of the Profile Contact,

.include(fields)

For example, to only include email and name fields,

.include { Email.all + Name.all }

For more info, read How do I include only the data that I want?

Cancelling the query

To cancel a query amid execution,

.find { returnTrueIfQueryShouldBeCancelled() }

The find function optionally takes in a function that, if it returns true, will cancel query processing as soon as possible. The function is called numerous times during query processing to check if processing should stop or continue. This gives you the option to cancel the query.

For example, to automatically cancel the query inside a Kotlin coroutine when the coroutine is cancelled,

launch {
    withContext(coroutineContext) {
        val profile = query.find { !isActive }
    }
}

Performing the query asynchronously

Queries are executed when the find function is invoked. The work is done in the same thread as the call-site. This may result in a choppy UI.

To perform the work in a different thread, use the Kotlin coroutine extensions provided in the async module. For more info, read How do I use the async module to simplify executing work outside of the UI thread using coroutines?

You may, of course, use other multi-threading libraries or just do it yourself =)

Extensions for Kotlin Flow and RxJava are also in the v1 roadmap, which includes APIs for listening to Contacts database changes.

Performing the query with permission

Queries require the android.permission.READ_CONTACTS permission. If not granted, the query will do nothing and return null.

For API 22 and below, the permission “android.permission.READ_PROFILE” is also required but only at the manifest level. Prior to API 23 (Marshmallow), permissions needed to be granted prior to installation instead of at runtime.

To perform the query with permission, use the extensions provided in the permissions module. For more info, read How do I use the permissions module to simplify permission handling using coroutines?

You may, of course, use other permission handling libraries or just do it yourself =)

Custom data support

The ProfilQuery API supports custom data. For more info, read How do I use query APIs to get custom data?