checkpoint

master
voussoir 2023-03-09 21:34:02 -08:00
parent df77b089ac
commit 04fa76249b
7 changed files with 197 additions and 191 deletions

View File

@ -58,7 +58,7 @@ class MapFragment : Fragment()
// https://gist.github.com/Dvik/a3de88d39da9d1d6d175025a56c5e797#file-viewextension-kt and // https://gist.github.com/Dvik/a3de88d39da9d1d6d175025a56c5e797#file-viewextension-kt and
// https://proandroiddev.com/android-full-screen-ui-with-transparent-status-bar-ef52f3adde63 // https://proandroiddev.com/android-full-screen-ui-with-transparent-status-bar-ef52f3adde63
// get current best location // get current best location
currentBestLocation = LocationHelper.getLastKnownLocation(activity as Context) currentBestLocation = getLastKnownLocation(activity as Context)
// get saved tracking state // get saved tracking state
trackingState = PreferencesHelper.loadTrackingState() trackingState = PreferencesHelper.loadTrackingState()
requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

View File

@ -20,7 +20,9 @@ import YesNoDialog
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.preference.* import androidx.preference.*
@ -118,6 +120,10 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
preferenceDeviceID.summary = getString(R.string.pref_device_id_summary) + "\n" + PreferencesHelper.load_device_id() preferenceDeviceID.summary = getString(R.string.pref_device_id_summary) + "\n" + PreferencesHelper.load_device_id()
preferenceDeviceID.setDefaultValue(random_device_id()) preferenceDeviceID.setDefaultValue(random_device_id())
preferenceCategoryGeneral.contains(preferenceDeviceID) preferenceCategoryGeneral.contains(preferenceDeviceID)
preferenceDeviceID.setOnPreferenceChangeListener { preference, newValue ->
preferenceDeviceID.summary = getString(R.string.pref_device_id_summary) + "\n" + newValue
return@setOnPreferenceChangeListener true
}
screen.addPreference(preferenceDeviceID) screen.addPreference(preferenceDeviceID)
val preferenceCategoryAbout: PreferenceCategory = PreferenceCategory(context) val preferenceCategoryAbout: PreferenceCategory = PreferenceCategory(context)

View File

@ -57,7 +57,7 @@ class TrackerService: Service(), SensorEventListener
var device_id: String = random_device_id() var device_id: String = random_device_id()
var recording_started: Date = GregorianCalendar.getInstance().time var recording_started: Date = GregorianCalendar.getInstance().time
var commitInterval: Int = Keys.COMMIT_INTERVAL var commitInterval: Int = Keys.COMMIT_INTERVAL
var currentBestLocation: Location = LocationHelper.getDefaultLocation() var currentBestLocation: Location = getDefaultLocation()
var lastCommit: Date = Keys.DEFAULT_DATE var lastCommit: Date = Keys.DEFAULT_DATE
var stepCountOffset: Float = 0f var stepCountOffset: Float = 0f
lateinit var track: Track lateinit var track: Track
@ -74,7 +74,6 @@ class TrackerService: Service(), SensorEventListener
private lateinit var gpsLocationListener: LocationListener private lateinit var gpsLocationListener: LocationListener
private lateinit var networkLocationListener: LocationListener private lateinit var networkLocationListener: LocationListener
/* Adds a GPS location listener to location manager */
private fun addGpsLocationListener() private fun addGpsLocationListener()
{ {
if (gpsLocationListenerRegistered) if (gpsLocationListenerRegistered)
@ -83,7 +82,7 @@ class TrackerService: Service(), SensorEventListener
return return
} }
gpsProviderActive = LocationHelper.isGpsEnabled(locationManager) gpsProviderActive = isGpsEnabled(locationManager)
if (! gpsProviderActive) if (! gpsProviderActive)
{ {
LogHelper.w(TAG, "Device GPS is not enabled.") LogHelper.w(TAG, "Device GPS is not enabled.")
@ -107,7 +106,6 @@ class TrackerService: Service(), SensorEventListener
LogHelper.v(TAG, "Added GPS location listener.") LogHelper.v(TAG, "Added GPS location listener.")
} }
/* Adds a Network location listener to location manager */
private fun addNetworkLocationListener() private fun addNetworkLocationListener()
{ {
if (gpsOnly) if (gpsOnly)
@ -122,7 +120,7 @@ class TrackerService: Service(), SensorEventListener
return return
} }
networkProviderActive = LocationHelper.isNetworkEnabled(locationManager) networkProviderActive = isNetworkEnabled(locationManager)
if (!networkProviderActive) if (!networkProviderActive)
{ {
LogHelper.w(TAG, "Unable to add Network location listener.") LogHelper.w(TAG, "Unable to add Network location listener.")
@ -151,7 +149,7 @@ class TrackerService: Service(), SensorEventListener
return object : LocationListener { return object : LocationListener {
override fun onLocationChanged(location: Location) override fun onLocationChanged(location: Location)
{ {
if (LocationHelper.isBetterLocation(location, currentBestLocation)) { if (isBetterLocation(location, currentBestLocation)) {
currentBestLocation = location currentBestLocation = location
} }
} }
@ -159,16 +157,16 @@ class TrackerService: Service(), SensorEventListener
{ {
LogHelper.v(TAG, "onProviderEnabled $provider") LogHelper.v(TAG, "onProviderEnabled $provider")
when (provider) { when (provider) {
LocationManager.GPS_PROVIDER -> gpsProviderActive = LocationHelper.isGpsEnabled(locationManager) LocationManager.GPS_PROVIDER -> gpsProviderActive = isGpsEnabled(locationManager)
LocationManager.NETWORK_PROVIDER -> networkProviderActive = LocationHelper.isNetworkEnabled(locationManager) LocationManager.NETWORK_PROVIDER -> networkProviderActive = isNetworkEnabled(locationManager)
} }
} }
override fun onProviderDisabled(provider: String) override fun onProviderDisabled(provider: String)
{ {
LogHelper.v(TAG, "onProviderDisabled $provider") LogHelper.v(TAG, "onProviderDisabled $provider")
when (provider) { when (provider) {
LocationManager.GPS_PROVIDER -> gpsProviderActive = LocationHelper.isGpsEnabled(locationManager) LocationManager.GPS_PROVIDER -> gpsProviderActive = isGpsEnabled(locationManager)
LocationManager.NETWORK_PROVIDER -> networkProviderActive = LocationHelper.isNetworkEnabled(locationManager) LocationManager.NETWORK_PROVIDER -> networkProviderActive = isNetworkEnabled(locationManager)
} }
} }
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?)
@ -179,7 +177,8 @@ class TrackerService: Service(), SensorEventListener
} }
/* Displays or updates notification */ /* Displays or updates notification */
private fun displayNotification(): Notification { private fun displayNotification(): Notification
{
val notification: Notification = notificationHelper.createNotification( val notification: Notification = notificationHelper.createNotification(
trackingState, trackingState,
iso8601(GregorianCalendar.getInstance().time) iso8601(GregorianCalendar.getInstance().time)
@ -189,7 +188,8 @@ class TrackerService: Service(), SensorEventListener
} }
/* Overrides onAccuracyChanged from SensorEventListener */ /* Overrides onAccuracyChanged from SensorEventListener */
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int)
{
LogHelper.v(TAG, "Accuracy changed: $accuracy") LogHelper.v(TAG, "Accuracy changed: $accuracy")
} }
@ -220,24 +220,24 @@ class TrackerService: Service(), SensorEventListener
sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationHelper = NotificationHelper(this) notificationHelper = NotificationHelper(this)
gpsProviderActive = LocationHelper.isGpsEnabled(locationManager) gpsProviderActive = isGpsEnabled(locationManager)
networkProviderActive = LocationHelper.isNetworkEnabled(locationManager) networkProviderActive = isNetworkEnabled(locationManager)
gpsLocationListener = createLocationListener() gpsLocationListener = createLocationListener()
networkLocationListener = createLocationListener() networkLocationListener = createLocationListener()
trackingState = PreferencesHelper.loadTrackingState() trackingState = PreferencesHelper.loadTrackingState()
currentBestLocation = LocationHelper.getLastKnownLocation(this) currentBestLocation = getLastKnownLocation(this)
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener) PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
} }
/* Overrides onDestroy from Service */ /* Overrides onDestroy from Service */
override fun onDestroy() { override fun onDestroy() {
LogHelper.i("VOUSSOIR", "TrackerService.onDestroy.")
super.onDestroy() super.onDestroy()
LogHelper.i(TAG, "onDestroy called.")
if (trackingState == Keys.STATE_TRACKING_ACTIVE) if (trackingState == Keys.STATE_TRACKING_ACTIVE)
{ {
pauseTracking() pauseTracking()
} }
stopForeground(true) 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)
removeGpsLocationListener() removeGpsLocationListener()
@ -316,7 +316,6 @@ class TrackerService: Service(), SensorEventListener
} }
} }
/* Adds location listeners to location manager */
fun removeNetworkLocationListener() fun removeNetworkLocationListener()
{ {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
@ -365,15 +364,14 @@ class TrackerService: Service(), SensorEventListener
stopForeground(STOP_FOREGROUND_DETACH) stopForeground(STOP_FOREGROUND_DETACH)
} }
/*
* Defines the listener for changes in shared preferences
*/
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key) { when (key)
{
Keys.PREF_GPS_ONLY -> Keys.PREF_GPS_ONLY ->
{ {
gpsOnly = PreferencesHelper.loadGpsOnly() gpsOnly = PreferencesHelper.loadGpsOnly()
when (gpsOnly) { when (gpsOnly)
{
true -> removeNetworkLocationListener() true -> removeNetworkLocationListener()
false -> addNetworkLocationListener() false -> addNetworkLocationListener()
} }
@ -418,12 +416,12 @@ class TrackerService: Service(), SensorEventListener
Log.i("VOUSSOIR", "Omitting due to 0,0 location.") Log.i("VOUSSOIR", "Omitting due to 0,0 location.")
return false return false
} }
if (! LocationHelper.isRecentEnough(location)) if (! isRecentEnough(location))
{ {
Log.i("VOUSSOIR", "Omitting due to not recent enough.") Log.i("VOUSSOIR", "Omitting due to not recent enough.")
return false return false
} }
if (! LocationHelper.isAccurateEnough(location, Keys.DEFAULT_THRESHOLD_LOCATION_ACCURACY)) if (! isAccurateEnough(location, Keys.DEFAULT_THRESHOLD_LOCATION_ACCURACY))
{ {
Log.i("VOUSSOIR", "Omitting due to not accurate enough.") Log.i("VOUSSOIR", "Omitting due to not accurate enough.")
return false return false
@ -440,7 +438,7 @@ class TrackerService: Service(), SensorEventListener
{ {
return true return true
} }
if (! LocationHelper.isDifferentEnough(track.trkpts.last().toLocation(), location, omitRests)) if (! isDifferentEnough(track.trkpts.last().toLocation(), location, omitRests))
{ {
Log.i("VOUSSOIR", "Omitting due to too close to previous.") Log.i("VOUSSOIR", "Omitting due to too close to previous.")
return false return false

View File

@ -17,7 +17,7 @@
package org.y20k.trackbook package org.y20k.trackbook
import android.location.Location import android.location.Location
import org.y20k.trackbook.helpers.LocationHelper import org.y20k.trackbook.helpers.getNumberOfSatellites
import java.util.* import java.util.*
/* /*
@ -42,7 +42,7 @@ data class Trkpt(
altitude=location.altitude, altitude=location.altitude,
accuracy=location.accuracy, accuracy=location.accuracy,
time=location.time, time=location.time,
numberSatellites=LocationHelper.getNumberOfSatellites(location), numberSatellites=getNumberOfSatellites(location),
) )
/* Converts WayPoint into Location */ /* Converts WayPoint into Location */

View File

@ -27,159 +27,163 @@ import androidx.core.content.ContextCompat
import org.y20k.trackbook.Keys import org.y20k.trackbook.Keys
import kotlin.math.pow import kotlin.math.pow
/* /* Get default location */
* Keys object fun getDefaultLocation(): Location
*/ {
object LocationHelper { val defaultLocation: Location = Location(LocationManager.NETWORK_PROVIDER)
defaultLocation.latitude = Keys.DEFAULT_LATITUDE
/* Define log tag */ defaultLocation.longitude = Keys.DEFAULT_LONGITUDE
private val TAG: String = LogHelper.makeLogTag(LocationHelper::class.java) defaultLocation.accuracy = Keys.DEFAULT_ACCURACY
defaultLocation.altitude = Keys.DEFAULT_ALTITUDE
/* Get default location */ defaultLocation.time = Keys.DEFAULT_DATE.time
fun getDefaultLocation(): Location { return defaultLocation
val defaultLocation: Location = Location(LocationManager.NETWORK_PROVIDER)
defaultLocation.latitude = Keys.DEFAULT_LATITUDE
defaultLocation.longitude = Keys.DEFAULT_LONGITUDE
defaultLocation.accuracy = Keys.DEFAULT_ACCURACY
defaultLocation.altitude = Keys.DEFAULT_ALTITUDE
defaultLocation.time = Keys.DEFAULT_DATE.time
return defaultLocation
}
/* Tries to return the last location that the system has stored */
fun getLastKnownLocation(context: Context): Location {
// get last location that Trackbook has stored
var lastKnownLocation: Location = PreferencesHelper.loadCurrentBestLocation()
// try to get the last location the system has stored - it is probably more recent
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val lastKnownLocationGps: Location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) ?: lastKnownLocation
val lastKnownLocationNetwork: Location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) ?: lastKnownLocation
when (isBetterLocation(lastKnownLocationGps, lastKnownLocationNetwork)) {
true -> lastKnownLocation = lastKnownLocationGps
false -> lastKnownLocation = lastKnownLocationNetwork
}
}
return lastKnownLocation
}
/* Determines whether one location reading is better than the current location fix */
fun isBetterLocation(location: Location, currentBestLocation: Location?): Boolean
{
// Credit: https://developer.android.com/guide/topics/location/strategies.html#BestEstimate
if (currentBestLocation == null) {
// a new location is always better than no location
return true
}
// check whether the new location fix is newer or older
val timeDelta: Long = location.time - currentBestLocation.time
val isSignificantlyNewer: Boolean = timeDelta > Keys.SIGNIFICANT_TIME_DIFFERENCE
val isSignificantlyOlder:Boolean = timeDelta < -Keys.SIGNIFICANT_TIME_DIFFERENCE
when {
// if it's been more than two minutes since the current location, use the new location because the user has likely moved
isSignificantlyNewer -> return true
// if the new location is more than two minutes older, it must be worse
isSignificantlyOlder -> return false
}
// check whether the new location fix is more or less accurate
val isNewer: Boolean = timeDelta > 0L
val accuracyDelta: Float = location.accuracy - currentBestLocation.accuracy
val isLessAccurate: Boolean = accuracyDelta > 0f
val isMoreAccurate: Boolean = accuracyDelta < 0f
val isSignificantlyLessAccurate: Boolean = accuracyDelta > 200f
// check if the old and new location are from the same provider
val isFromSameProvider: Boolean = location.provider == currentBestLocation.provider
// determine location quality using a combination of timeliness and accuracy
return when {
isMoreAccurate -> true
isNewer && !isLessAccurate -> true
isNewer && !isSignificantlyLessAccurate && isFromSameProvider -> true
else -> false
}
}
/* Checks if GPS location provider is available and enabled */
fun isGpsEnabled(locationManager: LocationManager): Boolean
{
if (locationManager.allProviders.contains(LocationManager.GPS_PROVIDER))
{
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
}
else
{
return false
}
}
/* Checks if Network location provider is available and enabled */
fun isNetworkEnabled(locationManager: LocationManager): Boolean {
if (locationManager.allProviders.contains(LocationManager.NETWORK_PROVIDER)) {
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
} else {
return false
}
}
/* Checks if given location is new */
fun isRecentEnough(location: Location): Boolean {
val locationAge: Long = SystemClock.elapsedRealtimeNanos() - location.elapsedRealtimeNanos
return locationAge < Keys.DEFAULT_THRESHOLD_LOCATION_AGE
}
/* Checks if given location is accurate */
fun isAccurateEnough(location: Location, locationAccuracyThreshold: Int): Boolean {
val isAccurate: Boolean
when (location.provider) {
LocationManager.GPS_PROVIDER -> isAccurate = location.accuracy < locationAccuracyThreshold
else -> isAccurate = location.accuracy < locationAccuracyThreshold + 10 // a bit more relaxed when location comes from network provider
}
return isAccurate
}
/* Checks if given location is different enough compared to previous location */
fun isDifferentEnough(previousLocation: Location?, location: Location, omitRests: Boolean): Boolean {
// check if previous location is (not) available
if (previousLocation == null)
{
return true
}
if (! omitRests)
{
return true
}
// location.accuracy is given as 1 standard deviation, with a 68% chance
// that the true position is within a circle of this radius.
// These formulas determine if the difference between the last point and
// new point is statistically significant.
val accuracy: Float = if (location.accuracy != 0.0f) location.accuracy else Keys.DEFAULT_THRESHOLD_DISTANCE
val previousAccuracy: Float = if (previousLocation.accuracy != 0.0f) previousLocation.accuracy else Keys.DEFAULT_THRESHOLD_DISTANCE
val accuracyDelta: Double = Math.sqrt((accuracy.pow(2) + previousAccuracy.pow(2)).toDouble())
val distance: Float = previousLocation.distanceTo(location)
// With 1*accuracyDelta we have 68% confidence that the points are
// different. We can multiply this number to increase confidence but
// decrease point recording frequency if needed.
return distance > accuracyDelta
}
/* Get number of satellites from Location extras */
fun getNumberOfSatellites(location: Location): Int {
val numberOfSatellites: Int
val extras: Bundle? = location.extras
if (extras != null && extras.containsKey("satellites")) {
numberOfSatellites = extras.getInt("satellites", 0)
} else {
numberOfSatellites = 0
}
return numberOfSatellites
}
} }
/* Tries to return the last location that the system has stored */
fun getLastKnownLocation(context: Context): Location
{
// get last location that Trackbook has stored
var lastKnownLocation: Location = PreferencesHelper.loadCurrentBestLocation()
// try to get the last location the system has stored - it is probably more recent
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val lastKnownLocationGps: Location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) ?: lastKnownLocation
val lastKnownLocationNetwork: Location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) ?: lastKnownLocation
when (isBetterLocation(lastKnownLocationGps, lastKnownLocationNetwork)) {
true -> lastKnownLocation = lastKnownLocationGps
false -> lastKnownLocation = lastKnownLocationNetwork
}
}
return lastKnownLocation
}
/* Determines whether one location reading is better than the current location fix */
fun isBetterLocation(location: Location, currentBestLocation: Location?): Boolean
{
// Credit: https://developer.android.com/guide/topics/location/strategies.html#BestEstimate
if (currentBestLocation == null)
{
// a new location is always better than no location
return true
}
// check whether the new location fix is newer or older
val timeDelta: Long = location.time - currentBestLocation.time
val isSignificantlyNewer: Boolean = timeDelta > Keys.SIGNIFICANT_TIME_DIFFERENCE
val isSignificantlyOlder:Boolean = timeDelta < -Keys.SIGNIFICANT_TIME_DIFFERENCE
when {
// if it's been more than two minutes since the current location, use the new location because the user has likely moved
isSignificantlyNewer -> return true
// if the new location is more than two minutes older, it must be worse
isSignificantlyOlder -> return false
}
// check whether the new location fix is more or less accurate
val isNewer: Boolean = timeDelta > 0L
val accuracyDelta: Float = location.accuracy - currentBestLocation.accuracy
val isLessAccurate: Boolean = accuracyDelta > 0f
val isMoreAccurate: Boolean = accuracyDelta < 0f
val isSignificantlyLessAccurate: Boolean = accuracyDelta > 200f
// check if the old and new location are from the same provider
val isFromSameProvider: Boolean = location.provider == currentBestLocation.provider
// determine location quality using a combination of timeliness and accuracy
return when {
isMoreAccurate -> true
isNewer && !isLessAccurate -> true
isNewer && !isSignificantlyLessAccurate && isFromSameProvider -> true
else -> false
}
}
/* Checks if GPS location provider is available and enabled */
fun isGpsEnabled(locationManager: LocationManager): Boolean
{
if (locationManager.allProviders.contains(LocationManager.GPS_PROVIDER))
{
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
}
else
{
return false
}
}
/* Checks if Network location provider is available and enabled */
fun isNetworkEnabled(locationManager: LocationManager): Boolean
{
if (locationManager.allProviders.contains(LocationManager.NETWORK_PROVIDER))
{
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
}
else
{
return false
}
}
/* Checks if given location is new */
fun isRecentEnough(location: Location): Boolean
{
val locationAge: Long = SystemClock.elapsedRealtimeNanos() - location.elapsedRealtimeNanos
return locationAge < Keys.DEFAULT_THRESHOLD_LOCATION_AGE
}
/* Checks if given location is accurate */
fun isAccurateEnough(location: Location, locationAccuracyThreshold: Int): Boolean
{
if (location.provider == LocationManager.GPS_PROVIDER)
{
return location.accuracy < locationAccuracyThreshold
}
else
{
return location.accuracy < locationAccuracyThreshold + 10 // a bit more relaxed when location comes from network provider
}
}
/* Checks if given location is different enough compared to previous location */
fun isDifferentEnough(previousLocation: Location?, location: Location, omitRests: Boolean): Boolean
{
// check if previous location is (not) available
if (previousLocation == null)
{
return true
}
if (! omitRests)
{
return true
}
// location.accuracy is given as 1 standard deviation, with a 68% chance
// that the true position is within a circle of this radius.
// These formulas determine if the difference between the last point and
// new point is statistically significant.
val accuracy: Float = if (location.accuracy != 0.0f) location.accuracy else Keys.DEFAULT_THRESHOLD_DISTANCE
val previousAccuracy: Float = if (previousLocation.accuracy != 0.0f) previousLocation.accuracy else Keys.DEFAULT_THRESHOLD_DISTANCE
val accuracyDelta: Double = Math.sqrt((accuracy.pow(2) + previousAccuracy.pow(2)).toDouble())
val distance: Float = previousLocation.distanceTo(location)
// With 1*accuracyDelta we have 68% confidence that the points are
// different. We can multiply this number to increase confidence but
// decrease point recording frequency if needed.
return distance > accuracyDelta
}
/* Get number of satellites from Location extras */
fun getNumberOfSatellites(location: Location): Int
{
val numberOfSatellites: Int
val extras: Bundle? = location.extras
if (extras != null && extras.containsKey("satellites")) {
numberOfSatellites = extras.getInt("satellites", 0)
} else {
numberOfSatellites = 0
}
return numberOfSatellites
}

View File

@ -134,8 +134,6 @@ fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, track:
map_view.overlays.add(createOverlay(context, overlayItems)) map_view.overlays.add(createOverlay(context, overlayItems))
} }
fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem
{ {
val title: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}" val title: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"

View File

@ -65,7 +65,6 @@ data class MapFragmentLayoutHolder(
private val trackingState: Int private val trackingState: Int
) )
{ {
/* Main class variables */
val rootView: View val rootView: View
var userInteraction: Boolean = false var userInteraction: Boolean = false
val currentLocationButton: FloatingActionButton val currentLocationButton: FloatingActionButton
@ -75,12 +74,13 @@ data class MapFragmentLayoutHolder(
private var current_location_radius: Polygon = Polygon() private var current_location_radius: Polygon = Polygon()
private var currentTrackOverlay: SimpleFastPointOverlay? private var currentTrackOverlay: SimpleFastPointOverlay?
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>? private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>?
private val useImperial: Boolean = PreferencesHelper.loadUseImperialUnits()
private var locationErrorBar: Snackbar private var locationErrorBar: Snackbar
private var controller: IMapController private var controller: IMapController
private var zoomLevel: Double private var zoomLevel: Double
init { init
{
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.init")
// find views // find views
rootView = inflater.inflate(R.layout.fragment_map, container, false) rootView = inflater.inflate(R.layout.fragment_map, container, false)
mapView = rootView.findViewById(R.id.map) mapView = rootView.findViewById(R.id.map)
@ -164,7 +164,7 @@ data class MapFragmentLayoutHolder(
fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED) fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
{ {
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition") Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition")
val locationIsOld: Boolean = !(LocationHelper.isRecentEnough(location)) val locationIsOld: Boolean = !(isRecentEnough(location))
// create marker // create marker
val newMarker: Drawable val newMarker: Drawable
@ -228,7 +228,7 @@ data class MapFragmentLayoutHolder(
val p = Polygon() val p = Polygon()
p.points = Polygon.pointsAsCircle(GeoPoint(homepoint.location.latitude, homepoint.location.longitude), homepoint.location.accuracy.toDouble()) p.points = Polygon.pointsAsCircle(GeoPoint(homepoint.location.latitude, homepoint.location.longitude), homepoint.location.accuracy.toDouble())
p.fillPaint.color = Color.argb(64, 255, 193, 7) p.fillPaint.color = Color.argb(64, 255, 193, 7)
p.outlinePaint.color = Color.argb(128, 255, 193, 7) p.outlinePaint.color = Color.argb(0, 0, 0, 0)
map_view.overlays.add(p) map_view.overlays.add(p)
} }
} }