Add Support for Web App Launch Trigger
TomTom Digital Cockpit provides a means for app launching functionality to be triggered from an external
source, like an App Store, by providing an implementation for
AppLaunchTriggerService
. For example, when a third-party app store
broadcasts an intent to launch an app, the implementation of this interface could observe such a
broadcast and trigger the launch functionality associated with that app type.
In this example, we will continue where we left off after adding an implementation for
AppLaunchHandlerService
to support launching web apps (see
Add support for a custom non-Android app type
),
as adding app launch trigger for any App
type requires having an
implementation for AppLaunchHandlerService
for the same app type.
In this example, we will be using the Android Debug Bridge (ADB) to fire a broadcast with the required information from the command-line. In production it would be expected that the broadcast would come from an external app.
The following steps describe how to add support for triggering web app launching by receiving a broadcast:
- Create web app launch trigger service module.
- Create web app launch trigger broadcast receiver.
- Implement web app launch trigger service.
- Create web app launch trigger service host.
- Configure web app launch trigger service host deployment.
- Send web app launch trigger broadcast.
Create web app launch trigger service module
First, add the AppLaunchTriggerService
dependency to the
/build-logic/libraries.versions.toml
file:
iviAppsuiteAppstoreApiServiceApplaunchtrigger = { module = "com.tomtom.ivi.appsuite:appsuite_appstore_api_service_applaunchtrigger", version.ref = "iviPlatform" }
Create a new module (for example,
webapplaunchtrigger
)
under
examples/applauncher/services
,
and add a Gradle build script.
Create a
build.gradle.kts
file:
1import com.tomtom.ivi.platform.gradle.api.framework.config.ivi23ivi {4 optInToExperimentalApis = true5}67dependencies {8 api(project(":examples_applauncher_common_webapp"))9 implementation(libraries.iviAppsuiteAppstoreApiServiceApplaunchtrigger)10}
Create a
src/main/AndroidManifest.xml
file to specify the required permissions:
1<?xml version="1.0" encoding="utf-8"?>2<manifest xmlns:android="http://schemas.android.com/apk/res/android">3 <permission android:name="com.example.ivi.example.applauncher.APP_LAUNCH_BROADCAST_PERMISSION" />4</manifest>
Create web app launch trigger broadcast receiver
To trigger the launch of the web app, we need to be able to receive and extract the information
sent through the broadcast. Therefore,
we need to create a subclass of
BroadcastReceiver
(for example, WebAppLaunchTriggerBroadcastReceiver
) and implement onReceive(Context, Intent)
, so
we can extract the required information for launching a web app.
Let's assume that the web app URL value will be sent with a key name url
.
1import android.content.BroadcastReceiver2import android.content.Context3import android.content.Intent4import androidx.lifecycle.LiveData5import androidx.lifecycle.MutableLiveData6import com.example.ivi.example.applauncher.common.webapp.WebApp7import com.tomtom.tools.android.api.resourceresolution.drawable.ResourceDrawableResolver8import com.tomtom.tools.android.api.resourceresolution.string.StaticStringResolver910class WebAppLaunchTriggerBroadcastReceiver : BroadcastReceiver() {1112 private val mutableTriggeredWebApp = MutableLiveData<WebApp>()13 val triggeredWebApp: LiveData<WebApp> = mutableTriggeredWebApp1415 override fun onReceive(context: Context?, intent: Intent?) {16 // [WebApp.displayName], [WebApp.summary] and [WebApp.icon] are not necessary for launching17 // a [WebApp], therefore dummy data is assigned for these values.18 intent?.apply {19 mutableTriggeredWebApp.value = WebApp(20 url = getStringExtra("url") ?: "",21 displayName = StaticStringResolver("Dummy display name"),22 summary = StaticStringResolver("Dummy summary"),23 icon = ResourceDrawableResolver(R.drawable.ttivi_appstore_icon_invalidpackage)24 )25 }26 }27}
Implement web app launch trigger service
The app launch trigger service can be implemented by defining a class (for example,
WebAppLaunchTriggerService
) that inherits from the abstract AppLaunchTriggerServiceBase
base
class, and provides the required implementation for the
AppLaunchTriggerService
interface.
For an instance of WebAppLaunchTriggerBroadcastReceiver
to receive a broadcast, we need to
register it with an
IntentFilter
,
which identifies the broadcast action.
1import android.content.IntentFilter2import com.tomtom.ivi.appsuite.appstore.api.service.applaunchtrigger.AppLaunchTriggerServiceBase3import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviDiscoverableServiceIdProvider4import com.tomtom.ivi.platform.framework.api.ipc.iviservice.IviServiceHostContext56class WebAppLaunchTriggerService(7 iviServiceHostContext: IviServiceHostContext,8 serviceIdProvider: IviDiscoverableServiceIdProvider9) : AppLaunchTriggerServiceBase(iviServiceHostContext, serviceIdProvider) {1011 override fun onCreate() {12 super.onCreate()1314 val webAppLaunchTriggerBroadcastReceiver = WebAppLaunchTriggerBroadcastReceiver()15 val filter = IntentFilter(WEB_APP_LAUNCH_TRIGGER_ACTION_BROADCAST)1617 // Register the receiver with a permission to prevent it being triggered insecurely.18 // Contact the 3rd-party app store provider to add the defined permission when sending the19 // intent.20 context.registerReceiver(21 webAppLaunchTriggerBroadcastReceiver,22 filter,23 WEB_APP_BROADCAST_LAUNCH_TRIGGER_PERMISSION,24 null)2526 webAppLaunchTriggerBroadcastReceiver.triggeredWebApp.observe(this) {27 appLaunchTriggerEventListener.onAppLaunchTriggered(it)28 }2930 serviceReady = true31 }3233 private companion object {34 const val WEB_APP_LAUNCH_TRIGGER_ACTION_BROADCAST =35 "com.example.ivi.example.applauncher.WEB_APP_LAUNCH_ACTION"3637 const val WEB_APP_BROADCAST_LAUNCH_TRIGGER_PERMISSION =38 "com.example.ivi.example.applauncher.APP_LAUNCH_BROADCAST_PERMISSION"39 }40}
Create web app launch trigger 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
WebAppLaunchTriggerServiceHost
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 WebAppLaunchTriggerServiceHost(6iviServiceHostContext: IviServiceHostContext,7iviDiscoverableServiceIdProvider: IviDiscoverableServiceIdProvider8) : IviServiceHostBase(iviServiceHostContext) {910 override val iviServices = setOf(11 WebAppLaunchTriggerService(iviServiceHostContext, iviDiscoverableServiceIdProvider)12 )13} -
A
WebAppLaunchTriggerServiceHostBuilder
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 WebAppLaunchTriggerServiceHostBuilder : IviServiceHostBuilder() {67 override fun build(iviServiceHostContext: IviServiceHostContext): IviServiceHostBase =8 WebAppLaunchTriggerServiceHost(iviServiceHostContext) {9 getDiscoverableServiceId(it)10 }1112 companion object13}
Configure web app launch trigger 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 */7val webAppLaunchTriggerServiceHost by extra {8 IviServiceHostConfig(9 serviceHostBuilderName = "WebAppLaunchTriggerServiceHostBuilder",10 implementationModule = ExampleModuleReference("examples_applauncher_services_webapplaunchtrigger"),11 interfaces = listOf(12 IviServiceInterfaceConfig(13 serviceName = "AppLaunchTriggerService",14 serviceId = "com.example.ivi.example.applauncher.services.webapplaunchtrigger",15 serviceApiModule = IviAppsuiteModuleReference("appsuite_appstore_api_service_applaunchtrigger"),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 webAppLaunchTriggerServiceHost: IviServiceHostConfig by project.extra45ivi {6 application {7 enabled = true8 services {9 // Add the web app launch trigger service host to the application.10 addHost(webAppLaunchTriggerServiceHost)11 }12 }13}
Send web app launch trigger broadcast
After setting up everything we need to test the implementation by sending a broadcast from our
development machine. To do this we can use the adb
command-line tool which provides a command for
sending a
broadcast.
Note: Make sure that the action sent through the broadcast is identical to the action defined in
the IntentFilter that was
previously registered for the broadcast. Also, you will need to temporarily comment out the
broadcastPermission
parameter when calling registerReceiver()
in order to verify it with adb
.
adb shell "am broadcast -a com.example.ivi.example.applauncher.WEB_APP_LAUNCH_ACTION --es url 'https://www.tomtom.com/'"