Create a Custom Contacts Service

Last edit: 2024.04.30

The IVI platform comes with a ContactsService interface for getting access to address book contacts. A product may provide its own implementation of the ContactsService interface or use an existing implementation. In order for the UI to be able to display contacts from this service, a custom contacts service needs to be written. This document describes how to do this.

How to create a custom contacts service

The following sections describe how to create a custom contacts service implementation.

Example code illustrating how to implement the concepts described in this document can be found in examples/telephony/customcontacts.

Service module setup

To create a custom contacts service, add a dependency to the ContactsService in the Gradle file of your module.

Your build.gradle.kts file should contain:

1dependencies {
2 implementation(libraries.iviPlatformContactsApiServiceContacts)
3}

Service configuration

To configure a contacts service to use your custom implementation, define a service host configuration class that inherits from the IviServiceHostConfig class. This class should be placed in the application Gradle build file.

examples/telephony/app/build.gradle.kts

1val customContactsServiceHost by extra {
2 IviServiceHostConfig(
3 serviceHostBuilderName = "CustomContactsServiceHostBuilder",
4 implementationModule = ExampleModuleReference("examples_telephony_customcontacts"),
5 interfaces = listOf(
6 IviServiceInterfaceConfig(
7 serviceName = "ContactsService",
8 serviceApiModule = IviPlatformModuleReference("platform_contacts_api_service_contacts")
9 )
10 )
11 )
12}

In this configuration, the services_customcontacts module defines the implementation for the platform_contacts_api_service_contacts interface.

In order to create the service host configuration named CustomContactsServiceHost, the IVI platform needs a service host builder class with the specific name CustomContactsServiceHostBuilder.

src/main/kotlin/com/example/ivi/example/telephony/customcontacts/CustomContactsServiceHostBuilder.kt

1class CustomContactsServiceHostBuilder : SimpleIviServiceHostBuilder() {
2
3 override fun createIviServices(
4 iviServiceHostContext: IviServiceHostContext
5 ): Collection<AnyIviServiceBase> =
6 listOf(CustomContactsService(iviServiceHostContext))
7
8 companion object
9}

Note: Every service host configuration needs to be registered in your application. This is necessary to know which service should be started with which implementation when a client requires the access to a service api.

To register this configuration, add the service host to your application build.gradle.kts file:

1ivi {
2 optInToExperimentalApis = true
3
4 application {
5 enabled = true
6 services {
7 // Replace the default contact service with the custom contacts service.
8 removeHost(contactsServiceHost)
9 addHost(customContactsServiceHost)
10 }
11 }
12}

Service definition

In order to create a custom contacts service implementation you need to create a class that inherits from the ContactsServiceBase class.

src/main/kotlin/com/example/ivi/example/telephony/customcontacts/CustomContactsService.kt

1internal class CustomContactsService(iviServiceHostContext: IviServiceHostContext) :
2 ContactsServiceBase(iviServiceHostContext) {
3
4 private val mutableContacts = MutableContactsDataSource(context)
5}

Note: The contacts service implementation can define any kind of source for the list of contacts, for example the Android Contacts provider.

In this example the contacts service contains two contacts. The list of contacts contains those two contacts after initialization. The mutable list contactsSource is the source of contacts:

src/main/kotlin/com/example/ivi/example/telephony/customcontacts/CustomContactsService.kt

1// The source of contacts.
2private val contactsSource = mutableListOf(
3 Contact(
4 displayName = "John Smith",
5 initials = "JS",
6 givenName = "John",
7 familyName = "Smith",
8 companyName = "Company Name",
9 phoneNumbers = listOf(PhoneNumber("+281111111", PhoneNumberType.Main)),
10 defaultPhoneNumberIndex = 0,
11 addresses = listOf(Address("45 Some Street, SomeCity, SC 10000", AddressType.Home)),
12 defaultAddressIndex = 0,
13 favorite = true,
14 primarySortKey = "John Smith",
15 alternativeSortKey = "Smith John"
16 ),
17 Contact(
18 displayName = "Kelly Goodwin",
19 initials = "KG",
20 givenName = "Kelly",
21 familyName = "Goodwin",
22 companyName = "Another Company Name",
23 phoneNumbers = listOf(PhoneNumber("+2822222222", PhoneNumberType.Mobile)),
24 defaultPhoneNumberIndex = 0,
25 addresses = listOf(
26 Address(
27 "45 Some Other Street, SomeOtherCity, SC 12000",
28 AddressType.Work
29 )
30 ),
31 defaultAddressIndex = 0,
32 favorite = false,
33 primarySortKey = "Kelly Goodwin",
34 alternativeSortKey = "Goodwin Kelly"
35 ),
36)

Service lifecycle

To manage the initialization and destruction of the service, override the onCreate and onDestroy methods.

When the service is created:

src/main/kotlin/com/example/ivi/example/telephony/customcontacts/CustomContactsService.kt

1override fun onCreate() {
2 super.onCreate()
3 // Initialize the synchronization status.
4 phoneBookSynchronizationStatus = PhoneBookSynchronizationStatus.NO_CONNECTED_DEVICES
5 // Bind the contacts property to an empty mutable map.
6 contacts = mutableContacts
7 // Set the service ready and clients can call any Api of the service.
8 serviceReady = true
9
10 // The source of contacts is ready and synchronization starts.
11 phoneBookSynchronizationStatus = PhoneBookSynchronizationStatus.SYNCHRONIZATION_IN_PROGRESS
12 // Updating the contacts property with some contacts from the source
13 mutableContacts.addContacts(contactsSource)
14}

The ContactsService.contacts and ContactsService.phoneBookSynchronizationStatus properties have been initialized.

When the service is destroyed:

src/main/kotlin/com/example/ivi/example/telephony/customcontacts/CustomContactsService.kt

1override fun onDestroy() {
2 // Put here cleaning code if necessary.
3 super.onDestroy()
4}