From dab4c6e9430f8e88fb89fc1115fbf8d98201688c Mon Sep 17 00:00:00 2001 From: Alberto Hidalgo Date: Wed, 22 Nov 2023 16:58:53 +0000 Subject: [PATCH 1/4] Migrate BasicNavigation to Compose --- .../example/usecase/BasicNavigationCompose.kt | 556 ++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt diff --git a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt new file mode 100644 index 0000000..a70dab8 --- /dev/null +++ b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt @@ -0,0 +1,556 @@ +/* + * © 2023 TomTom NV. All rights reserved. + * + * This software is the proprietary copyright of TomTom NV and its subsidiaries and may be + * used for internal evaluation purposes or commercial use strictly subject to separate + * license agreement between you and TomTom NV. If you are the licensee, you are only permitted + * to use this software in accordance with the terms of your license agreement. If you are + * not the licensee, you are not authorized to use this software in any manner and should + * immediately return or destroy it. + */ +package com.tomtom.sdk.examples.usecase + + +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import android.os.Bundle +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.activity.compose.setContent +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidViewBinding +import androidx.core.content.ContextCompat +import com.tomtom.sdk.examples.BuildConfig +import com.tomtom.sdk.examples.R +import com.tomtom.sdk.examples.databinding.ActivityBasicNavigationBinding +import com.tomtom.sdk.location.GeoLocation +import com.tomtom.sdk.location.GeoPoint +import com.tomtom.sdk.location.LocationProvider +import com.tomtom.sdk.location.OnLocationUpdateListener +import com.tomtom.sdk.location.android.AndroidLocationProvider +import com.tomtom.sdk.location.mapmatched.MapMatchedLocationProvider +import com.tomtom.sdk.location.simulation.SimulationLocationProvider +import com.tomtom.sdk.location.simulation.strategy.InterpolationStrategy +import com.tomtom.sdk.map.display.MapOptions +import com.tomtom.sdk.map.display.TomTomMap +import com.tomtom.sdk.map.display.camera.CameraChangeListener +import com.tomtom.sdk.map.display.camera.CameraOptions +import com.tomtom.sdk.map.display.camera.CameraTrackingMode +import com.tomtom.sdk.map.display.common.screen.Padding +import com.tomtom.sdk.map.display.gesture.MapLongClickListener +import com.tomtom.sdk.map.display.location.LocationMarkerOptions +import com.tomtom.sdk.map.display.route.Instruction +import com.tomtom.sdk.map.display.route.RouteClickListener +import com.tomtom.sdk.map.display.route.RouteOptions +import com.tomtom.sdk.map.display.ui.MapFragment +import com.tomtom.sdk.map.display.ui.currentlocation.CurrentLocationButton.VisibilityPolicy +import com.tomtom.sdk.navigation.NavigationFailure +import com.tomtom.sdk.navigation.ProgressUpdatedListener +import com.tomtom.sdk.navigation.RoutePlan +import com.tomtom.sdk.navigation.RouteUpdateReason +import com.tomtom.sdk.navigation.RouteUpdatedListener +import com.tomtom.sdk.navigation.TomTomNavigation +import com.tomtom.sdk.navigation.online.Configuration +import com.tomtom.sdk.navigation.online.OnlineTomTomNavigationFactory +import com.tomtom.sdk.navigation.routereplanner.RouteReplanner +import com.tomtom.sdk.navigation.routereplanner.online.OnlineRouteReplannerFactory +import com.tomtom.sdk.navigation.ui.NavigationFragment +import com.tomtom.sdk.navigation.ui.NavigationUiOptions +import com.tomtom.sdk.routing.RoutePlanner +import com.tomtom.sdk.routing.RoutePlanningCallback +import com.tomtom.sdk.routing.RoutePlanningResponse +import com.tomtom.sdk.routing.RoutingFailure +import com.tomtom.sdk.routing.online.OnlineRoutePlanner +import com.tomtom.sdk.routing.options.Itinerary +import com.tomtom.sdk.routing.options.RoutePlanningOptions +import com.tomtom.sdk.routing.options.guidance.AnnouncementPoints +import com.tomtom.sdk.routing.options.guidance.ExtendedSections +import com.tomtom.sdk.routing.options.guidance.GuidanceOptions +import com.tomtom.sdk.routing.options.guidance.InstructionPhoneticsType +import com.tomtom.sdk.routing.options.guidance.InstructionType +import com.tomtom.sdk.routing.options.guidance.ProgressPoints +import com.tomtom.sdk.routing.route.Route +import com.tomtom.sdk.vehicle.DefaultVehicleProvider +import com.tomtom.sdk.vehicle.Vehicle + +/** + * This example shows how to build a simple navigation application using the TomTom Navigation SDK for Android. + * The application displays a map and shows the user’s location. After the user selects a destination with a long click, the app plans a route and draws it on the map. + * Navigation is started in a simulation mode, once the user taps on the route. + * The application will display upcoming manoeuvres, remaining distance, estimated time of arrival (ETA), current speed, and speed limit information. + * + * For more details on this example, check out the tutorial: https://developer.tomtom.com/android/navigation/documentation/use-cases/build-a-navigation-app + * + **/ + +class BasicNavigationCompose : AppCompatActivity() { + private lateinit var binding: ActivityBasicNavigationBinding + private lateinit var mapFragment: MapFragment + private lateinit var tomTomMap: TomTomMap + private lateinit var locationProvider: LocationProvider + private lateinit var onLocationUpdateListener: OnLocationUpdateListener + private lateinit var routePlanner: RoutePlanner + private lateinit var routeReplanner: RouteReplanner + private var route: Route? = null + private lateinit var routePlanningOptions: RoutePlanningOptions + private lateinit var tomTomNavigation: TomTomNavigation + private lateinit var navigationFragment: NavigationFragment + + /** + * Navigation SDK is only avaialble upon request. + * Use the API key provided by TomTom to start using the SDK. + */ + private val apiKey = BuildConfig.TOMTOM_API_KEY + + + override fun onCreateView( + parent: View?, + name: String, + context: Context, + attrs: AttributeSet + ): View? { + return super.onCreateView(parent, name, context, attrs) + + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContent { // In here, we can call composables! + MaterialTheme { + AndroidViewBinding( + factory = { inflater: LayoutInflater, viewGroup: ViewGroup, attachToParent: Boolean -> + ActivityBasicNavigationBinding.inflate(inflater, viewGroup, attachToParent) + .apply { + navigationFragment = this.navigationFragmentContainer.getFragment() + mapFragment = this.mapContainer.getFragment() + + initMap() + initLocationProvider() + initRouting() + initNavigation() + } + }, + modifier = Modifier.fillMaxSize(), + ) { } + } + } + } + + /** + * Displaying a map + * + * MapOptions is required to initialize the map. + * Use MapFragment to display a map. + * Optional configuration: You can further configure the map by setting various properties of the MapOptions object. You can learn more in the Map Configuration guide. + * The last step is adding the MapFragment to the previously created container. + */ + private fun initMap() { + val mapOptions = MapOptions(mapKey = apiKey) + mapFragment = MapFragment.newInstance(mapOptions) + supportFragmentManager.beginTransaction() + .replace(R.id.map_container, mapFragment) + .commit() + mapFragment.getMapAsync { map -> + tomTomMap = map + enableUserLocation() + setUpMapListeners() + } + } + + /** + * The SDK provides a LocationProvider interface that is used between different modules to get location updates. + * This examples uses the AndroidLocationProvider. + * Under the hood, the engine uses Android’s system location services. + */ + private fun initLocationProvider() { + locationProvider = AndroidLocationProvider(context = this) + } + + /** + * You can plan route by initializing by using the online route planner and default route replanner. + */ + private fun initRouting() { + routePlanner = + OnlineRoutePlanner.create(context = this, apiKey = apiKey) + routeReplanner = OnlineRouteReplannerFactory.create(routePlanner) + } + + /** + * To use navigation in the application, start by by initialising the navigation configuration. + */ + private fun initNavigation() { + val configuration = Configuration( + context = this, + apiKey = apiKey, + locationProvider = locationProvider, + routeReplanner = routeReplanner, + vehicleProvider = DefaultVehicleProvider(vehicle = Vehicle.Car()) + ) + tomTomNavigation = OnlineTomTomNavigationFactory.create(configuration) + } + + /** + * In order to show the user’s location, the application must use the device’s location services, which requires the appropriate permissions. + */ + private fun enableUserLocation() { + if (areLocationPermissionsGranted()) { + showUserLocation() + } else { + requestLocationPermission() + } + } + + /** + * The LocationProvider itself only reports location changes. It does not interact internally with the map or navigation. + * Therefore, to show the user’s location on the map you have to set the LocationProvider to the TomTomMap. + * You also have to manually enable the location indicator. + * It can be configured using the LocationMarkerOptions class. + * + * Read more about user location on the map in the Showing User Location guide. + */ + private fun showUserLocation() { + locationProvider.enable() + // zoom to current location at city level + onLocationUpdateListener = OnLocationUpdateListener { location -> + tomTomMap.moveCamera(CameraOptions(location.position, zoom = 8.0)) + locationProvider.removeOnLocationUpdateListener(onLocationUpdateListener) + } + locationProvider.addOnLocationUpdateListener(onLocationUpdateListener) + tomTomMap.setLocationProvider(locationProvider) + val locationMarker = LocationMarkerOptions(type = LocationMarkerOptions.Type.Pointer) + tomTomMap.enableLocationMarker(locationMarker) + } + + /** + * In this example on planning a route, the origin is the user’s location and the destination is determined by the user selecting a location on the map. + * Navigation is started once the user taps on the route. + * + * To mark the destination on the map, add the MapLongClickListener event handler to the map view. + * To start navigation, add the addRouteClickListener event handler to the map view. + */ + private fun setUpMapListeners() { + tomTomMap.addMapLongClickListener(mapLongClickListener) + tomTomMap.addRouteClickListener(routeClickListener) + } + + /** + * Used to calculate a route based on a selected location. + * - The method removes all polygons, circles, routes, and markers that were previously added to the map. + * - It then creates a route between the user’s location and the selected location. + * - The method needs to return a boolean value when the callback is consumed. + */ + private val mapLongClickListener = MapLongClickListener { geoPoint -> + clearMap() + calculateRouteTo(geoPoint) + true + } + + /** + * Checks whether navigation is currently running. + */ + private fun isNavigationRunning(): Boolean = tomTomNavigation.navigationSnapshot != null + + + /** + * Used to start navigation based on a tapped route, if navigation is not already running. + * - Hide the location button + * - Then start the navigation using the selected route. + */ + private val routeClickListener = RouteClickListener { + if (!isNavigationRunning()) { + route?.let { route -> + mapFragment.currentLocationButton.visibilityPolicy = VisibilityPolicy.Invisible + startNavigation(route) + } + } + } + + /** + * Used to calculate a route using the following parameters: + * - InstructionType - This indicates that the routing result has to contain guidance instructions. + * - InstructionPhoneticsType - This specifies whether to include phonetic transcriptions in the response. + * - AnnouncementPoints - When this parameter is specified, the instruction in the response includes up to three additional fine-grained announcement points, each with its own location, maneuver type, and distance to the instruction point. + * - ExtendedSections - This specifies whether to include extended guidance sections in the response, such as sections of type road shield, lane, and speed limit. + * - ProgressPoints - This specifies whether to include progress points in the response. + */ + private fun calculateRouteTo(destination: GeoPoint) { + val userLocation = + tomTomMap.currentLocation?.position ?: return + val itinerary = Itinerary(origin = userLocation, destination = destination) + routePlanningOptions = RoutePlanningOptions( + itinerary = itinerary, + guidanceOptions = GuidanceOptions( + instructionType = InstructionType.Text, + phoneticsType = InstructionPhoneticsType.Ipa, + announcementPoints = AnnouncementPoints.All, + extendedSections = ExtendedSections.All, + progressPoints = ProgressPoints.All + ), + vehicle = Vehicle.Car() + ) + routePlanner.planRoute(routePlanningOptions, routePlanningCallback) + } + + /** + * The RoutePlanningCallback itself has two methods. + * - The first method is triggered if the request fails. + * - The second method returns RoutePlanningResponse containing the routing results. + * - This example draws the first retrieved route on the map, using the RouteOptions class. + */ + private val routePlanningCallback = object : RoutePlanningCallback { + override fun onSuccess(result: RoutePlanningResponse) { + route = result.routes.first() + drawRoute(route!!) + tomTomMap.zoomToRoutes(ZOOM_TO_ROUTE_PADDING) + } + + override fun onFailure(failure: RoutingFailure) { + Toast.makeText(this@BasicNavigationCompose, failure.message, Toast.LENGTH_SHORT).show() + } + + override fun onRoutePlanned(route: Route) = Unit + } + + /** + * Used to draw route on the map + * You can show the overview of the added routes using the TomTomMap.zoomToRoutes(Int) method. Note that its padding parameter is expressed in pixels. + */ + private fun drawRoute(route: Route) { + val instructions = route.mapInstructions() + val routeOptions = RouteOptions( + geometry = route.geometry, + destinationMarkerVisible = true, + departureMarkerVisible = true, + instructions = instructions, + routeOffset = route.routePoints.map { it.routeOffset } + ) + tomTomMap.addRoute(routeOptions) + } + + /** + * For the navigation use case, the instructions can be drawn on the route in form of arrows that indicate maneuvers. + * To do this, map the Instruction object provided by routing to the Instruction object used by the map. + * Note that during navigation, you need to update the progress property of the drawn route to display the next instructions. + */ + private fun Route.mapInstructions(): List { + val routeInstructions = legs.flatMap { routeLeg -> routeLeg.instructions } + return routeInstructions.map { + Instruction( + routeOffset = it.routeOffset, + combineWithNext = it.combineWithNext + ) + } + } + + /** + * Used to start navigation by + * - initializing the NavigationFragment to display the UI navigation information, + * - passing the Route object along which the navigation will be done, and RoutePlanningOptions used during the route planning, + * - handling the updates to the navigation states using the NavigationListener. + * Note that you have to set the previously-created TomTom Navigation object to the NavigationFragment before using it. + */ + + private fun startNavigation(route: Route) { + initNavigationFragment() + navigationFragment.setTomTomNavigation(tomTomNavigation) + val routePlan = RoutePlan(route, routePlanningOptions) + navigationFragment.startNavigation(routePlan) + navigationFragment.addNavigationListener(navigationListener) + tomTomNavigation.addProgressUpdatedListener(progressUpdatedListener) + tomTomNavigation.addRouteUpdatedListener(routeUpdatedListener) + } + + /** + * Handle the updates to the navigation states using the NavigationListener + * - Use CameraChangeListener to observe camera tracking mode and detect if the camera is locked on the chevron. If the user starts to move the camera, it will change and you can adjust the UI to suit. + * - Use the SimulationLocationProvider for testing purposes. + * - Once navigation is started, the camera is set to follow the user position, and the location indicator is changed to a chevron. To match raw location updates to the routes, use MapMatchedLocationProvider and set it to the TomTomMap. + * - Set the bottom padding on the map. The padding sets a safe area of the MapView in which user interaction is not received. It is used to uncover the chevron in the navigation panel. + */ + private val navigationListener = object : NavigationFragment.NavigationListener { + override fun onStarted() { + tomTomMap.addCameraChangeListener(cameraChangeListener) + tomTomMap.cameraTrackingMode = CameraTrackingMode.FollowRoute + tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerOptions.Type.Chevron)) + setMapMatchedLocationProvider() + setSimulationLocationProviderToNavigation(route!!) + setMapNavigationPadding() + } + + override fun onFailed(failure: NavigationFailure) { + Toast.makeText(this@BasicNavigationCompose, failure.message, Toast.LENGTH_SHORT).show() + stopNavigation() + } + + override fun onStopped() { + stopNavigation() + } + } + + /** + * Used to initialize the NavigationFragment to display the UI navigation information, + */ + private fun initNavigationFragment() { + val navigationUiOptions = NavigationUiOptions( + keepInBackground = true + ) + navigationFragment = NavigationFragment.newInstance(navigationUiOptions) + supportFragmentManager.beginTransaction() + .add(R.id.navigation_fragment_container, navigationFragment) + .commitNow() + } + + private val progressUpdatedListener = ProgressUpdatedListener { + tomTomMap.routes.first().progress = it.distanceAlongRoute + } + + private val routeUpdatedListener by lazy { + RouteUpdatedListener { route, updateReason -> + if (updateReason != RouteUpdateReason.Refresh && + updateReason != RouteUpdateReason.Increment && + updateReason != RouteUpdateReason.LanguageChange + ) { + tomTomMap.removeRoutes() + drawRoute(route) + } + } + } + + /** + * Use the SimulationLocationProvider for testing purposes. + */ + private fun setSimulationLocationProviderToNavigation(route: Route) { + val routeGeoLocations = route.geometry.map { GeoLocation(it) } + val simulationStrategy = InterpolationStrategy(routeGeoLocations) + locationProvider = SimulationLocationProvider.create(strategy = simulationStrategy) + tomTomNavigation.locationProvider = locationProvider + locationProvider.enable() + } + + /** + * Stop the navigation process using NavigationFragment. + * This hides the UI elements and calls the TomTomNavigation.stop() method. + * Don’t forget to reset any map settings that were changed, such as camera tracking, location marker, and map padding. + */ + private fun stopNavigation() { + navigationFragment.stopNavigation() + mapFragment.currentLocationButton.visibilityPolicy = + VisibilityPolicy.InvisibleWhenRecentered + tomTomMap.removeCameraChangeListener(cameraChangeListener) + tomTomMap.cameraTrackingMode = CameraTrackingMode.None + tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerOptions.Type.Pointer)) + resetMapPadding() + navigationFragment.removeNavigationListener(navigationListener) + tomTomNavigation.removeProgressUpdatedListener(progressUpdatedListener) + tomTomNavigation.removeRouteUpdatedListener(routeUpdatedListener) + clearMap() + initLocationProvider() + enableUserLocation() + } + + /** + * Set the bottom padding on the map. The padding sets a safe area of the MapView in which user interaction is not received. It is used to uncover the chevron in the navigation panel. + */ + private fun setMapNavigationPadding() { + val paddingBottom = resources.getDimensionPixelOffset(R.dimen.map_padding_bottom) + val padding = Padding(0, 0, 0, paddingBottom) + setPadding(padding) + } + + private fun setPadding(padding: Padding) { + val scale: Float = resources.displayMetrics.density + val paddingInPixels = Padding( + top = (padding.top * scale).toInt(), + left = (padding.left * scale).toInt(), + right = (padding.right * scale).toInt(), + bottom = (padding.bottom * scale).toInt() + ) + tomTomMap.setPadding(paddingInPixels) + } + + private fun resetMapPadding() { + tomTomMap.setPadding(Padding(0, 0, 0, 0)) + } + + /** + * Once navigation is started, the camera is set to follow the user position, and the location indicator is changed to a chevron. + * To match raw location updates to the routes, use MapMatchedLocationProvider and set it to the TomTomMap. + */ + private fun setMapMatchedLocationProvider() { + val mapMatchedLocationProvider = MapMatchedLocationProvider(tomTomNavigation) + tomTomMap.setLocationProvider(mapMatchedLocationProvider) + mapMatchedLocationProvider.enable() + } + + /** + * + * The method removes all polygons, circles, routes, and markers that were previously added to the map. + */ + private fun clearMap() { + tomTomMap.clear() + } + + private fun requestLocationPermission() { + locationPermissionRequest.launch( + arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) + } + + private val cameraChangeListener by lazy { + CameraChangeListener { + val cameraTrackingMode = tomTomMap.cameraTrackingMode + if (cameraTrackingMode == CameraTrackingMode.FollowRoute) { + navigationFragment.navigationView.showSpeedView() + } else { + navigationFragment.navigationView.hideSpeedView() + } + } + } + + private val locationPermissionRequest = registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + if (permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true && + permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true + ) { + showUserLocation() + } else { + Toast.makeText( + this, + getString(R.string.location_permission_denied), + Toast.LENGTH_SHORT + ).show() + } + } + + private fun areLocationPermissionsGranted() = ContextCompat.checkSelfPermission( + this, + Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( + this, + Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + + override fun onDestroy() { + tomTomMap.setLocationProvider(null) + super.onDestroy() + tomTomNavigation.close() + locationProvider.close() + } + + companion object { + private const val ZOOM_TO_ROUTE_PADDING = 100 + } +} From 94180073757c90b288feda26a5ee92fb8b9fd3c7 Mon Sep 17 00:00:00 2001 From: Alberto Hidalgo Date: Wed, 24 Jan 2024 15:30:53 +0000 Subject: [PATCH 2/4] Rebase to main branch, update dependencies and migrate code to compose --- tomtom-navigation-core-examples/.gitignore | 278 ++++++++++++++++++ .../gradle/libs.versions.toml | 37 ++- .../usecase/build.gradle.kts | 11 +- .../usecase/src/main/AndroidManifest.xml | 5 +- .../example/usecase/BasicNavigationCompose.kt | 161 +++++----- .../res/layout/activity_basic_navigation.xml | 20 ++ 6 files changed, 425 insertions(+), 87 deletions(-) create mode 100644 tomtom-navigation-core-examples/.gitignore create mode 100644 tomtom-navigation-core-examples/usecase/src/main/res/layout/activity_basic_navigation.xml diff --git a/tomtom-navigation-core-examples/.gitignore b/tomtom-navigation-core-examples/.gitignore new file mode 100644 index 0000000..8ee4a25 --- /dev/null +++ b/tomtom-navigation-core-examples/.gitignore @@ -0,0 +1,278 @@ +# Created by https://www.toptal.com/developers/gitignore/api/android,androidstudio,macos,gradle,firebase,kotlin,git,bitrise,jenv +# Edit at https://www.toptal.com/developers/gitignore?templates=android,androidstudio,macos,gradle,firebase,kotlin,git,bitrise,jenv + +### Android ### +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log/OS Files +*.log + +# Android Studio generated files and folders +captures/ +.externalNativeBuild/ +.cxx/ +*.apk +output.json + +# IntelliJ +*.iml +.idea/ +misc.xml +deploymentTargetDropDown.xml +render.experimental.xml + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +google-services.json +firebase.json + +# Android Profiling +*.hprof + +### Android Patch ### +gen-external-apklibs + +# Replacement of .externalNativeBuild directories introduced +# with Android Studio 3.5. + +### Bitrise ### +.bitrise.secrets.yml + +### Firebase ### +.idea +**/node_modules/* +**/.firebaserc + +### Firebase Patch ### +.runtimeconfig.json +.firebase/ + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### JEnv ### +# JEnv local Java version configuration file +.java-version + +# Used by previous versions of JEnv +.jenv-version + +### Kotlin ### +# Compiled class file +*.class + +# Log file + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump + +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files + +# Generated files +bin/ +gen/ +out/ + +# Gradle files + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +.navigation/ +*.ipr +*~ +*.swp + +# Keystore files + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# NDK +obj/ + +# IntelliJ IDEA +*.iws +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/assetWizardSettings.xml +.idea/gradle.xml +.idea/jarRepositories.xml +.idea/navEditor.xml + +# Legacy Eclipse project files +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) + +# Package Files # + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +# End of https://www.toptal.com/developers/gitignore/api/android,androidstudio,macos,gradle,firebase,kotlin,git,bitrise,jenv \ No newline at end of file diff --git a/tomtom-navigation-core-examples/gradle/libs.versions.toml b/tomtom-navigation-core-examples/gradle/libs.versions.toml index 30d9fac..b308e6b 100644 --- a/tomtom-navigation-core-examples/gradle/libs.versions.toml +++ b/tomtom-navigation-core-examples/gradle/libs.versions.toml @@ -1,6 +1,8 @@ [versions] androidx_compat = "1.6.1" androidx_constraintlayout = "2.1.4" +androidx_activityCompose = "1.8.2" +androidx_composeBom = "2024.03.00" default_world_map = "45424" tomtom_sdk = "1.8.0" @@ -13,19 +15,46 @@ locationProvider = { module = "com.tomtom.sdk.location:provider-android", versio locationSimulation = { module = "com.tomtom.sdk.location:provider-simulation", version.ref = "tomtom_sdk" } locationMapmatched = { module = "com.tomtom.sdk.location:provider-map-matched", version.ref = "tomtom_sdk" } mapsDisplay = { module = "com.tomtom.sdk.maps:map-display", version.ref = "tomtom_sdk" } -navigationOffline = { module = "com.tomtom.sdk.navigation:navigation-offline", version.ref = "tomtom_sdk" } navigationUi = { module = "com.tomtom.sdk.navigation:ui", version.ref = "tomtom_sdk" } +navigationOffline = { module = "com.tomtom.sdk.navigation:navigation-offline", version.ref = "tomtom_sdk" } routeReplannerOffline = { module = "com.tomtom.sdk.routing:route-planner-offline", version.ref = "tomtom_sdk" } styleProviderOffline = { module = "com.tomtom.sdk.maps:style-provider-offline", version.ref = "tomtom_sdk" } -androidXCompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx_compat" } -androidXConstraintLayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx_constraintlayout" } defaultMap = { module = "com.tomtom.sdk.datamanagement.nds:default-world-map", version.ref = "default_world_map" } navigationOnline = { module = "com.tomtom.sdk.navigation:navigation-online", version.ref = "tomtom_sdk" } routePlannerOnline = { module = "com.tomtom.sdk.routing:route-planner-online", version.ref = "tomtom_sdk" } routeReplannerOnline = { module = "com.tomtom.sdk.navigation:route-replanner-online", version.ref = "tomtom_sdk" } +androidXCompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx_compat" } +androidXConstraintLayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx_constraintlayout" } +androidxActivityCompose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidx_activityCompose" } +compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidx_composeBom" } +compose-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +compose-material-icons-core = { group = "androidx.compose.material", name = "material-icons-core" } +compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" } +compose-material3 = { group = "androidx.compose.material3", name = "material3" } +compose-material3-window-size = { group = "androidx.compose.material3", name = "material3-window-size-class" } +compose-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata" } +compose-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +compose-ui = { group = "androidx.compose.ui", name = "ui" } +compose-viewbinding = { group = "androidx.compose.ui", name = "ui-viewbinding" } [bundles] -androidCommon = ["androidXCompat", "androidXConstraintLayout"] +androidCommon = [ + "androidXCompat", + "androidXConstraintLayout", + "androidxActivityCompose", +] + +androidCompose = [ + "compose-graphics", + "compose-material-icons-core", + "compose-material-icons-extended", + "compose-material3", + "compose-material3-window-size", + "compose-runtime-livedata", + "compose-tooling-preview", + "compose-ui", + "compose-viewbinding", +] [plugins] androidApplication = { id = "com.android.application", version = "8.5.0" } diff --git a/tomtom-navigation-core-examples/usecase/build.gradle.kts b/tomtom-navigation-core-examples/usecase/build.gradle.kts index 635b7cd..68e6ab2 100644 --- a/tomtom-navigation-core-examples/usecase/build.gradle.kts +++ b/tomtom-navigation-core-examples/usecase/build.gradle.kts @@ -20,7 +20,7 @@ android { defaultConfig { minSdk = 26 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" buildConfigField("String", "TOMTOM_API_KEY", "\"${extra["tomtomApiKey"].toString()}\"") @@ -36,9 +36,14 @@ android { jvmTarget = "1.8" } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.8" + } + buildFeatures { viewBinding = true buildConfig = true + compose = true } } @@ -55,4 +60,8 @@ dependencies { // Android dependencies. implementation(libs.bundles.androidCommon) + + // Compose + implementation(platform(libs.compose.bom)) + implementation(libs.bundles.androidCompose) } diff --git a/tomtom-navigation-core-examples/usecase/src/main/AndroidManifest.xml b/tomtom-navigation-core-examples/usecase/src/main/AndroidManifest.xml index 131d35d..cdc4a3d 100644 --- a/tomtom-navigation-core-examples/usecase/src/main/AndroidManifest.xml +++ b/tomtom-navigation-core-examples/usecase/src/main/AndroidManifest.xml @@ -13,6 +13,7 @@ + @@ -20,11 +21,11 @@ diff --git a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt index a70dab8..5eba05f 100644 --- a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt +++ b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt @@ -8,16 +8,14 @@ * not the licensee, you are not authorized to use this software in any manner and should * immediately return or destroy it. */ -package com.tomtom.sdk.examples.usecase - +package com.example.usecase import android.Manifest -import android.content.Context import android.content.pm.PackageManager +import android.os.Build import android.os.Bundle -import android.util.AttributeSet +import android.util.Log import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.activity.compose.setContent @@ -28,9 +26,9 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidViewBinding import androidx.core.content.ContextCompat -import com.tomtom.sdk.examples.BuildConfig -import com.tomtom.sdk.examples.R -import com.tomtom.sdk.examples.databinding.ActivityBasicNavigationBinding +import com.example.usecase.databinding.ActivityBasicNavigationBinding +import com.tomtom.sdk.datamanagement.navigationtile.NavigationTileStore +import com.tomtom.sdk.datamanagement.navigationtile.NavigationTileStoreConfiguration import com.tomtom.sdk.location.GeoLocation import com.tomtom.sdk.location.GeoPoint import com.tomtom.sdk.location.LocationProvider @@ -52,16 +50,12 @@ import com.tomtom.sdk.map.display.route.RouteClickListener import com.tomtom.sdk.map.display.route.RouteOptions import com.tomtom.sdk.map.display.ui.MapFragment import com.tomtom.sdk.map.display.ui.currentlocation.CurrentLocationButton.VisibilityPolicy -import com.tomtom.sdk.navigation.NavigationFailure +import com.tomtom.sdk.navigation.ActiveRouteChangedListener import com.tomtom.sdk.navigation.ProgressUpdatedListener import com.tomtom.sdk.navigation.RoutePlan -import com.tomtom.sdk.navigation.RouteUpdateReason -import com.tomtom.sdk.navigation.RouteUpdatedListener import com.tomtom.sdk.navigation.TomTomNavigation import com.tomtom.sdk.navigation.online.Configuration import com.tomtom.sdk.navigation.online.OnlineTomTomNavigationFactory -import com.tomtom.sdk.navigation.routereplanner.RouteReplanner -import com.tomtom.sdk.navigation.routereplanner.online.OnlineRouteReplannerFactory import com.tomtom.sdk.navigation.ui.NavigationFragment import com.tomtom.sdk.navigation.ui.NavigationUiOptions import com.tomtom.sdk.routing.RoutePlanner @@ -71,15 +65,12 @@ import com.tomtom.sdk.routing.RoutingFailure import com.tomtom.sdk.routing.online.OnlineRoutePlanner import com.tomtom.sdk.routing.options.Itinerary import com.tomtom.sdk.routing.options.RoutePlanningOptions -import com.tomtom.sdk.routing.options.guidance.AnnouncementPoints import com.tomtom.sdk.routing.options.guidance.ExtendedSections import com.tomtom.sdk.routing.options.guidance.GuidanceOptions import com.tomtom.sdk.routing.options.guidance.InstructionPhoneticsType -import com.tomtom.sdk.routing.options.guidance.InstructionType -import com.tomtom.sdk.routing.options.guidance.ProgressPoints import com.tomtom.sdk.routing.route.Route -import com.tomtom.sdk.vehicle.DefaultVehicleProvider import com.tomtom.sdk.vehicle.Vehicle +import com.tomtom.sdk.vehicle.VehicleProviderFactory /** * This example shows how to build a simple navigation application using the TomTom Navigation SDK for Android. @@ -95,32 +86,17 @@ class BasicNavigationCompose : AppCompatActivity() { private lateinit var binding: ActivityBasicNavigationBinding private lateinit var mapFragment: MapFragment private lateinit var tomTomMap: TomTomMap + private lateinit var navigationTileStore: NavigationTileStore private lateinit var locationProvider: LocationProvider private lateinit var onLocationUpdateListener: OnLocationUpdateListener private lateinit var routePlanner: RoutePlanner - private lateinit var routeReplanner: RouteReplanner private var route: Route? = null private lateinit var routePlanningOptions: RoutePlanningOptions private lateinit var tomTomNavigation: TomTomNavigation private lateinit var navigationFragment: NavigationFragment - /** - * Navigation SDK is only avaialble upon request. - * Use the API key provided by TomTom to start using the SDK. - */ private val apiKey = BuildConfig.TOMTOM_API_KEY - - override fun onCreateView( - parent: View?, - name: String, - context: Context, - attrs: AttributeSet - ): View? { - return super.onCreateView(parent, name, context, attrs) - - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -134,6 +110,7 @@ class BasicNavigationCompose : AppCompatActivity() { mapFragment = this.mapContainer.getFragment() initMap() + initNavigationTileStore() initLocationProvider() initRouting() initNavigation() @@ -167,8 +144,22 @@ class BasicNavigationCompose : AppCompatActivity() { } /** - * The SDK provides a LocationProvider interface that is used between different modules to get location updates. - * This examples uses the AndroidLocationProvider. + * The SDK provides a [NavigationTileStore] class that is used between different modules to get tile data based + * on the online map. + */ + private fun initNavigationTileStore() { + navigationTileStore = NavigationTileStore.create( + context = this, + navigationTileStoreConfig = NavigationTileStoreConfiguration( + apiKey = apiKey + ) + ) + } + + + /** + * The SDK provides a [LocationProvider] interface that is used between different modules to get location updates. + * This examples uses the [AndroidLocationProvider]. * Under the hood, the engine uses Android’s system location services. */ private fun initLocationProvider() { @@ -179,9 +170,7 @@ class BasicNavigationCompose : AppCompatActivity() { * You can plan route by initializing by using the online route planner and default route replanner. */ private fun initRouting() { - routePlanner = - OnlineRoutePlanner.create(context = this, apiKey = apiKey) - routeReplanner = OnlineRouteReplannerFactory.create(routePlanner) + routePlanner = OnlineRoutePlanner.create(context = this, apiKey = apiKey) } /** @@ -190,10 +179,10 @@ class BasicNavigationCompose : AppCompatActivity() { private fun initNavigation() { val configuration = Configuration( context = this, - apiKey = apiKey, + navigationTileStore = navigationTileStore, locationProvider = locationProvider, - routeReplanner = routeReplanner, - vehicleProvider = DefaultVehicleProvider(vehicle = Vehicle.Car()) + routePlanner = routePlanner, + vehicleProvider = VehicleProviderFactory.create(vehicle = Vehicle.Car()) ) tomTomNavigation = OnlineTomTomNavigationFactory.create(configuration) } @@ -289,11 +278,8 @@ class BasicNavigationCompose : AppCompatActivity() { routePlanningOptions = RoutePlanningOptions( itinerary = itinerary, guidanceOptions = GuidanceOptions( - instructionType = InstructionType.Text, phoneticsType = InstructionPhoneticsType.Ipa, - announcementPoints = AnnouncementPoints.All, extendedSections = ExtendedSections.All, - progressPoints = ProgressPoints.All ), vehicle = Vehicle.Car() ) @@ -314,6 +300,7 @@ class BasicNavigationCompose : AppCompatActivity() { } override fun onFailure(failure: RoutingFailure) { + Log.w(TAG, failure.message) Toast.makeText(this@BasicNavigationCompose, failure.message, Toast.LENGTH_SHORT).show() } @@ -346,7 +333,6 @@ class BasicNavigationCompose : AppCompatActivity() { return routeInstructions.map { Instruction( routeOffset = it.routeOffset, - combineWithNext = it.combineWithNext ) } } @@ -366,7 +352,7 @@ class BasicNavigationCompose : AppCompatActivity() { navigationFragment.startNavigation(routePlan) navigationFragment.addNavigationListener(navigationListener) tomTomNavigation.addProgressUpdatedListener(progressUpdatedListener) - tomTomNavigation.addRouteUpdatedListener(routeUpdatedListener) + tomTomNavigation.addActiveRouteChangedListener(activeRouteChangedListener) } /** @@ -379,18 +365,13 @@ class BasicNavigationCompose : AppCompatActivity() { private val navigationListener = object : NavigationFragment.NavigationListener { override fun onStarted() { tomTomMap.addCameraChangeListener(cameraChangeListener) - tomTomMap.cameraTrackingMode = CameraTrackingMode.FollowRoute + tomTomMap.cameraTrackingMode = CameraTrackingMode.FollowRouteDirection tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerOptions.Type.Chevron)) setMapMatchedLocationProvider() setSimulationLocationProviderToNavigation(route!!) setMapNavigationPadding() } - override fun onFailed(failure: NavigationFailure) { - Toast.makeText(this@BasicNavigationCompose, failure.message, Toast.LENGTH_SHORT).show() - stopNavigation() - } - override fun onStopped() { stopNavigation() } @@ -400,12 +381,15 @@ class BasicNavigationCompose : AppCompatActivity() { * Used to initialize the NavigationFragment to display the UI navigation information, */ private fun initNavigationFragment() { - val navigationUiOptions = NavigationUiOptions( - keepInBackground = true - ) - navigationFragment = NavigationFragment.newInstance(navigationUiOptions) + if (!::navigationFragment.isInitialized) { + navigationFragment = NavigationFragment.newInstance( + NavigationUiOptions( + keepInBackground = true + ) + ) + } supportFragmentManager.beginTransaction() - .add(R.id.navigation_fragment_container, navigationFragment) + .replace(R.id.navigation_fragment_container, navigationFragment) .commitNow() } @@ -413,15 +397,10 @@ class BasicNavigationCompose : AppCompatActivity() { tomTomMap.routes.first().progress = it.distanceAlongRoute } - private val routeUpdatedListener by lazy { - RouteUpdatedListener { route, updateReason -> - if (updateReason != RouteUpdateReason.Refresh && - updateReason != RouteUpdateReason.Increment && - updateReason != RouteUpdateReason.LanguageChange - ) { - tomTomMap.removeRoutes() - drawRoute(route) - } + private val activeRouteChangedListener by lazy { + ActiveRouteChangedListener { route -> + tomTomMap.removeRoutes() + drawRoute(route) } } @@ -451,7 +430,7 @@ class BasicNavigationCompose : AppCompatActivity() { resetMapPadding() navigationFragment.removeNavigationListener(navigationListener) tomTomNavigation.removeProgressUpdatedListener(progressUpdatedListener) - tomTomNavigation.removeRouteUpdatedListener(routeUpdatedListener) + tomTomNavigation.removeActiveRouteChangedListener(activeRouteChangedListener) clearMap() initLocationProvider() enableUserLocation() @@ -461,8 +440,9 @@ class BasicNavigationCompose : AppCompatActivity() { * Set the bottom padding on the map. The padding sets a safe area of the MapView in which user interaction is not received. It is used to uncover the chevron in the navigation panel. */ private fun setMapNavigationPadding() { - val paddingBottom = resources.getDimensionPixelOffset(R.dimen.map_padding_bottom) - val padding = Padding(0, 0, 0, paddingBottom) + // This paddingBottom provides 920 which makes the chevron go off the screen + // val paddingBottom = resources.getDimensionPixelOffset(R.dimen.map_padding_bottom) + val padding = Padding(0, 0, 0, CHEVRON_PADDING) setPadding(padding) } @@ -511,7 +491,7 @@ class BasicNavigationCompose : AppCompatActivity() { private val cameraChangeListener by lazy { CameraChangeListener { val cameraTrackingMode = tomTomMap.cameraTrackingMode - if (cameraTrackingMode == CameraTrackingMode.FollowRoute) { + if (cameraTrackingMode == CameraTrackingMode.FollowRouteDirection) { navigationFragment.navigationView.showSpeedView() } else { navigationFragment.navigationView.hideSpeedView() @@ -527,30 +507,51 @@ class BasicNavigationCompose : AppCompatActivity() { ) { showUserLocation() } else { + Log.w(TAG, getString(R.string.location_permission_denied)) Toast.makeText( - this, - getString(R.string.location_permission_denied), - Toast.LENGTH_SHORT + this, getString(R.string.location_permission_denied), Toast.LENGTH_SHORT ).show() } } - private fun areLocationPermissionsGranted() = ContextCompat.checkSelfPermission( - this, - Manifest.permission.ACCESS_FINE_LOCATION - ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( - this, - Manifest.permission.ACCESS_COARSE_LOCATION - ) == PackageManager.PERMISSION_GRANTED + /** + * Method to verify permissions: + * - [Manifest.permission.ACCESS_FINE_LOCATION] + * - [Manifest.permission.ACCESS_COARSE_LOCATION] + * - [Manifest.permission.FOREGROUND_SERVICE_LOCATION] + */ + private fun areLocationPermissionsGranted(): Boolean { + val fineLocationGranted = ContextCompat.checkSelfPermission( + this, Manifest.permission.ACCESS_FINE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + + val coarseLocationGranted = ContextCompat.checkSelfPermission( + this, Manifest.permission.ACCESS_COARSE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + + val isForegroundServiceLocationRequired = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE + val foregroundServiceLocationGranted = if (isForegroundServiceLocationRequired) { + ContextCompat.checkSelfPermission( + this, Manifest.permission.FOREGROUND_SERVICE_LOCATION + ) == PackageManager.PERMISSION_GRANTED + } else true // Assume granted for lower versions + + return fineLocationGranted && coarseLocationGranted && foregroundServiceLocationGranted + } + override fun onDestroy() { tomTomMap.setLocationProvider(null) super.onDestroy() tomTomNavigation.close() + navigationTileStore.close() locationProvider.close() } companion object { + private const val TAG = "BasicNavigationCompose" private const val ZOOM_TO_ROUTE_PADDING = 100 + private const val CHEVRON_PADDING = 263 } } diff --git a/tomtom-navigation-core-examples/usecase/src/main/res/layout/activity_basic_navigation.xml b/tomtom-navigation-core-examples/usecase/src/main/res/layout/activity_basic_navigation.xml new file mode 100644 index 0000000..5b48fcc --- /dev/null +++ b/tomtom-navigation-core-examples/usecase/src/main/res/layout/activity_basic_navigation.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file From bf5fc7d8757090d09ae02c500c08d65e89a8bd7c Mon Sep 17 00:00:00 2001 From: Alberto Hidalgo Date: Fri, 2 Feb 2024 19:13:02 +0000 Subject: [PATCH 3/4] Update versions and clean code --- .../kotlin/com/example/usecase/BasicNavigationCompose.kt | 1 - .../src/main/kotlin/com/example/usecase/MainActivity.kt | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt index 5eba05f..43f540b 100644 --- a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt +++ b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/BasicNavigationCompose.kt @@ -81,7 +81,6 @@ import com.tomtom.sdk.vehicle.VehicleProviderFactory * For more details on this example, check out the tutorial: https://developer.tomtom.com/android/navigation/documentation/use-cases/build-a-navigation-app * **/ - class BasicNavigationCompose : AppCompatActivity() { private lateinit var binding: ActivityBasicNavigationBinding private lateinit var mapFragment: MapFragment diff --git a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/MainActivity.kt b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/MainActivity.kt index e5d98df..9c8a614 100644 --- a/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/MainActivity.kt +++ b/tomtom-navigation-core-examples/usecase/src/main/kotlin/com/example/usecase/MainActivity.kt @@ -32,9 +32,9 @@ import com.tomtom.sdk.location.simulation.SimulationLocationProvider import com.tomtom.sdk.location.simulation.strategy.InterpolationStrategy import com.tomtom.sdk.map.display.MapOptions import com.tomtom.sdk.map.display.TomTomMap -import com.tomtom.sdk.map.display.camera.CameraTrackingMode import com.tomtom.sdk.map.display.camera.CameraChangeListener import com.tomtom.sdk.map.display.camera.CameraOptions +import com.tomtom.sdk.map.display.camera.CameraTrackingMode import com.tomtom.sdk.map.display.common.screen.Padding import com.tomtom.sdk.map.display.gesture.MapLongClickListener import com.tomtom.sdk.map.display.location.LocationMarkerOptions @@ -49,20 +49,18 @@ import com.tomtom.sdk.navigation.RoutePlan import com.tomtom.sdk.navigation.TomTomNavigation import com.tomtom.sdk.navigation.online.Configuration import com.tomtom.sdk.navigation.online.OnlineTomTomNavigationFactory -import com.tomtom.sdk.navigation.routereplanner.RouteReplanner -import com.tomtom.sdk.navigation.routereplanner.online.OnlineRouteReplannerFactory import com.tomtom.sdk.navigation.ui.NavigationFragment import com.tomtom.sdk.navigation.ui.NavigationUiOptions import com.tomtom.sdk.routing.RoutePlanner import com.tomtom.sdk.routing.RoutePlanningCallback import com.tomtom.sdk.routing.RoutePlanningResponse import com.tomtom.sdk.routing.RoutingFailure +import com.tomtom.sdk.routing.online.OnlineRoutePlanner import com.tomtom.sdk.routing.options.Itinerary import com.tomtom.sdk.routing.options.RoutePlanningOptions import com.tomtom.sdk.routing.options.guidance.ExtendedSections import com.tomtom.sdk.routing.options.guidance.GuidanceOptions import com.tomtom.sdk.routing.options.guidance.InstructionPhoneticsType -import com.tomtom.sdk.routing.online.OnlineRoutePlanner import com.tomtom.sdk.routing.route.Route import com.tomtom.sdk.vehicle.Vehicle import com.tomtom.sdk.vehicle.VehicleProviderFactory From c1357042f1de31cdbf2c5c90f470ade51e7e39ae Mon Sep 17 00:00:00 2001 From: Alberto Hidalgo Date: Fri, 29 Mar 2024 15:51:50 +0000 Subject: [PATCH 4/4] Update tomtom to v0.50.6 and rebase to main --- tomtom-navigation-core-examples/usecase/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tomtom-navigation-core-examples/usecase/build.gradle.kts b/tomtom-navigation-core-examples/usecase/build.gradle.kts index 68e6ab2..b2cabe8 100644 --- a/tomtom-navigation-core-examples/usecase/build.gradle.kts +++ b/tomtom-navigation-core-examples/usecase/build.gradle.kts @@ -37,7 +37,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.5.8" + kotlinCompilerExtensionVersion = "1.5.11" } buildFeatures {