From 0a1c908a9da5125f34c6db1e51f8a12e236ddcf1 Mon Sep 17 00:00:00 2001
From: Piotr Dec <piotr_dec@msn.com>
Date: Fri, 19 Jul 2024 22:15:32 +0200
Subject: [PATCH] feat: Navigation observer

---
 .../main/java/eu/ztsh/garmin/MainActivity.kt  | 21 ++++++--
 .../java/eu/ztsh/garmin/mapbox/MapControl.kt  | 48 ++++++++++++++++++-
 .../ztsh/garmin/mapbox/NavigationObserver.kt  | 27 ++++++++++-
 app/src/main/res/layout/activity_main.xml     |  2 -
 4 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/app/src/main/java/eu/ztsh/garmin/MainActivity.kt b/app/src/main/java/eu/ztsh/garmin/MainActivity.kt
index a958c08..1e39f57 100644
--- a/app/src/main/java/eu/ztsh/garmin/MainActivity.kt
+++ b/app/src/main/java/eu/ztsh/garmin/MainActivity.kt
@@ -32,7 +32,8 @@ class MainActivity : AppCompatActivity() {
 
     private lateinit var binding: ActivityMainBinding
     private lateinit var mapControl: MapControl
-    private val navigationObserver = NavigationObserver()
+    private lateinit var navigationObserver: NavigationObserver
+    private lateinit var initThread: Thread
     val permissionsHelper = PermissionsHelper(WeakReference(this))
 
     init {
@@ -62,13 +63,27 @@ class MainActivity : AppCompatActivity() {
                         .build()
                 }
             }
-            MapboxNavigationApp.current()?.startTripSession()
-            mapControl = MapControl(this, binding.mapView, resources)
+            mapControl = MapControl(binding.mapView, resources)
             mapControl.init()
+            navigationObserver = NavigationObserver(mapControl)
         }
+        initThread = Thread {
+            while (true) {
+                if (MapboxNavigationApp.current() != null) {
+                    MapboxNavigationApp.current()!!.startTripSession()
+                    threadCallback()
+                }
+                Thread.sleep(100)
+            }
+        }
+        initThread.start()
         bluetoothInit()
     }
 
+    private fun threadCallback() {
+        initThread.join()
+    }
+
     override fun onStart() {
         super.onStart()
 //        MapboxNavigationApp.current()?.registerRouteProgressObserver(routeProgressObserver)
diff --git a/app/src/main/java/eu/ztsh/garmin/mapbox/MapControl.kt b/app/src/main/java/eu/ztsh/garmin/mapbox/MapControl.kt
index 255f95a..e00814f 100644
--- a/app/src/main/java/eu/ztsh/garmin/mapbox/MapControl.kt
+++ b/app/src/main/java/eu/ztsh/garmin/mapbox/MapControl.kt
@@ -2,6 +2,7 @@ package eu.ztsh.garmin.mapbox
 
 import android.content.res.Resources
 import android.util.Log
+import com.mapbox.api.directions.v5.models.RouteOptions
 import com.mapbox.maps.EdgeInsets
 import com.mapbox.maps.MapView
 import com.mapbox.maps.Style
@@ -10,12 +11,45 @@ import com.mapbox.maps.plugin.locationcomponent.location
 import com.mapbox.maps.plugin.viewport.data.FollowPuckViewportStateOptions
 import com.mapbox.maps.plugin.viewport.state.FollowPuckViewportState
 import com.mapbox.maps.plugin.viewport.viewport
-import eu.ztsh.garmin.MainActivity
+import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
+import com.mapbox.navigation.base.route.NavigationRoute
+import com.mapbox.navigation.base.route.NavigationRouterCallback
+import com.mapbox.navigation.base.route.RouterFailure
+import com.mapbox.navigation.base.route.RouterOrigin
+import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
+import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
+import com.mapbox.navigation.utils.internal.toPoint
+
+class MapControl(val mapView: MapView, private val resources: Resources) {
+
+    val navigationLocationProvider = NavigationLocationProvider()
+
+    val routesRequestCallback = object : NavigationRouterCallback {
+        override fun onRoutesReady(routes: List<NavigationRoute>, @RouterOrigin routerOrigin: String) {
+            MapboxNavigationApp.current()?.setNavigationRoutes(routes)
+        }
+
+        override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
+            Log.e(TAG, "onFailure: ")
+        }
+
+        override fun onCanceled(routeOptions: RouteOptions, @RouterOrigin routerOrigin: String) {
+            Log.w(TAG, "onCanceled: ")
+        }
+    }
+
 
-class MapControl(private val context: MainActivity, private val mapView: MapView, private val resources: Resources) {
 
     fun init() {
         mapView.mapboxMap.loadStyle(Style.TRAFFIC_DAY) // TODO: base on sun position
+
+        mapView.location.apply {
+//            locationProvider = this.getLocationProvider()
+//            setLocationProvider(navigationLocationProvider)
+            puckBearingEnabled = true
+            enabled = true
+        }
+
         follow(true)
         setGestures(mapView)
     }
@@ -52,6 +86,16 @@ class MapControl(private val context: MainActivity, private val mapView: MapView
                 }
                 true
             }
+            addOnMapLongClickListener { point ->
+                MapboxNavigationApp.current()?.requestRoutes(
+                    RouteOptions.builder()
+                        .applyDefaultNavigationOptions()
+                        .coordinatesList(mutableListOf(navigationLocationProvider.lastLocation!!.toPoint(), point))
+                        .build(),
+                    routesRequestCallback
+                )
+                true
+            }
         }
     }
 
diff --git a/app/src/main/java/eu/ztsh/garmin/mapbox/NavigationObserver.kt b/app/src/main/java/eu/ztsh/garmin/mapbox/NavigationObserver.kt
index 663818a..8d892ab 100644
--- a/app/src/main/java/eu/ztsh/garmin/mapbox/NavigationObserver.kt
+++ b/app/src/main/java/eu/ztsh/garmin/mapbox/NavigationObserver.kt
@@ -1,16 +1,41 @@
 package eu.ztsh.garmin.mapbox
 
 import android.util.Log
+import com.mapbox.common.location.Location
 import com.mapbox.navigation.core.MapboxNavigation
 import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
+import com.mapbox.navigation.core.trip.session.LocationMatcherResult
+import com.mapbox.navigation.core.trip.session.LocationObserver
+import com.mapbox.navigation.ui.maps.camera.data.MapboxNavigationViewportDataSource
 
-class NavigationObserver : MapboxNavigationObserver {
+class NavigationObserver(private val mapControl: MapControl) : MapboxNavigationObserver {
+
+    private val viewportDataSource = MapboxNavigationViewportDataSource(mapControl.mapView.mapboxMap)
+
+    private val locationObserver = object : LocationObserver {
+
+        override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
+            mapControl.navigationLocationProvider.changePosition(
+                location = locationMatcherResult.enhancedLocation,
+                keyPoints = locationMatcherResult.keyPoints
+            )
+            viewportDataSource.onLocationChanged(locationMatcherResult.enhancedLocation)
+            viewportDataSource.evaluate()
+        }
+
+        override fun onNewRawLocation(rawLocation: Location) {
+            println()
+        }
+
+    }
 
     override fun onAttached(mapboxNavigation: MapboxNavigation) {
+        mapboxNavigation.registerLocationObserver(locationObserver)
         Log.d(TAG, "Attached")
     }
 
     override fun onDetached(mapboxNavigation: MapboxNavigation) {
+        mapboxNavigation.unregisterLocationObserver(locationObserver)
         Log.d(TAG, "Detached")
     }
 
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 8bcf23b..7b7292a 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,6 +5,4 @@
                          android:id="@+id/mapView"
                          android:layout_width="match_parent"
                          android:layout_height="match_parent"
-                         mapbox:mapbox_locationComponentEnabled = "true"
-                         mapbox:mapbox_locationComponentPuckBearingEnabled = "true"
                          tools:context=".MainActivity" />