Show current position on Track view.

This primarily helps when you want to use the "when was I here" button,
to remember a previous day when you were at the same location.

Besides that, seeing the current realtime location provides helpful
context to historical tracks.
master
voussoir 2023-12-24 22:23:27 -08:00
parent eb1ad45c4c
commit a04a0d3a3a
1 changed files with 98 additions and 4 deletions

View File

@ -21,12 +21,18 @@
package net.voussoir.trkpt package net.voussoir.trkpt
import YesNoDialog import YesNoDialog
import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.Dialog import android.app.Dialog
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.location.Location import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
@ -55,10 +61,7 @@ import org.osmdroid.events.ZoomEvent
import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.MapEventsOverlay import org.osmdroid.views.overlay.*
import org.osmdroid.views.overlay.Marker
import org.osmdroid.views.overlay.Polyline
import org.osmdroid.views.overlay.TilesOverlay
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions
import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme
@ -93,6 +96,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
var ready_to_straighten: Boolean = false var ready_to_straighten: Boolean = false
var track_query_start_time_previous: Int = 0 var track_query_start_time_previous: Int = 0
var track_query_end_time_previous: Int = 0 var track_query_end_time_previous: Int = 0
private lateinit var mapView: MapView private lateinit var mapView: MapView
private lateinit var controller: IMapController private lateinit var controller: IMapController
private lateinit var statisticsSheetBehavior: BottomSheetBehavior<View> private lateinit var statisticsSheetBehavior: BottomSheetBehavior<View>
@ -115,6 +119,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
private lateinit var track_segment_overlays: ArrayDeque<Polyline> private lateinit var track_segment_overlays: ArrayDeque<Polyline>
private var track_geopoints: MutableList<IGeoPoint> = mutableListOf() private var track_geopoints: MutableList<IGeoPoint> = mutableListOf()
private var track_points_overlay: SimpleFastPointOverlay? = null private var track_points_overlay: SimpleFastPointOverlay? = null
private var current_position_overlays = ArrayList<Overlay>()
// private lateinit var trkpt_infowindow: InfoWindow // private lateinit var trkpt_infowindow: InfoWindow
private var useImperialUnits: Boolean = false private var useImperialUnits: Boolean = false
private val handler: Handler = Handler(Looper.getMainLooper()) private val handler: Handler = Handler(Looper.getMainLooper())
@ -123,6 +128,10 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
var selected_trkpt: Trkpt? = null var selected_trkpt: Trkpt? = null
lateinit var selected_trkpt_marker: Marker lateinit var selected_trkpt_marker: Marker
private lateinit var locationManager: LocationManager
private lateinit var gpsLocationListener: LocationListener
private var gpslistenerregistered = false
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -178,6 +187,20 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
} }
controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL) controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL)
val has_permission: Boolean = ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (has_permission)
{
locationManager = requireContext().getSystemService(Context.LOCATION_SERVICE) as LocationManager
gpsLocationListener = createLocationListener()
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0,
0f,
gpsLocationListener,
)
gpslistenerregistered = true
}
// trkpt_infowindow = MarkerInfoWindow(R.layout.trkpt_infowindow, mapView) // trkpt_infowindow = MarkerInfoWindow(R.layout.trkpt_infowindow, mapView)
statisticsSheet = rootView.findViewById(R.id.statistics_sheet) statisticsSheet = rootView.findViewById(R.id.statistics_sheet)
@ -469,12 +492,78 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
return rootView return rootView
} }
override fun onDestroyView()
{
super.onDestroyView()
if (gpslistenerregistered)
{
locationManager.removeUpdates(gpsLocationListener)
gpslistenerregistered = false
}
}
fun clear_current_position_overlays()
{
for (ov in current_position_overlays)
{
if (ov in mapView.overlays)
{
mapView.overlays.remove(ov)
}
}
current_position_overlays.clear()
}
fun create_current_position_overlays(location: Location)
{
clear_current_position_overlays()
val newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_blue_24dp)!!
val fillcolor = Color.argb(64, 60, 152, 219)
val current_location_radius = Polygon()
current_location_radius.points = Polygon.pointsAsCircle(
GeoPoint(location.latitude, location.longitude),
location.accuracy.toDouble()
)
current_location_radius.fillPaint.color = fillcolor
current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0)
current_position_overlays.add(current_location_radius)
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
val overlayItem: OverlayItem = createOverlayItem(
location.latitude,
location.longitude,
title="Current location",
description="Current location",
)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
current_position_overlays.add(createOverlay(requireContext(), overlayItems))
for (ov in current_position_overlays)
{
mapView.overlays.add(ov)
}
}
/* Overrides onResume from Fragment */ /* Overrides onResume from Fragment */
override fun onResume() override fun onResume()
{ {
super.onResume() super.onResume()
} }
private fun createLocationListener(): LocationListener
{
return object : LocationListener
{
override fun onLocationChanged(location: Location)
{
create_current_position_overlays(location)
}
}
}
fun select_trkpt(trkpt: Trkpt) fun select_trkpt(trkpt: Trkpt)
{ {
selected_trkpt = trkpt selected_trkpt = trkpt
@ -658,6 +747,11 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
{ {
create_start_end_markers(requireContext(), mapView, pl.actualPoints.first() as Trkpt, pl.actualPoints.last() as Trkpt) create_start_end_markers(requireContext(), mapView, pl.actualPoints.first() as Trkpt, pl.actualPoints.last() as Trkpt)
} }
for (ov in current_position_overlays)
{
mapView.overlays.add(ov)
}
} }
fun new_track_segment_overlay(): Polyline fun new_track_segment_overlay(): Polyline