Also watch step counter movement, notification icon by status.
This commit is contained in:
parent
59389accc5
commit
6ad4c2dbe5
7 changed files with 178 additions and 154 deletions
|
@ -5,6 +5,7 @@
|
||||||
<!-- USE GPS AND NETWORK - EXCLUDE NON-GPS DEVICES -->
|
<!-- USE GPS AND NETWORK - EXCLUDE NON-GPS DEVICES -->
|
||||||
<uses-feature android:name="android.hardware.location.gps" android:required="true" />
|
<uses-feature android:name="android.hardware.location.gps" android:required="true" />
|
||||||
<uses-feature android:name="android.hardware.location.network" />
|
<uses-feature android:name="android.hardware.location.network" />
|
||||||
|
<uses-feature android:name="android.hardware.sensor.stepcounter" />
|
||||||
|
|
||||||
<!-- NORMAL PERMISSIONS, automatically granted -->
|
<!-- NORMAL PERMISSIONS, automatically granted -->
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
|
||||||
<!-- DANGEROUS PERMISSIONS, must request -->
|
<!-- DANGEROUS PERMISSIONS, must request -->
|
||||||
|
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
|
@ -26,6 +26,11 @@ object Keys {
|
||||||
// application name
|
// application name
|
||||||
const val APPLICATION_NAME: String = "trkpt"
|
const val APPLICATION_NAME: String = "trkpt"
|
||||||
|
|
||||||
|
// axioms
|
||||||
|
const val ONE_SECOND_IN_MILLISECONDS: Long = 1000
|
||||||
|
const val ONE_MINUTE_IN_MILLISECONDS: Long = 60 * ONE_SECOND_IN_MILLISECONDS
|
||||||
|
const val ONE_HOUR_IN_MILLISECONDS: Long = 60 * ONE_MINUTE_IN_MILLISECONDS
|
||||||
|
|
||||||
// version numbers
|
// version numbers
|
||||||
const val CURRENT_TRACK_FORMAT_VERSION: Int = 4
|
const val CURRENT_TRACK_FORMAT_VERSION: Int = 4
|
||||||
const val DATABASE_VERSION: Int = 1
|
const val DATABASE_VERSION: Int = 1
|
||||||
|
@ -63,6 +68,9 @@ object Keys {
|
||||||
// states
|
// states
|
||||||
const val STATE_TRACKING_STOPPED: Int = 0
|
const val STATE_TRACKING_STOPPED: Int = 0
|
||||||
const val STATE_TRACKING_ACTIVE: Int = 1
|
const val STATE_TRACKING_ACTIVE: Int = 1
|
||||||
|
const val LOCATION_INTERVAL_FULL_POWER: Long = 0
|
||||||
|
const val LOCATION_INTERVAL_SLEEP: Long = ONE_MINUTE_IN_MILLISECONDS
|
||||||
|
const val LOCATION_INTERVAL_GIVE_UP: Long = -1
|
||||||
const val STATE_THEME_FOLLOW_SYSTEM: String = "stateFollowSystem"
|
const val STATE_THEME_FOLLOW_SYSTEM: String = "stateFollowSystem"
|
||||||
const val STATE_THEME_LIGHT_MODE: String = "stateLightMode"
|
const val STATE_THEME_LIGHT_MODE: String = "stateLightMode"
|
||||||
const val STATE_THEME_DARK_MODE: String = "stateDarkMode"
|
const val STATE_THEME_DARK_MODE: String = "stateDarkMode"
|
||||||
|
@ -85,9 +93,6 @@ object Keys {
|
||||||
|
|
||||||
// default values
|
// default values
|
||||||
val DEFAULT_DATE: Date = Date(0L)
|
val DEFAULT_DATE: Date = Date(0L)
|
||||||
const val ONE_SECOND_IN_MILLISECONDS: Long = 1000
|
|
||||||
const val ONE_MINUTE_IN_MILLISECONDS: Long = 60 * ONE_SECOND_IN_MILLISECONDS
|
|
||||||
const val ONE_HOUR_IN_MILLISECONDS: Long = 60 * ONE_MINUTE_IN_MILLISECONDS
|
|
||||||
const val EMPTY_STRING_RESOURCE: Int = 0
|
const val EMPTY_STRING_RESOURCE: Int = 0
|
||||||
const val REQUEST_CURRENT_LOCATION_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS
|
const val REQUEST_CURRENT_LOCATION_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS
|
||||||
const val SAVE_TEMP_TRACK_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS
|
const val SAVE_TEMP_TRACK_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS
|
||||||
|
|
|
@ -107,6 +107,7 @@ class MainActivity: AppCompatActivity()
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION,
|
||||||
)
|
)
|
||||||
val permissions_needed = ArrayList<String>()
|
val permissions_needed = ArrayList<String>()
|
||||||
for (permission in permissions_wanted)
|
for (permission in permissions_wanted)
|
||||||
|
|
|
@ -71,7 +71,6 @@ class MapFragment : Fragment()
|
||||||
lateinit var zoom_out_button: FloatingActionButton
|
lateinit var zoom_out_button: FloatingActionButton
|
||||||
lateinit var currentLocationButton: FloatingActionButton
|
lateinit var currentLocationButton: FloatingActionButton
|
||||||
lateinit var map_current_time: TextView
|
lateinit var map_current_time: TextView
|
||||||
lateinit var power_level_indicator: ImageButton
|
|
||||||
private var current_track_overlay: Polyline? = null
|
private var current_track_overlay: Polyline? = null
|
||||||
private var current_position_overlays = ArrayList<Overlay>()
|
private var current_position_overlays = ArrayList<Overlay>()
|
||||||
private var homepoints_overlays = ArrayList<Overlay>()
|
private var homepoints_overlays = ArrayList<Overlay>()
|
||||||
|
@ -113,7 +112,6 @@ class MapFragment : Fragment()
|
||||||
zoom_in_button = rootView.findViewById(R.id.zoom_in_button)
|
zoom_in_button = rootView.findViewById(R.id.zoom_in_button)
|
||||||
zoom_out_button = rootView.findViewById(R.id.zoom_out_button)
|
zoom_out_button = rootView.findViewById(R.id.zoom_out_button)
|
||||||
map_current_time = rootView.findViewById(R.id.map_current_time)
|
map_current_time = rootView.findViewById(R.id.map_current_time)
|
||||||
power_level_indicator = rootView.findViewById(R.id.power_level_indicator)
|
|
||||||
mainButton = rootView.findViewById(R.id.main_button)
|
mainButton = rootView.findViewById(R.id.main_button)
|
||||||
locationErrorBar = Snackbar.make(mapView, String(), Snackbar.LENGTH_INDEFINITE)
|
locationErrorBar = Snackbar.make(mapView, String(), Snackbar.LENGTH_INDEFINITE)
|
||||||
|
|
||||||
|
@ -390,38 +388,74 @@ class MapFragment : Fragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark current position on map */
|
/* Mark current position on map */
|
||||||
fun create_current_position_overlays(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
|
fun create_current_position_overlays()
|
||||||
{
|
{
|
||||||
clear_current_position_overlays()
|
clear_current_position_overlays()
|
||||||
|
|
||||||
val locationIsOld: Boolean = !(isRecentEnough(location))
|
val tracker = trackerService
|
||||||
|
if (tracker == null)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val locationIsOld: Boolean = !(isRecentEnough(tracker.currentBestLocation))
|
||||||
|
|
||||||
val newMarker: Drawable
|
val newMarker: Drawable
|
||||||
val fillcolor: Int
|
val fillcolor: Int
|
||||||
if (locationIsOld)
|
val description: String
|
||||||
|
if (tracker.listeners_enabled_at == 0L)
|
||||||
|
{
|
||||||
|
fillcolor = Color.argb(64, 0, 0, 0)
|
||||||
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_skull_24dp)!!
|
||||||
|
description = "No location listeners are enabled"
|
||||||
|
}
|
||||||
|
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE && tracker.location_interval == Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
|
{
|
||||||
|
fillcolor = Color.argb(64, 0, 0, 0)
|
||||||
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_skull_24dp)!!
|
||||||
|
description = "GPS is struggling; disabled until movement"
|
||||||
|
}
|
||||||
|
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE && tracker.location_interval == Keys.LOCATION_INTERVAL_SLEEP)
|
||||||
|
{
|
||||||
|
fillcolor = Color.argb(64, 220, 61, 51)
|
||||||
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_sleep_24dp)!!
|
||||||
|
description = "GPS sleeping until movement"
|
||||||
|
}
|
||||||
|
else if (locationIsOld)
|
||||||
{
|
{
|
||||||
fillcolor = Color.argb(64, 0, 0, 0)
|
fillcolor = Color.argb(64, 0, 0, 0)
|
||||||
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_black_24dp)!!
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_black_24dp)!!
|
||||||
|
description = "GPS tracking at full power"
|
||||||
}
|
}
|
||||||
else if (trackingState == Keys.STATE_TRACKING_ACTIVE)
|
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE)
|
||||||
{
|
{
|
||||||
fillcolor = Color.argb(64, 220, 61, 51)
|
fillcolor = Color.argb(64, 220, 61, 51)
|
||||||
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_red_24dp)!!
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_red_24dp)!!
|
||||||
|
description = "GPS tracking at full power"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fillcolor = Color.argb(64, 60, 152, 219)
|
fillcolor = Color.argb(64, 60, 152, 219)
|
||||||
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_blue_24dp)!!
|
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_blue_24dp)!!
|
||||||
|
description = "GPS tracking at full power"
|
||||||
}
|
}
|
||||||
|
|
||||||
val current_location_radius = Polygon()
|
val current_location_radius = Polygon()
|
||||||
current_location_radius.points = Polygon.pointsAsCircle(GeoPoint(location.latitude, location.longitude), location.accuracy.toDouble())
|
current_location_radius.points = Polygon.pointsAsCircle(
|
||||||
|
GeoPoint(tracker.currentBestLocation.latitude, tracker.currentBestLocation.longitude),
|
||||||
|
tracker.currentBestLocation.accuracy.toDouble()
|
||||||
|
)
|
||||||
current_location_radius.fillPaint.color = fillcolor
|
current_location_radius.fillPaint.color = fillcolor
|
||||||
current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0)
|
current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0)
|
||||||
current_position_overlays.add(current_location_radius)
|
current_position_overlays.add(current_location_radius)
|
||||||
|
|
||||||
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
|
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
|
||||||
val overlayItem: OverlayItem = createOverlayItem(requireContext(), location.latitude, location.longitude, location.accuracy, location.provider.toString(), location.time)
|
val overlayItem: OverlayItem = createOverlayItem(
|
||||||
|
tracker.currentBestLocation.latitude,
|
||||||
|
tracker.currentBestLocation.longitude,
|
||||||
|
title="Current location",
|
||||||
|
description=description,
|
||||||
|
)
|
||||||
overlayItem.setMarker(newMarker)
|
overlayItem.setMarker(newMarker)
|
||||||
overlayItems.add(overlayItem)
|
overlayItems.add(overlayItem)
|
||||||
current_position_overlays.add(createOverlay(requireContext(), overlayItems))
|
current_position_overlays.add(createOverlay(requireContext(), overlayItems))
|
||||||
|
@ -478,12 +512,10 @@ class MapFragment : Fragment()
|
||||||
|
|
||||||
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
|
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
|
||||||
val overlayItem: OverlayItem = createOverlayItem(
|
val overlayItem: OverlayItem = createOverlayItem(
|
||||||
context,
|
|
||||||
homepoint.location.latitude,
|
homepoint.location.latitude,
|
||||||
homepoint.location.longitude,
|
homepoint.location.longitude,
|
||||||
homepoint.location.accuracy,
|
title=homepoint.name,
|
||||||
homepoint.location.provider.toString(),
|
description="Radius ${homepoint.radius}"
|
||||||
homepoint.location.time
|
|
||||||
)
|
)
|
||||||
overlayItem.setMarker(newMarker)
|
overlayItem.setMarker(newMarker)
|
||||||
overlayItems.add(overlayItem)
|
overlayItems.add(overlayItem)
|
||||||
|
@ -615,7 +647,7 @@ class MapFragment : Fragment()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
create_current_position_overlays(tracker.currentBestLocation, tracker.trackingState)
|
create_current_position_overlays()
|
||||||
if (current_track_overlay == null)
|
if (current_track_overlay == null)
|
||||||
{
|
{
|
||||||
create_track_overlay()
|
create_track_overlay()
|
||||||
|
@ -629,28 +661,7 @@ class MapFragment : Fragment()
|
||||||
|
|
||||||
map_current_time.text = iso8601_local_noms(tracker.currentBestLocation.time)
|
map_current_time.text = iso8601_local_noms(tracker.currentBestLocation.time)
|
||||||
|
|
||||||
|
mapView.invalidate()
|
||||||
if (tracker.location_interval == tracker.LOCATION_INTERVAL_FULL_POWER)
|
|
||||||
{
|
|
||||||
power_level_indicator.setImageResource(R.drawable.ic_satellite_24dp)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
power_level_indicator.tooltipText = "GPS tracking at full power"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tracker.location_interval == tracker.LOCATION_INTERVAL_SLEEP)
|
|
||||||
{
|
|
||||||
power_level_indicator.setImageResource(R.drawable.ic_sleep_24dp)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
power_level_indicator.tooltipText = "GPS sleeping until movement"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tracker.location_interval == tracker.LOCATION_INTERVAL_GIVE_UP)
|
|
||||||
{
|
|
||||||
power_level_indicator.setImageResource(R.drawable.ic_skull_24dp)
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
power_level_indicator.tooltipText = "GPS is struggling; disabled until movement"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val redraw_runnable: Runnable = object : Runnable
|
val redraw_runnable: Runnable = object : Runnable
|
||||||
|
|
|
@ -31,10 +31,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.hardware.Sensor
|
import android.hardware.*
|
||||||
import android.hardware.SensorManager
|
|
||||||
import android.hardware.TriggerEvent
|
|
||||||
import android.hardware.TriggerEventListener
|
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.location.LocationListener
|
import android.location.LocationListener
|
||||||
import android.location.LocationManager
|
import android.location.LocationManager
|
||||||
|
@ -68,9 +65,9 @@ class TrackerService: Service()
|
||||||
var last_significant_motion: Long = 0
|
var last_significant_motion: Long = 0
|
||||||
var arrived_at_home: Long = 0
|
var arrived_at_home: Long = 0
|
||||||
var location_interval: Long = 0
|
var location_interval: Long = 0
|
||||||
val LOCATION_INTERVAL_FULL_POWER: Long = 0
|
val TIME_UNTIL_SLEEP: Long = 2 * Keys.ONE_MINUTE_IN_MILLISECONDS
|
||||||
val LOCATION_INTERVAL_SLEEP: Long = Keys.ONE_MINUTE_IN_MILLISECONDS
|
val TIME_UNTIL_GIVE_UP: Long = 3 * Keys.ONE_MINUTE_IN_MILLISECONDS
|
||||||
val LOCATION_INTERVAL_GIVE_UP: Long = -1
|
val WATCHDOG_INTERVAL: Long = 30 * Keys.ONE_SECOND_IN_MILLISECONDS
|
||||||
private val RECENT_TRKPT_COUNT = 3600
|
private val RECENT_TRKPT_COUNT = 3600
|
||||||
private val DISPLACEMENT_LOCATION_COUNT = 5
|
private val DISPLACEMENT_LOCATION_COUNT = 5
|
||||||
lateinit var recent_displacement_locations: Deque<Location>
|
lateinit var recent_displacement_locations: Deque<Location>
|
||||||
|
@ -94,27 +91,23 @@ class TrackerService: Service()
|
||||||
|
|
||||||
private lateinit var sensor_manager: SensorManager
|
private lateinit var sensor_manager: SensorManager
|
||||||
private var significant_motion_sensor: Sensor? = null
|
private var significant_motion_sensor: Sensor? = null
|
||||||
|
private var step_counter_sensor: Sensor? = null
|
||||||
|
var has_motion_sensor: Boolean = false
|
||||||
|
|
||||||
private fun addGpsLocationListener(interval: Long)
|
private fun addGpsLocationListener(interval: Long): Boolean
|
||||||
{
|
{
|
||||||
if (! use_gps_location)
|
|
||||||
{
|
|
||||||
Log.i("VOUSSOIR", "Skipping GPS listener.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gpsProviderActive = isGpsEnabled(locationManager)
|
gpsProviderActive = isGpsEnabled(locationManager)
|
||||||
if (! gpsProviderActive)
|
if (! gpsProviderActive)
|
||||||
{
|
{
|
||||||
Log.w("VOUSSOIR", "Device GPS is not enabled.")
|
Log.w("VOUSSOIR", "Device GPS is not enabled.")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val has_permission: Boolean = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
val has_permission: Boolean = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
if (! has_permission)
|
if (! has_permission)
|
||||||
{
|
{
|
||||||
Log.w("VOUSSOIR", "Location permission is not granted.")
|
Log.w("VOUSSOIR", "Location permission is not granted.")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
locationManager.requestLocationUpdates(
|
locationManager.requestLocationUpdates(
|
||||||
|
@ -125,28 +118,23 @@ class TrackerService: Service()
|
||||||
)
|
)
|
||||||
gpsLocationListenerRegistered = true
|
gpsLocationListenerRegistered = true
|
||||||
Log.i("VOUSSOIR", "Added GPS location listener.")
|
Log.i("VOUSSOIR", "Added GPS location listener.")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNetworkLocationListener(interval: Long)
|
private fun addNetworkLocationListener(interval: Long): Boolean
|
||||||
{
|
{
|
||||||
if (! use_network_location)
|
|
||||||
{
|
|
||||||
Log.i("VOUSSOIR", "Skipping Network listener.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
networkProviderActive = isNetworkEnabled(locationManager)
|
networkProviderActive = isNetworkEnabled(locationManager)
|
||||||
if (!networkProviderActive)
|
if (!networkProviderActive)
|
||||||
{
|
{
|
||||||
Log.w("VOUSSOIR", "Unable to add Network location listener.")
|
Log.w("VOUSSOIR", "Unable to add Network location listener.")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val has_permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
val has_permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
||||||
if (! has_permission)
|
if (! has_permission)
|
||||||
{
|
{
|
||||||
Log.w("VOUSSOIR", "Unable to add Network location listener. Location permission is not granted.")
|
Log.w("VOUSSOIR", "Unable to add Network location listener. Location permission is not granted.")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
locationManager.requestLocationUpdates(
|
locationManager.requestLocationUpdates(
|
||||||
|
@ -157,6 +145,7 @@ class TrackerService: Service()
|
||||||
)
|
)
|
||||||
networkLocationListenerRegistered = true
|
networkLocationListenerRegistered = true
|
||||||
Log.i("VOUSSOIR", "Added Network location listener.")
|
Log.i("VOUSSOIR", "Added Network location listener.")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeGpsLocationListener()
|
fun removeGpsLocationListener()
|
||||||
|
@ -193,19 +182,17 @@ class TrackerService: Service()
|
||||||
location_interval = interval
|
location_interval = interval
|
||||||
var gps_added = false
|
var gps_added = false
|
||||||
var network_added = false
|
var network_added = false
|
||||||
if (use_gps_location && interval != LOCATION_INTERVAL_GIVE_UP)
|
if (use_gps_location && interval != Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
{
|
{
|
||||||
addGpsLocationListener(interval)
|
gps_added = addGpsLocationListener(interval)
|
||||||
gps_added = true
|
|
||||||
}
|
}
|
||||||
else if (gpsLocationListenerRegistered)
|
else if (gpsLocationListenerRegistered)
|
||||||
{
|
{
|
||||||
removeGpsLocationListener()
|
removeGpsLocationListener()
|
||||||
}
|
}
|
||||||
if (use_network_location && interval != LOCATION_INTERVAL_GIVE_UP)
|
if (use_network_location && interval != Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
{
|
{
|
||||||
addNetworkLocationListener(interval)
|
network_added = addNetworkLocationListener(interval)
|
||||||
network_added = true
|
|
||||||
}
|
}
|
||||||
else if (networkLocationListenerRegistered)
|
else if (networkLocationListenerRegistered)
|
||||||
{
|
{
|
||||||
|
@ -219,7 +206,9 @@ class TrackerService: Service()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
listeners_enabled_at = 0
|
listeners_enabled_at = 0
|
||||||
|
location_interval = Keys.LOCATION_INTERVAL_GIVE_UP
|
||||||
}
|
}
|
||||||
|
displayNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createLocationListener(): LocationListener
|
private fun createLocationListener(): LocationListener
|
||||||
|
@ -277,16 +266,20 @@ class TrackerService: Service()
|
||||||
Log.i("VOUSSOIR", "Arrived at home.")
|
Log.i("VOUSSOIR", "Arrived at home.")
|
||||||
arrived_at_home = System.currentTimeMillis()
|
arrived_at_home = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
else if (location_interval == LOCATION_INTERVAL_SLEEP || significant_motion_sensor == null)
|
else if (location_interval == Keys.LOCATION_INTERVAL_SLEEP)
|
||||||
{
|
{
|
||||||
// If we are already asleep, do not reset the listeners again because
|
// If we are already asleep, do not reset the listeners again because
|
||||||
// that immediately fetches a new location.
|
// that immediately fetches a new location.
|
||||||
// If we cannot rely on the motion sensor, then don't sleep!
|
|
||||||
}
|
}
|
||||||
else if (allow_sleep && (System.currentTimeMillis() - arrived_at_home) > Keys.ONE_MINUTE_IN_MILLISECONDS)
|
else if (
|
||||||
|
allow_sleep &&
|
||||||
|
has_motion_sensor &&
|
||||||
|
(System.currentTimeMillis() - arrived_at_home) > TIME_UNTIL_SLEEP &&
|
||||||
|
(System.currentTimeMillis() - last_significant_motion) > TIME_UNTIL_SLEEP
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "Staying at home, sleeping.")
|
Log.i("VOUSSOIR", "Staying at home, sleeping.")
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_SLEEP)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_SLEEP)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -295,7 +288,7 @@ class TrackerService: Service()
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "Leaving home.")
|
Log.i("VOUSSOIR", "Leaving home.")
|
||||||
arrived_at_home = 0
|
arrived_at_home = 0
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! isRecentEnough(location))
|
if (! isRecentEnough(location))
|
||||||
|
@ -365,31 +358,41 @@ class TrackerService: Service()
|
||||||
|
|
||||||
private fun displayNotification(): Notification
|
private fun displayNotification(): Notification
|
||||||
{
|
{
|
||||||
val timestamp = iso8601_local_noms(currentBestLocation.time)
|
notification_builder.setWhen(currentBestLocation.time)
|
||||||
if (shouldCreateNotificationChannel())
|
if (shouldCreateNotificationChannel())
|
||||||
{
|
{
|
||||||
createNotificationChannel()
|
createNotificationChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location_interval == LOCATION_INTERVAL_SLEEP)
|
val timestamp = iso8601_local_noms(currentBestLocation.time)
|
||||||
|
if (trackingState == Keys.STATE_TRACKING_ACTIVE)
|
||||||
{
|
{
|
||||||
notification_builder.setContentText("${timestamp} (sleeping)")
|
notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_running))
|
||||||
|
if (location_interval == Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
|
{
|
||||||
|
notification_builder.setContentTitle("${timestamp} (recording)")
|
||||||
|
notification_builder.setSmallIcon(R.drawable.ic_satellite_24dp)
|
||||||
|
}
|
||||||
|
else if (location_interval == Keys.LOCATION_INTERVAL_SLEEP)
|
||||||
|
{
|
||||||
|
notification_builder.setContentTitle("${timestamp} (sleeping)")
|
||||||
|
notification_builder.setSmallIcon(R.drawable.ic_sleep_24dp)
|
||||||
|
}
|
||||||
|
else if (location_interval == Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
|
{
|
||||||
|
notification_builder.setContentTitle("${timestamp} (deadzone)")
|
||||||
|
notification_builder.setSmallIcon(R.drawable.ic_skull_24dp)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
notification_builder.setContentText(timestamp)
|
notification_builder.setContentText(timestamp)
|
||||||
|
notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_record_inactive_24dp)
|
||||||
}
|
}
|
||||||
notification_builder.setWhen(currentBestLocation.time)
|
|
||||||
|
|
||||||
if (trackingState == Keys.STATE_TRACKING_ACTIVE)
|
|
||||||
{
|
|
||||||
notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_running))
|
|
||||||
notification_builder.setLargeIcon(AppCompatResources.getDrawable(this, R.drawable.ic_notification_icon_large_tracking_active_48dp)!!.toBitmap())
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_not_running))
|
notification_builder.setContentTitle("${timestamp} (stopped)")
|
||||||
notification_builder.setLargeIcon(AppCompatResources.getDrawable(this, R.drawable.ic_notification_icon_large_tracking_stopped_48dp)!!.toBitmap())
|
notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_stop_24dp)
|
||||||
}
|
}
|
||||||
|
|
||||||
val notification = notification_builder.build()
|
val notification = notification_builder.build()
|
||||||
|
@ -452,8 +455,9 @@ class TrackerService: Service()
|
||||||
Log.i("VOUSSOIR", "TrackerService.onBind")
|
Log.i("VOUSSOIR", "TrackerService.onBind")
|
||||||
if (listeners_enabled_at == 0L)
|
if (listeners_enabled_at == 0L)
|
||||||
{
|
{
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
|
displayNotification()
|
||||||
bound = true
|
bound = true
|
||||||
return binder
|
return binder
|
||||||
}
|
}
|
||||||
|
@ -464,8 +468,9 @@ class TrackerService: Service()
|
||||||
Log.i("VOUSSOIR", "TrackerService.onRebind")
|
Log.i("VOUSSOIR", "TrackerService.onRebind")
|
||||||
if (listeners_enabled_at == 0L)
|
if (listeners_enabled_at == 0L)
|
||||||
{
|
{
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
|
displayNotification()
|
||||||
bound = true
|
bound = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +483,7 @@ class TrackerService: Service()
|
||||||
// stop receiving location updates - if not tracking
|
// stop receiving location updates - if not tracking
|
||||||
if (trackingState != Keys.STATE_TRACKING_ACTIVE)
|
if (trackingState != Keys.STATE_TRACKING_ACTIVE)
|
||||||
{
|
{
|
||||||
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
}
|
}
|
||||||
// ensures onRebind is called
|
// ensures onRebind is called
|
||||||
return true
|
return true
|
||||||
|
@ -516,6 +521,52 @@ class TrackerService: Service()
|
||||||
currentBestLocation = getLastKnownLocation(this)
|
currentBestLocation = getLastKnownLocation(this)
|
||||||
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
|
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
|
|
||||||
|
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
|
has_motion_sensor = false
|
||||||
|
sensor_manager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||||
|
significant_motion_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
|
||||||
|
if (significant_motion_sensor != null)
|
||||||
|
{
|
||||||
|
val significant_motion_listener = object : TriggerEventListener() {
|
||||||
|
override fun onTrigger(event: TriggerEvent?) {
|
||||||
|
Log.i("VOUSSOIR", "Significant motion")
|
||||||
|
last_significant_motion = System.currentTimeMillis()
|
||||||
|
if (trackingState == Keys.STATE_TRACKING_ACTIVE && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
|
{
|
||||||
|
vibrator.vibrate(100)
|
||||||
|
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
|
}
|
||||||
|
sensor_manager.requestTriggerSensor(this, significant_motion_sensor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.i("VOUSSOIR", "Got significant motion sensor.")
|
||||||
|
sensor_manager.requestTriggerSensor(significant_motion_listener, significant_motion_sensor)
|
||||||
|
has_motion_sensor = true
|
||||||
|
}
|
||||||
|
|
||||||
|
step_counter_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
|
||||||
|
if (step_counter_sensor != null)
|
||||||
|
{
|
||||||
|
val step_counter_listener = object: SensorEventListener {
|
||||||
|
override fun onSensorChanged(event: SensorEvent?) {
|
||||||
|
Log.i("VOUSSOIR", "Step counter changed")
|
||||||
|
last_significant_motion = System.currentTimeMillis()
|
||||||
|
if (trackingState == Keys.STATE_TRACKING_ACTIVE && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
|
{
|
||||||
|
// beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150)
|
||||||
|
vibrator.vibrate(100)
|
||||||
|
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.i("VOUSSOIR", "Got step count sensor.")
|
||||||
|
sensor_manager.registerListener(step_counter_listener, step_counter_sensor, 5_000_000, 5_000_000)
|
||||||
|
has_motion_sensor = true
|
||||||
|
}
|
||||||
|
|
||||||
handler.post(background_watchdog)
|
handler.post(background_watchdog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,28 +575,6 @@ class TrackerService: Service()
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "TrackerService.onStartCommand")
|
Log.i("VOUSSOIR", "TrackerService.onStartCommand")
|
||||||
|
|
||||||
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
|
||||||
sensor_manager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
|
||||||
significant_motion_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
|
|
||||||
if (significant_motion_sensor != null)
|
|
||||||
{
|
|
||||||
val triggerEventListener = object : TriggerEventListener() {
|
|
||||||
override fun onTrigger(event: TriggerEvent?) {
|
|
||||||
Log.i("VOUSSOIR", "Significant motion")
|
|
||||||
last_significant_motion = System.currentTimeMillis()
|
|
||||||
arrived_at_home = 0L
|
|
||||||
if (location_interval != LOCATION_INTERVAL_FULL_POWER)
|
|
||||||
{
|
|
||||||
// beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150)
|
|
||||||
vibrator.vibrate(100)
|
|
||||||
reset_location_listeners(LOCATION_INTERVAL_FULL_POWER)
|
|
||||||
}
|
|
||||||
sensor_manager.requestTriggerSensor(this, significant_motion_sensor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sensor_manager.requestTriggerSensor(triggerEventListener, significant_motion_sensor)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SERVICE RESTART (via START_STICKY)
|
// SERVICE RESTART (via START_STICKY)
|
||||||
if (intent == null)
|
if (intent == null)
|
||||||
{
|
{
|
||||||
|
@ -580,7 +609,7 @@ class TrackerService: Service()
|
||||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
notificationManager.cancel(Keys.TRACKER_SERVICE_NOTIFICATION_ID) // this call was not necessary prior to Android 12
|
notificationManager.cancel(Keys.TRACKER_SERVICE_NOTIFICATION_ID) // this call was not necessary prior to Android 12
|
||||||
PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
|
PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
handler.removeCallbacks(background_watchdog)
|
handler.removeCallbacks(background_watchdog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,7 +617,7 @@ class TrackerService: Service()
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "TrackerService.startTracking")
|
Log.i("VOUSSOIR", "TrackerService.startTracking")
|
||||||
arrived_at_home = 0
|
arrived_at_home = 0
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
trackingState = Keys.STATE_TRACKING_ACTIVE
|
trackingState = Keys.STATE_TRACKING_ACTIVE
|
||||||
PreferencesHelper.saveTrackingState(trackingState)
|
PreferencesHelper.saveTrackingState(trackingState)
|
||||||
recent_displacement_locations.clear()
|
recent_displacement_locations.clear()
|
||||||
|
@ -600,7 +629,7 @@ class TrackerService: Service()
|
||||||
Log.i("VOUSSOIR", "TrackerService.stopTracking")
|
Log.i("VOUSSOIR", "TrackerService.stopTracking")
|
||||||
trackbook.database.commit()
|
trackbook.database.commit()
|
||||||
arrived_at_home = 0
|
arrived_at_home = 0
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
trackingState = Keys.STATE_TRACKING_STOPPED
|
trackingState = Keys.STATE_TRACKING_STOPPED
|
||||||
PreferencesHelper.saveTrackingState(trackingState)
|
PreferencesHelper.saveTrackingState(trackingState)
|
||||||
recent_displacement_locations.clear()
|
recent_displacement_locations.clear()
|
||||||
|
@ -614,12 +643,12 @@ class TrackerService: Service()
|
||||||
Keys.PREF_LOCATION_GPS ->
|
Keys.PREF_LOCATION_GPS ->
|
||||||
{
|
{
|
||||||
use_gps_location = PreferencesHelper.load_location_gps()
|
use_gps_location = PreferencesHelper.load_location_gps()
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
Keys.PREF_LOCATION_NETWORK ->
|
Keys.PREF_LOCATION_NETWORK ->
|
||||||
{
|
{
|
||||||
use_network_location = PreferencesHelper.load_location_network()
|
use_network_location = PreferencesHelper.load_location_network()
|
||||||
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
Keys.PREF_USE_IMPERIAL_UNITS ->
|
Keys.PREF_USE_IMPERIAL_UNITS ->
|
||||||
{
|
{
|
||||||
|
@ -632,9 +661,9 @@ class TrackerService: Service()
|
||||||
Keys.PREF_ALLOW_SLEEP ->
|
Keys.PREF_ALLOW_SLEEP ->
|
||||||
{
|
{
|
||||||
allow_sleep = PreferencesHelper.loadAllowSleep()
|
allow_sleep = PreferencesHelper.loadAllowSleep()
|
||||||
if (! allow_sleep && location_interval != LOCATION_INTERVAL_FULL_POWER)
|
if (! allow_sleep && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
{
|
{
|
||||||
reset_location_listeners(LOCATION_INTERVAL_FULL_POWER)
|
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Keys.PREF_DEVICE_ID ->
|
Keys.PREF_DEVICE_ID ->
|
||||||
|
@ -649,28 +678,19 @@ class TrackerService: Service()
|
||||||
override fun run()
|
override fun run()
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "TrackerService.background_watchdog")
|
Log.i("VOUSSOIR", "TrackerService.background_watchdog")
|
||||||
handler.postDelayed(this, 30 * Keys.ONE_SECOND_IN_MILLISECONDS)
|
handler.postDelayed(this, WATCHDOG_INTERVAL)
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
val struggletime: Long
|
|
||||||
if (location_interval == LOCATION_INTERVAL_FULL_POWER)
|
|
||||||
{
|
|
||||||
struggletime = 2 * Keys.ONE_MINUTE_IN_MILLISECONDS
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struggletime = 4 * Keys.ONE_MINUTE_IN_MILLISECONDS
|
|
||||||
}
|
|
||||||
if (
|
if (
|
||||||
allow_sleep &&
|
allow_sleep &&
|
||||||
|
has_motion_sensor &&
|
||||||
trackingState == Keys.STATE_TRACKING_ACTIVE &&
|
trackingState == Keys.STATE_TRACKING_ACTIVE &&
|
||||||
location_interval != LOCATION_INTERVAL_GIVE_UP &&
|
location_interval != Keys.LOCATION_INTERVAL_GIVE_UP &&
|
||||||
significant_motion_sensor != null &&
|
(now - listeners_enabled_at) > TIME_UNTIL_GIVE_UP &&
|
||||||
(now - listeners_enabled_at) > struggletime &&
|
(now - currentBestLocation.time) > TIME_UNTIL_GIVE_UP &&
|
||||||
(now - currentBestLocation.time) > struggletime &&
|
(now - last_significant_motion) > TIME_UNTIL_GIVE_UP
|
||||||
(now - last_significant_motion) > struggletime
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
|
reset_location_listeners(Keys.LOCATION_INTERVAL_GIVE_UP)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,12 @@ fun create_start_end_markers(context: Context, map_view: MapView, startpoint: Tr
|
||||||
{
|
{
|
||||||
Log.i("VOUSSOIR", "MapOverlayHelper.create_start_end_markers")
|
Log.i("VOUSSOIR", "MapOverlayHelper.create_start_end_markers")
|
||||||
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
|
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
|
||||||
val startmarker: OverlayItem = createOverlayItem(context, startpoint.latitude, startpoint.longitude, startpoint.accuracy, startpoint.provider, startpoint.time)
|
val startmarker: OverlayItem = createOverlayItem(startpoint.latitude, startpoint.longitude, title="Start", iso8601_local_noms(startpoint.time))
|
||||||
startmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_48dp)!!)
|
startmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_48dp)!!)
|
||||||
overlayItems.add(startmarker)
|
overlayItems.add(startmarker)
|
||||||
if (startpoint != endpoint)
|
if (startpoint != endpoint)
|
||||||
{
|
{
|
||||||
val endmarker: OverlayItem = createOverlayItem(context, endpoint.latitude, endpoint.longitude, endpoint.accuracy, endpoint.provider, endpoint.time)
|
val endmarker: OverlayItem = createOverlayItem(endpoint.latitude, endpoint.longitude, title="End", description= iso8601_local_noms(endpoint.time))
|
||||||
endmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_48dp)!!)
|
endmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_48dp)!!)
|
||||||
overlayItems.add(endmarker)
|
overlayItems.add(endmarker)
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,8 @@ fun create_start_end_markers(context: Context, map_view: MapView, startpoint: Tr
|
||||||
return overlay
|
return overlay
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem
|
fun createOverlayItem(latitude: Double, longitude: Double, title: String, description: String): OverlayItem
|
||||||
{
|
{
|
||||||
val title = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"
|
|
||||||
val description = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
|
|
||||||
val position = GeoPoint(latitude, longitude)
|
val position = GeoPoint(latitude, longitude)
|
||||||
val item = OverlayItem(title, description, position)
|
val item = OverlayItem(title, description, position)
|
||||||
item.markerHotspot = OverlayItem.HotspotPlace.CENTER
|
item.markerHotspot = OverlayItem.HotspotPlace.CENTER
|
||||||
|
|
|
@ -97,19 +97,6 @@
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/power_level_indicator"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:src="@drawable/ic_satellite_24dp"
|
|
||||||
app:backgroundTint="@color/default_transparent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_satellite_24dp"
|
|
||||||
app:tint="@color/location_button_icon" />
|
|
||||||
|
|
||||||
<!-- GROUPS -->
|
<!-- GROUPS -->
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
Loading…
Reference in a new issue