Replace the Stock Android App Support
The TomTom Digital Cockpit app launcher provides stock implementations for providing the list of Android apps to show in the app launcher panel and for launching the Android apps when they are selected.
The stock Android app source provider will provide the list of Android apps which are present on the device, and that were not installed as part of the TomTom Digital Cockpit system image or subsequent TomTom Digital Cockpit updates. If there is a requirement to show or filter apps based on different criteria then this can be done by overriding the stock app source provider.
An example of an alternative Android app source implementation could be one which returns a fixed list of pre-installed apps.
TomTom Digital Cockpit provides stock implementations for launching "launchable" Android apps (that is, standard Android apps with a launcher activity) and Android media apps (that is, media source apps that can be launched in a media player). Launch handling for these two Android app types can be overridden individually with separate implementations or both can be overridden together with a single combined implementation.
An example of an alternative "launchable" Android app launch handler implementation could be one which launches a separate standalone app rather than the stock behaviour of launching the app within a panel.
This section shows how to:
- Replace the stock Android app source support
- Replace the stock launchable Android app launch support
Replace the stock Android app source support
The stock Android app source provider implementation can be overridden by creating your own
AppSourceProviderService
implementation and returning the
AndroidApp
class as the value of the
AppSourceProviderService.supportedAppClass
.
The following steps describe how to override the implementation of the stock
AndroidApp
source provider:
- Create the replacement app source provider module
- Implement the replacement app source provider service
- Create a service host for the replacement app source provider
- Configure the service host deployment for the replacement app source provider
Create the replacement app source provider module
First add the app store common module and AppSourceProviderService
dependency to the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiCommonModel = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_common_model", version.ref = "iviPlatform" }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/androidappsourceprovider
)
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 implementation(libraries.iviAppsuiteAppstoreApiCommonModel)10 implementation(libraries.iviAppsuiteAppstoreApiServiceAppsourceprovider)11}
Implement the replacement app source provider service
The app source provider service can be implemented by defining a class (for example,
AndroidAppSourceProviderService
) 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.common.model.androidapptypes.AndroidApp3import com.tomtom.ivi.appsuite.appstore.api.common.model.androidapptypes.LaunchableAndroidApp4import com.tomtom.ivi.appsuite.appstore.api.service.appsourceprovider.AppSourceProviderServiceBase5import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider6import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext78class AndroidAppSourceProviderService(9 iviServiceHostContext: IviServiceHostContext,10 serviceIdProvider: IviDiscoverableServiceIdProvider11) : AppSourceProviderServiceBase(iviServiceHostContext, serviceIdProvider) {1213 override fun onCreate() {14 super.onCreate()1516 appStore = null1718 // An IVI service interface can use only [Parcelable] types, so the [supportedAppClass] must19 // be returned inside a [Parcelable] wrapper class.20 supportedAppClass = ParcelableAppClass(AndroidApp::class.java)2122 // The value of [launchablePackageName] should match the package name of an Android app23 // known to be installed on the device, otherwise the app will not appear in the app24 // launcher.25 installedApps = listOf(26 LaunchableAndroidApp(27 launchablePackageName = "com.android.example"28 )29 )30 }3132 override fun onRequiredPropertiesInitialized() {33 serviceReady = true34 }35}
Create a service host for the replacement app source provider
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.
-
An
AndroidAppSourceProviderServiceHost
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 AndroidAppSourceProviderServiceHost(6 iviServiceHostContext: IviServiceHostContext,7 iviDiscoverableServiceIdProvider: IviDiscoverableServiceIdProvider8) : IviServiceHostBase(iviServiceHostContext) {910 override val iviServices = setOf(11 AndroidAppSourceProviderService(12 iviServiceHostContext,13 iviDiscoverableServiceIdProvider14 )15 )16} -
An
AndroidAppSourceProviderServiceHostBuilder
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 AndroidAppSourceProviderServiceHostBuilder : IviServiceHostBuilder() {67 override fun build(iviServiceHostContext: IviServiceHostContext): IviServiceHostBase =8 AndroidAppSourceProviderServiceHost(iviServiceHostContext) {9 getDiscoverableServiceId(it)10 }11 companion object12}
Configure the service host deployment for the replacement app source provider
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 android 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 androidAppSourceProviderServiceHost by extra {9 IviServiceHostConfig(10 serviceHostBuilderName = "AndroidAppSourceProviderServiceHostBuilder",11 implementationModule = ExampleModuleReference("services_androidappsourceprovider"),12 interfaces = listOf(13 IviServiceInterfaceConfig(14 serviceName = "AppSourceProviderService",15 serviceId = "com.tomtom.ivi.example.service.androidappsourceprovider",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 androidAppSourceProviderServiceHost: IviServiceHostConfig by project.extra45ivi {6 application {7 enabled = true8 services {9 // Add the Android app source provider service host to the application.10 addHost(androidAppSourceProviderServiceHost)11 }12 }13}
Replace the stock launchable Android app launch support
The stock Android app launch handler implementation can be overridden by creating your own
AppLaunchHandlerService
implementation and returning either the
LaunchableAndroidApp
or MediaAndroidApp
class as the
value of the AppLaunchHandlerService.supportedAppClass
.
In this example we will override the launching implementation for
LaunchableAndroidApp
.
The following steps describe how to override the implementation of the stock
LaunchableAndroidApp
launch handler:
- Create the replacement app launch handler module
- Implement the replacement app launch handler service
- Create a service host for the replacement app launch handler
- Configure the service host deployment for the replacement app launch handler
Create the replacement app launch handler module
First add the app store common module and AppLaunchHandlerService
dependency
to the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiCommonModel = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_common_model", version.ref = "iviPlatform" }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/launchableandroidapplaunchhandler
)
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 implementation(libraries.iviAppsuiteAppstoreApiCommonModel)10 implementation(libraries.iviAppsuiteAppstoreApiServiceApplaunchhandler)11}
Implement the replacement app launch handler service
The app launch handler service can be implemented by defining a class (for example,
LaunchableAndroidAppLaunchHandlerService
) that inherits from the abstract
AppLaunchHandlerServiceBase
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.
The properties can be set by overriding the onCreate()
method.
1import com.tomtom.ivi.appsuite.appstore.api.common.model.App2import com.tomtom.ivi.appsuite.appstore.api.common.model.ParcelableAppClass3import com.tomtom.ivi.appsuite.appstore.api.common.model.androidapptypes.LaunchableAndroidApp4import com.tomtom.ivi.appsuite.appstore.api.service.applaunchhandler.AppLaunchHandlerServiceBase5import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider6import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext78class LaunchableAndroidAppLaunchHandlerService(9 private val iviServiceHostContext: IviServiceHostContext,10 serviceIdProvider: IviDiscoverableServiceIdProvider11) : AppLaunchHandlerServiceBase(iviServiceHostContext, serviceIdProvider) {1213 override fun onCreate() {14 super.onCreate()1516 // An IVI service interface can use only [Parcelable] types, so the [supportedAppClass] must17 // be returned inside a [Parcelable] wrapper class.18 supportedAppClass = ParcelableAppClass(LaunchableAndroidApp::class.java)19 }2021 override fun onRequiredPropertiesInitialized() {22 serviceReady = true23 }2425 override suspend fun launchApp(app: App) {26 require(app is LaunchableAndroidApp)27 launchLaunchableAndroidApp(app)28 }2930 private fun launchLaunchableAndroidApp(app: LaunchableAndroidApp) {31 val launchIntent =32 iviServiceHostContext.context.packageManager.getLaunchIntentForPackage(app.packageName);33 iviServiceHostContext.context.startActivity(launchIntent)3435 }36}
Create a service host for the replacement app launch handler
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
LaunchableAndroidAppLaunchHandlerServiceHost
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 LaunchableAndroidAppLaunchHandlerServiceHost(6 iviServiceHostContext: IviServiceHostContext,7 iviDiscoverableServiceIdProvider: IviDiscoverableServiceIdProvider8) : IviServiceHostBase(iviServiceHostContext) {910 override val iviServices = setOf(11 LaunchableAndroidAppLaunchHandlerService(iviServiceHostContext, iviDiscoverableServiceIdProvider)12 )13} -
A
LaunchableAndroidAppLaunchHandlerServiceHostBuilder
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 LaunchableAndroidAppLaunchHandlerServiceHostBuilder : IviServiceHostBuilder() {67 override fun build(iviServiceHostContext: IviServiceHostContext): IviServiceHostBase =8 LaunchableAndroidAppLaunchHandlerServiceHost(iviServiceHostContext) {9 getDiscoverableServiceId(it)10 }1112 companion object13}
Configure the service host deployment for the replacement app launch handler
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 launchable android app launch handler service.3 *4 * The configuration specifies the service host implementation and the list of interfaces5 * implemented by this service host.6 */7val launchableAndroidAppLaunchHandlerServiceHost by extra {8 IviServiceHostConfig(9 serviceHostBuilderName = "LaunchableAndroidAppLaunchHandlerServiceHostBuilder",10 implementationModule = ExampleModuleReference("services_launchableandroidapplaunchhandler"),11 interfaces = listOf(12 IviServiceInterfaceConfig(13 serviceName = "AppLaunchHandlerService",14 serviceId = "com.tomtom.ivi.example.service.launchableandroidapplaunchhandler",15 serviceApiModule = IviAppsuiteModuleReference("appsuite_appstore_api_service_applaunchhandler"),16 multipleInstances = true17 )18 )19 )20}
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 launchableAndroidAppLaunchHandlerServiceHost: IviServiceHostConfig by project.extra45ivi {6 application {7 enabled = true8 services {9 // Add the Android app launch handler service host to the application.10 addHost(launchableAndroidAppLaunchHandlerServiceHost)11 }12 }13}