Add Support for a Custom Non-Android App Type
For a custom, non-Android, app type, a means to access the list of available apps to display in the
App Launcher and also a means to launch these apps will be required. To do this the
AppSourceProviderService
and AppLaunchHandlerService
will need to be implemented.
The following steps describe how to create source provider and launch handler service implementations, using the example of a web app:
Create the web app type
The new app type will need to be visible from a number of other modules, so create a new module for
it under examples/applauncher/common
. Name the module webapp
, and add a Gradle build script.
Create a
build.gradle.kts
file:
1import com.tomtom.ivi.platform.gradle.api.framework.config.ivi23ivi {4 // The App base class is currently flagged as experimental, and has to be explicitly opted in.5 optInToExperimentalApis = true6}78dependencies {9 implementation(libraries.iviAppsuiteAppstoreApiCommonModel)10}
Declare an app store dependency in the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiCommonModel = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_common_model", version.ref = "iviPlatform" }
Declare the custom app type. Create
src/main/kotlin/com/example/ivi/example/applauncher/common/webapp/WebApp.kt
1import com.tomtom.ivi.appsuite.appstore.api.common.model.App2import com.tomtom.tools.android.api.resourceresolution.drawable.DrawableResolver3import com.tomtom.tools.android.api.resourceresolution.string.StringResolver4import kotlinx.parcelize.Parcelize56@Parcelize7class WebApp(8 val url: String,9 override val displayName: StringResolver,10 override val summary: StringResolver,11 override val icon: DrawableResolver,12) : App {1314 override val id: String = "${this::class.java.simpleName}.$url"1516 override fun equals(other: Any?): Boolean {17 if (this === other) return true18 if (javaClass != other?.javaClass) return false1920 other as WebApp2122 if (url != other.url) return false2324 return true25 }2627 override fun hashCode(): Int = url.hashCode()28}
Create the web app source provider
The following steps describe how to create a custom app source provider service implementation:
- Create the web app source provider service module
- Implement the web app source provider service
- Create the web app source provider service host
- Configure the web app source provider service host deployment
Create the web app source provider service module
First, add the AppSourceProviderService
dependency to the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiServiceAppsourceprovider = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_service_appsourceprovider", version.ref = "iviPlatform" }
Create a module for the AppSourceProviderService
implementation under
examples/applauncher/services
(for example
examples/applauncher/services/webappsourceprovider
)
and add a Gradle build script.
Create a
build.gradle.kts
file:
1import com.tomtom.ivi.platform.gradle.api.framework.config.ivi23ivi {4 // The AppSourceProviderService API is currently an experimental feature, and has to be5 // explicitly opted in.6 optInToExperimentalApis = true7}8dependencies {9 api(project(":examples_applauncher_common_webapp"))10 implementation(libraries.iviAppsuiteAppstoreApiServiceAppsourceprovider)11}
Implement the web app source provider service
The app source provider service can be implemented by defining a class (for example,
WebAppSourceProviderService
) that inherits from the abstract AppSourceProviderServiceBase
base
class, and implements the methods defined in the AppSourceProviderService
interface.
The service implementation needs to set a number of properties for configuring itself with the
TomTom Digital Cockpit platform. Please refer to the AppSourceProviderService
API
reference documentation for detailed information on these properties.
The properties can be set by overriding the onCreate()
method.
1import com.tomtom.ivi.appsuite.appstore.api.common.model.ParcelableAppClass2import com.tomtom.ivi.appsuite.appstore.api.service.appsourceprovider.AppSourceProviderServiceBase3import com.tomtom.ivi.example.common.webapp.WebApp4import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider5import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext6import com.tomtom.tools.android.api.resourceresolution.drawable.ResourceDrawableResolver7import com.tomtom.tools.android.api.resourceresolution.string.StaticStringResolver89class WebAppSourceProviderService(10 iviServiceHostContext: IviServiceHostContext,11 serviceIdProvider: IviDiscoverableServiceIdProvider12) : AppSourceProviderServiceBase(iviServiceHostContext, serviceIdProvider) {1314 override fun onCreate() {15 super.onCreate()1617 appStore = null1819 // An IVI service interface can use only [Parcelable] types, so the [supportedAppClass]20 // must be returned inside a [Parcelable] wrapper class.21 supportedAppClass = ParcelableAppClass(WebApp::class.java)2223 installedApps = listOf(24 WebApp(25 url = "https://www.tomtom.com/",26 displayName = StaticStringResolver("TomTom"),27 summary = StaticStringResolver("TomTom Web"),28 icon = ResourceDrawableResolver(R.drawable.ttivi_appstore_icon_invalidpackage)29 )30 )31 }3233 override fun onRequiredPropertiesInitialized() {34 serviceReady = true35 }36}
Create the web app source provider service host
Your module will also need to define a service host where the service will be running, as well as provide a service host builder. This can be achieved by creating two classes.
-
A
WebAppSourceProviderServiceHost
class:1import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider2import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBase3import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext45class WebAppSourceProviderServiceHost(6 iviServiceHostContext: IviServiceHostContext,7 iviDiscoverableServiceIdProvider: IviDiscoverableServiceIdProvider8) : IviServiceHostBase(iviServiceHostContext) {910 override val iviServices = setOf(11 WebAppSourceProviderService(iviServiceHostContext, iviDiscoverableServiceIdProvider)12 )13} -
A
WebAppSourceProviderServiceHostBuilder
class:1/**2 * A [WebAppSourceProviderServiceHost] builder used to build a [WebAppSourceProviderService]3 * host.4 */5import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBase6import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBuilder7import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext89class WebAppSourceProviderServiceHostBuilder : IviServiceHostBuilder() {1011 override fun build(iviServiceHostContext: IviServiceHostContext): IviServiceHostBase =12 WebAppSourceProviderServiceHost(iviServiceHostContext) {13 getDiscoverableServiceId(it)14 }1516 companion object17}
Configure the web app source provider service host deployment
Note: Every service host needs to be configured and 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.
Define an IVI service host implementation, in your gradle file, This can also be defined in a
top-level gradle file (for example, iviservicehosts.gradle.kts
) so it can be
used in a multi-project build, including the tests.
Modify the
examples/applauncher/iviservicehosts.gradle.kts
file:
1/**2 * Defines a configuration for the web app source provider service.3 *4 * The configuration specifies the service host implementation and the list of interfaces5 * implemented by this service host.6 */78val webAppSourceProviderServiceHost by extra {9 IviServiceHostConfig(10 serviceHostBuilderName = "WebAppSourceProviderServiceHostBuilder",11 implementationModule = ExampleModuleReference("services_webappsourceprovider"),12 interfaces = listOf(13 IviServiceInterfaceConfig(14 serviceName = "AppSourceProviderService",15 serviceId = "com.tomtom.ivi.example.service.webappsourceprovider",16 serviceApiModule = IviAppsuiteModuleReference("appsuite_appstore_api_service_appsourceprovider"),17 multipleInstances = true18 )19 )20 )21}
Register the service host build configuration in the main application's build script.
Modify the
examples/applauncher/app/build.gradle.kts
file:
1apply(from = rootProject.file("examples/applauncher/iviservicehosts.gradle.kts"))23val webAppSourceProviderServiceHost: IviServiceHostConfig by project.extra45ivi {6 application {7 enabled = true8 services {9 // Add the web app source provider service host to the application.10 addHost(webAppSourceProviderServiceHost)11 }12 }13}
Create the web app launch handler
The following steps describe how to create a web app launch handler service implementation:
- Create the web app launch handler service module
- Implement the web app launch handler service
- Create the web app launch handler service host
- Configure the web app launch handler service host deployment
Create the web app launch handler service module
First, add the AppLaunchHandlerService
dependency to the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiServiceApplaunchhandler = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_service_applaunchhandler", version.ref = "iviPlatform" }
Create a module for the AppLaunchHandlerService
implementation under
examples/applauncher/services
(for example
examples/applauncher/services/webapplaunchhandler
)
and add a Gradle build script.
Create a
build.gradle.kts
file:
1import com.tomtom.ivi.platform.gradle.api.framework.config.ivi23ivi {4 // The AppLaunchHandlerService API is currently an experimental feature, and has to be5 // explicitly opted in.6 optInToExperimentalApis = true7}8dependencies {9 api(project(":examples_applauncher_common_webapp"))10 implementation(libraries.iviAppsuiteAppstoreApiServiceApplaunchhandler)11}
Implement the web app launch handler service
The app launch handler service can be implemented by defining a class (for example,
WebAppLaunchHandlerService
) that inherits from the abstract AppLaunchHandlerServiceBase
base
class, and implements the methods defined in the AppLaunchHandlerService
interface.
The service implementation needs to set a number of properties for configuring itself with the
TomTom Digital Cockpit platform. Please refer to the AppLaunchHandlerService
API
reference documentation for detailed information on these properties.
In this example we will launch the web app in the default browser app, whereas in production, it
would be expected to launch the web app within a
WebView
within a TomTom Digital Cockpit
panel.
The properties can be set by overriding the onCreate()
method.
1import android.content.Intent2import android.net.Uri3import com.tomtom.ivi.appsuite.appstore.api.common.model.App4import com.tomtom.ivi.appsuite.appstore.api.common.model.ParcelableAppClass5import com.tomtom.ivi.appsuite.appstore.api.service.applaunchhandler.AppLaunchHandlerServiceBase6import com.tomtom.ivi.example.common.webapp.WebApp7import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider8import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext910class WebAppLaunchHandlerService(11 private val iviServiceHostContext: IviServiceHostContext,12 serviceIdProvider: IviDiscoverableServiceIdProvider13) : AppLaunchHandlerServiceBase(iviServiceHostContext, serviceIdProvider) {1415 override fun onCreate() {16 super.onCreate()171819 // An IVI service interface can use only [Parcelable] types, so the [supportedAppClass]20 // must be returned inside a [Parcelable] wrapper class.21 supportedAppClass = ParcelableAppClass(WebApp::class.java)22 }2324 override fun onRequiredPropertiesInitialized() {25 serviceReady = true26 }2728 override suspend fun launchApp(app: App) {29 require(app is WebApp)30 launchWebAppInBrowser(app)31 }3233 private fun launchWebAppInBrowser(app: WebApp) {34 val webIntent = Intent(Intent.ACTION_VIEW, Uri.parse(app.url))35 iviServiceHostContext.context.startActivity(webIntent)36 }37}
Create the web app launch handler service host
Your module will also need to define a service host where the service will be running, as well as provide a service host builder. This can be achieved by creating two classes.
-
A
WebAppLaunchHandlerServiceHost
class:1import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider2import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBase3import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext45class WebAppLaunchHandlerServiceHost(6 iviServiceHostContext: IviServiceHostContext,7 iviDiscoverableServiceIdProvider: IviDiscoverableServiceIdProvider8) : IviServiceHostBase(iviServiceHostContext) {910 override val iviServices = setOf(11 WebAppLaunchHandlerService(iviServiceHostContext, iviDiscoverableServiceIdProvider)12 )13} -
A
WebAppLaunchHandlerServiceHostBuilder
class:1import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBase2import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostBuilder3import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext45class WebAppLaunchHandlerServiceHostBuilder : IviServiceHostBuilder() {67 override fun build(iviServiceHostContext: IviServiceHostContext): IviServiceHostBase =8 WebAppLaunchHandlerServiceHost(iviServiceHostContext) {9 getDiscoverableServiceId(it)10 }1112 companion object13}
Configure the web app launch handler service host deployment
Note: Every service host needs to be configured and 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.
Define an IVI service host implementation, in your gradle file, This can also be defined in a
top-level gradle file (for example, iviservicehosts.gradle.kts
) so it can be used in a
multi-project build, including the tests.
Modify the
examples/applauncher/iviservicehosts.gradle.kts
file:
1/**2 * Defines a configuration for the web app launch handler service.3 *4 * The configuration specifies the service host implementation and the list of interfaces5 * implemented by this service host.6 */78val webAppLaunchHandlerServiceHost by extra {9 IviServiceHostConfig(10 serviceHostBuilderName = "WebAppLaunchHandlerServiceHostBuilder",11 implementationModule = ExampleModuleReference("services_webapplaunchhandler"),12 interfaces = listOf(13 IviServiceInterfaceConfig(14 serviceName = "AppLaunchHandlerService",15 serviceId = "com.tomtom.ivi.example.service.webapplaunchhandler",16 serviceApiModule = IviAppsuiteModuleReference("appsuite_appstore_api_service_applaunchhandler"),17 multipleInstances = true18 )19 )20 )21}
Register the service host build configuration in the main application's build script.
Modify the
examples/applauncher/app/build.gradle.kts
file:
1apply(from = rootProject.file("examples/applauncher/iviservicehosts.gradle.kts"))23val webAppLaunchHandlerServiceHost: IviServiceHostConfig by project.extra45ivi {6 application {7 enabled = true8 services {9 // Add the web app launch handler service host to the application.10 addHost(webAppLaunchHandlerServiceHost)11 }12 }13}