checkpoint
This commit is contained in:
parent
df77b089ac
commit
04fa76249b
7 changed files with 197 additions and 191 deletions
|
@ -58,7 +58,7 @@ class MapFragment : Fragment()
|
|||
// https://gist.github.com/Dvik/a3de88d39da9d1d6d175025a56c5e797#file-viewextension-kt and
|
||||
// https://proandroiddev.com/android-full-screen-ui-with-transparent-status-bar-ef52f3adde63
|
||||
// get current best location
|
||||
currentBestLocation = LocationHelper.getLastKnownLocation(activity as Context)
|
||||
currentBestLocation = getLastKnownLocation(activity as Context)
|
||||
// get saved tracking state
|
||||
trackingState = PreferencesHelper.loadTrackingState()
|
||||
requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
|
|
|
@ -20,7 +20,9 @@ import YesNoDialog
|
|||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
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.setDefaultValue(random_device_id())
|
||||
preferenceCategoryGeneral.contains(preferenceDeviceID)
|
||||
preferenceDeviceID.setOnPreferenceChangeListener { preference, newValue ->
|
||||
preferenceDeviceID.summary = getString(R.string.pref_device_id_summary) + "\n" + newValue
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
screen.addPreference(preferenceDeviceID)
|
||||
|
||||
val preferenceCategoryAbout: PreferenceCategory = PreferenceCategory(context)
|
||||
|
|
|
@ -57,7 +57,7 @@ class TrackerService: Service(), SensorEventListener
|
|||
var device_id: String = random_device_id()
|
||||
var recording_started: Date = GregorianCalendar.getInstance().time
|
||||
var commitInterval: Int = Keys.COMMIT_INTERVAL
|
||||
var currentBestLocation: Location = LocationHelper.getDefaultLocation()
|
||||
var currentBestLocation: Location = getDefaultLocation()
|
||||
var lastCommit: Date = Keys.DEFAULT_DATE
|
||||
var stepCountOffset: Float = 0f
|
||||
lateinit var track: Track
|
||||
|
@ -74,7 +74,6 @@ class TrackerService: Service(), SensorEventListener
|
|||
private lateinit var gpsLocationListener: LocationListener
|
||||
private lateinit var networkLocationListener: LocationListener
|
||||
|
||||
/* Adds a GPS location listener to location manager */
|
||||
private fun addGpsLocationListener()
|
||||
{
|
||||
if (gpsLocationListenerRegistered)
|
||||
|
@ -83,7 +82,7 @@ class TrackerService: Service(), SensorEventListener
|
|||
return
|
||||
}
|
||||
|
||||
gpsProviderActive = LocationHelper.isGpsEnabled(locationManager)
|
||||
gpsProviderActive = isGpsEnabled(locationManager)
|
||||
if (! gpsProviderActive)
|
||||
{
|
||||
LogHelper.w(TAG, "Device GPS is not enabled.")
|
||||
|
@ -107,7 +106,6 @@ class TrackerService: Service(), SensorEventListener
|
|||
LogHelper.v(TAG, "Added GPS location listener.")
|
||||
}
|
||||
|
||||
/* Adds a Network location listener to location manager */
|
||||
private fun addNetworkLocationListener()
|
||||
{
|
||||
if (gpsOnly)
|
||||
|
@ -122,7 +120,7 @@ class TrackerService: Service(), SensorEventListener
|
|||
return
|
||||
}
|
||||
|
||||
networkProviderActive = LocationHelper.isNetworkEnabled(locationManager)
|
||||
networkProviderActive = isNetworkEnabled(locationManager)
|
||||
if (!networkProviderActive)
|
||||
{
|
||||
LogHelper.w(TAG, "Unable to add Network location listener.")
|
||||
|
@ -151,7 +149,7 @@ class TrackerService: Service(), SensorEventListener
|
|||
return object : LocationListener {
|
||||
override fun onLocationChanged(location: Location)
|
||||
{
|
||||
if (LocationHelper.isBetterLocation(location, currentBestLocation)) {
|
||||
if (isBetterLocation(location, currentBestLocation)) {
|
||||
currentBestLocation = location
|
||||
}
|
||||
}
|
||||
|
@ -159,16 +157,16 @@ class TrackerService: Service(), SensorEventListener
|
|||
{
|
||||
LogHelper.v(TAG, "onProviderEnabled $provider")
|
||||
when (provider) {
|
||||
LocationManager.GPS_PROVIDER -> gpsProviderActive = LocationHelper.isGpsEnabled(locationManager)
|
||||
LocationManager.NETWORK_PROVIDER -> networkProviderActive = LocationHelper.isNetworkEnabled(locationManager)
|
||||
LocationManager.GPS_PROVIDER -> gpsProviderActive = isGpsEnabled(locationManager)
|
||||
LocationManager.NETWORK_PROVIDER -> networkProviderActive = isNetworkEnabled(locationManager)
|
||||
}
|
||||
}
|
||||
override fun onProviderDisabled(provider: String)
|
||||
{
|
||||
LogHelper.v(TAG, "onProviderDisabled $provider")
|
||||
when (provider) {
|
||||
LocationManager.GPS_PROVIDER -> gpsProviderActive = LocationHelper.isGpsEnabled(locationManager)
|
||||
LocationManager.NETWORK_PROVIDER -> networkProviderActive = LocationHelper.isNetworkEnabled(locationManager)
|
||||
LocationManager.GPS_PROVIDER -> gpsProviderActive = isGpsEnabled(locationManager)
|
||||
LocationManager.NETWORK_PROVIDER -> networkProviderActive = isNetworkEnabled(locationManager)
|
||||
}
|
||||
}
|
||||
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?)
|
||||
|
@ -179,7 +177,8 @@ class TrackerService: Service(), SensorEventListener
|
|||
}
|
||||
|
||||
/* Displays or updates notification */
|
||||
private fun displayNotification(): Notification {
|
||||
private fun displayNotification(): Notification
|
||||
{
|
||||
val notification: Notification = notificationHelper.createNotification(
|
||||
trackingState,
|
||||
iso8601(GregorianCalendar.getInstance().time)
|
||||
|
@ -189,7 +188,8 @@ class TrackerService: Service(), 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")
|
||||
}
|
||||
|
||||
|
@ -220,24 +220,24 @@ class TrackerService: Service(), SensorEventListener
|
|||
sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationHelper = NotificationHelper(this)
|
||||
gpsProviderActive = LocationHelper.isGpsEnabled(locationManager)
|
||||
networkProviderActive = LocationHelper.isNetworkEnabled(locationManager)
|
||||
gpsProviderActive = isGpsEnabled(locationManager)
|
||||
networkProviderActive = isNetworkEnabled(locationManager)
|
||||
gpsLocationListener = createLocationListener()
|
||||
networkLocationListener = createLocationListener()
|
||||
trackingState = PreferencesHelper.loadTrackingState()
|
||||
currentBestLocation = LocationHelper.getLastKnownLocation(this)
|
||||
currentBestLocation = getLastKnownLocation(this)
|
||||
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||
}
|
||||
|
||||
/* Overrides onDestroy from Service */
|
||||
override fun onDestroy() {
|
||||
LogHelper.i("VOUSSOIR", "TrackerService.onDestroy.")
|
||||
super.onDestroy()
|
||||
LogHelper.i(TAG, "onDestroy called.")
|
||||
if (trackingState == Keys.STATE_TRACKING_ACTIVE)
|
||||
{
|
||||
pauseTracking()
|
||||
}
|
||||
stopForeground(true)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
notificationManager.cancel(Keys.TRACKER_SERVICE_NOTIFICATION_ID) // this call was not necessary prior to Android 12
|
||||
PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||
removeGpsLocationListener()
|
||||
|
@ -316,7 +316,6 @@ class TrackerService: Service(), SensorEventListener
|
|||
}
|
||||
}
|
||||
|
||||
/* Adds location listeners to location manager */
|
||||
fun removeNetworkLocationListener()
|
||||
{
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
|
@ -365,15 +364,14 @@ class TrackerService: Service(), SensorEventListener
|
|||
stopForeground(STOP_FOREGROUND_DETACH)
|
||||
}
|
||||
|
||||
/*
|
||||
* Defines the listener for changes in shared preferences
|
||||
*/
|
||||
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||
when (key) {
|
||||
when (key)
|
||||
{
|
||||
Keys.PREF_GPS_ONLY ->
|
||||
{
|
||||
gpsOnly = PreferencesHelper.loadGpsOnly()
|
||||
when (gpsOnly) {
|
||||
when (gpsOnly)
|
||||
{
|
||||
true -> removeNetworkLocationListener()
|
||||
false -> addNetworkLocationListener()
|
||||
}
|
||||
|
@ -418,12 +416,12 @@ class TrackerService: Service(), SensorEventListener
|
|||
Log.i("VOUSSOIR", "Omitting due to 0,0 location.")
|
||||
return false
|
||||
}
|
||||
if (! LocationHelper.isRecentEnough(location))
|
||||
if (! isRecentEnough(location))
|
||||
{
|
||||
Log.i("VOUSSOIR", "Omitting due to not recent enough.")
|
||||
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.")
|
||||
return false
|
||||
|
@ -440,7 +438,7 @@ class TrackerService: Service(), SensorEventListener
|
|||
{
|
||||
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.")
|
||||
return false
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.y20k.trackbook
|
||||
|
||||
import android.location.Location
|
||||
import org.y20k.trackbook.helpers.LocationHelper
|
||||
import org.y20k.trackbook.helpers.getNumberOfSatellites
|
||||
import java.util.*
|
||||
|
||||
/*
|
||||
|
@ -42,7 +42,7 @@ data class Trkpt(
|
|||
altitude=location.altitude,
|
||||
accuracy=location.accuracy,
|
||||
time=location.time,
|
||||
numberSatellites=LocationHelper.getNumberOfSatellites(location),
|
||||
numberSatellites=getNumberOfSatellites(location),
|
||||
)
|
||||
|
||||
/* Converts WayPoint into Location */
|
||||
|
|
|
@ -27,159 +27,163 @@ import androidx.core.content.ContextCompat
|
|||
import org.y20k.trackbook.Keys
|
||||
import kotlin.math.pow
|
||||
|
||||
/*
|
||||
* Keys object
|
||||
*/
|
||||
object LocationHelper {
|
||||
|
||||
/* Define log tag */
|
||||
private val TAG: String = LogHelper.makeLogTag(LocationHelper::class.java)
|
||||
|
||||
/* Get default location */
|
||||
fun getDefaultLocation(): Location {
|
||||
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
|
||||
}
|
||||
|
||||
/* Get default location */
|
||||
fun getDefaultLocation(): Location
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
|
@ -134,8 +134,6 @@ fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, track:
|
|||
map_view.overlays.add(createOverlay(context, overlayItems))
|
||||
}
|
||||
|
||||
|
||||
|
||||
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)}"
|
||||
|
|
|
@ -65,7 +65,6 @@ data class MapFragmentLayoutHolder(
|
|||
private val trackingState: Int
|
||||
)
|
||||
{
|
||||
/* Main class variables */
|
||||
val rootView: View
|
||||
var userInteraction: Boolean = false
|
||||
val currentLocationButton: FloatingActionButton
|
||||
|
@ -75,12 +74,13 @@ data class MapFragmentLayoutHolder(
|
|||
private var current_location_radius: Polygon = Polygon()
|
||||
private var currentTrackOverlay: SimpleFastPointOverlay?
|
||||
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>?
|
||||
private val useImperial: Boolean = PreferencesHelper.loadUseImperialUnits()
|
||||
private var locationErrorBar: Snackbar
|
||||
private var controller: IMapController
|
||||
private var zoomLevel: Double
|
||||
|
||||
init {
|
||||
init
|
||||
{
|
||||
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.init")
|
||||
// find views
|
||||
rootView = inflater.inflate(R.layout.fragment_map, container, false)
|
||||
mapView = rootView.findViewById(R.id.map)
|
||||
|
@ -164,7 +164,7 @@ data class MapFragmentLayoutHolder(
|
|||
fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
|
||||
{
|
||||
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition")
|
||||
val locationIsOld: Boolean = !(LocationHelper.isRecentEnough(location))
|
||||
val locationIsOld: Boolean = !(isRecentEnough(location))
|
||||
|
||||
// create marker
|
||||
val newMarker: Drawable
|
||||
|
@ -228,7 +228,7 @@ data class MapFragmentLayoutHolder(
|
|||
val p = Polygon()
|
||||
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.outlinePaint.color = Color.argb(128, 255, 193, 7)
|
||||
p.outlinePaint.color = Color.argb(0, 0, 0, 0)
|
||||
map_view.overlays.add(p)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue