Add preference max accuracy, filters inaccurate points from view.

This commit is contained in:
voussoir 2023-04-09 20:27:08 -07:00
parent 3b1ccb7781
commit a181d67150
8 changed files with 76 additions and 28 deletions

View file

@ -95,21 +95,31 @@ class Database(val trackbook: Trackbook)
} }
} }
fun select_trkpt_start_end(device_id: String, start_time: Long, end_time: Long, order: String="ASC"): Iterator<Trkpt> fun select_trkpt_start_end(device_id: String, start_time: Long, end_time: Long, max_accuracy: Float=Keys.DEFAULT_MAX_ACCURACY, order: String="ASC"): Iterator<Trkpt>
{ {
Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between ${start_time} -- ${end_time}.") Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between ${start_time} -- ${end_time}.")
return _trkpt_generator(this.connection.rawQuery( return _trkpt_generator(this.connection.rawQuery(
"SELECT device_id, lat, lon, time, provider, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND time >= ? AND time <= ? ORDER BY time ${order}", """
arrayOf(device_id, start_time.toString(), end_time.toString()) SELECT device_id, lat, lon, time, provider, ele, accuracy, sat
FROM trkpt
WHERE device_id = ? AND time >= ? AND time <= ? AND accuracy <= ?
ORDER BY time ${order}
""",
arrayOf(device_id, start_time.toString(), end_time.toString(), max_accuracy.toString())
)) ))
} }
fun select_trkpt_bounding_box(device_id: String, north: Double, south: Double, east: Double, west: Double): Iterator<Trkpt> fun select_trkpt_bounding_box(device_id: String, north: Double, south: Double, east: Double, west: Double, max_accuracy: Float=Keys.DEFAULT_MAX_ACCURACY): Iterator<Trkpt>
{ {
Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between $north, $south, $east, $west.") Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between $north, $south, $east, $west.")
return _trkpt_generator(this.connection.rawQuery( return _trkpt_generator(this.connection.rawQuery(
"SELECT device_id, lat, lon, time, provider, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND lat >= ? AND lat <= ? AND lon >= ? AND lon <= ? ORDER BY time ASC", """
arrayOf(device_id, south.toString(), north.toString(), west.toString(), east.toString()) SELECT device_id, lat, lon, time, provider, ele, accuracy, sat
FROM trkpt
WHERE device_id = ? AND lat >= ? AND lat <= ? AND lon >= ? AND lon <= ? AND accuracy <= ?
ORDER BY time ASC
""",
arrayOf(device_id, south.toString(), north.toString(), west.toString(), east.toString(), max_accuracy.toString())
)) ))
} }

View file

@ -64,6 +64,7 @@ object Keys {
const val PREF_SHOW_DEBUG: String = "prefShowDebug" const val PREF_SHOW_DEBUG: String = "prefShowDebug"
const val PREF_DEVICE_ID: String = "prefDeviceID" const val PREF_DEVICE_ID: String = "prefDeviceID"
const val PREF_DATABASE_DIRECTORY: String = "prefDatabaseDirectory" const val PREF_DATABASE_DIRECTORY: String = "prefDatabaseDirectory"
const val PREF_MAX_ACCURACY: String = "prefMaxAccuracy"
// states // states
const val STATE_TRACKING_STOPPED: Int = 0 const val STATE_TRACKING_STOPPED: Int = 0
@ -102,13 +103,13 @@ object Keys {
const val DEFAULT_ALTITUDE: Double = 0.0 const val DEFAULT_ALTITUDE: Double = 0.0
const val DEFAULT_TIME: Long = 0L const val DEFAULT_TIME: Long = 0L
const val COMMIT_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS const val COMMIT_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS
const val DEFAULT_THRESHOLD_LOCATION_ACCURACY: Int = 30 // 30 meters
const val DEFAULT_THRESHOLD_LOCATION_AGE: Long = 5_000_000_000L // 5s in nanoseconds const val DEFAULT_THRESHOLD_LOCATION_AGE: Long = 5_000_000_000L // 5s in nanoseconds
const val DEFAULT_THRESHOLD_DISTANCE: Float = 15f // 15 meters const val DEFAULT_THRESHOLD_DISTANCE: Float = 15f // 15 meters
const val DEFAULT_ZOOM_LEVEL: Double = 16.0 const val DEFAULT_ZOOM_LEVEL: Double = 16.0
const val DEFAULT_OMIT_RESTS: Boolean = true const val DEFAULT_OMIT_RESTS: Boolean = true
const val DEFAULT_ALLOW_SLEEP: Boolean = true const val DEFAULT_ALLOW_SLEEP: Boolean = true
const val DEFAULT_SHOW_DEBUG: Boolean = false const val DEFAULT_SHOW_DEBUG: Boolean = false
const val DEFAULT_MAX_ACCURACY: Float = 30f
// notification // notification
const val TRACKER_SERVICE_NOTIFICATION_ID: Int = 1 const val TRACKER_SERVICE_NOTIFICATION_ID: Int = 1

View file

@ -32,13 +32,7 @@ import android.provider.Settings
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.preference.EditTextPreference import androidx.preference.*
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import androidx.preference.contains
import get_path_from_uri import get_path_from_uri
import net.voussoir.trkpt.helpers.AppThemeHelper import net.voussoir.trkpt.helpers.AppThemeHelper
import net.voussoir.trkpt.helpers.LengthUnitHelper import net.voussoir.trkpt.helpers.LengthUnitHelper
@ -139,6 +133,23 @@ class SettingsFragment : PreferenceFragmentCompat()
preferenceCategoryGeneral.contains(prefAllowSleep) preferenceCategoryGeneral.contains(prefAllowSleep)
screen.addPreference(prefAllowSleep) screen.addPreference(prefAllowSleep)
val prefMaxAccuracy = SeekBarPreference(activity as Context)
prefMaxAccuracy.title = getString(R.string.pref_max_accuracy_title)
prefMaxAccuracy.setIcon(R.drawable.ic_bullseye_24dp)
prefMaxAccuracy.key = Keys.PREF_MAX_ACCURACY
prefMaxAccuracy.summary = getString(R.string.pref_max_accuracy_summary) + "\n${PreferencesHelper.load_max_accuracy()} m"
prefMaxAccuracy.showSeekBarValue = true
prefMaxAccuracy.min = 0
prefMaxAccuracy.max = 500
prefMaxAccuracy.setDefaultValue((Keys.DEFAULT_MAX_ACCURACY * 10).toInt())
prefMaxAccuracy.setOnPreferenceChangeListener { preference, newValue ->
val floated = (newValue as Int) / 10f
prefMaxAccuracy.summary = getString(R.string.pref_max_accuracy_summary) + "\n${floated} m"
return@setOnPreferenceChangeListener true
}
preferenceCategoryGeneral.contains(prefMaxAccuracy)
screen.addPreference(prefMaxAccuracy)
val prefShowDebug = SwitchPreferenceCompat(activity as Context) val prefShowDebug = SwitchPreferenceCompat(activity as Context)
prefShowDebug.isSingleLineTitle = false prefShowDebug.isSingleLineTitle = false
prefShowDebug.title = getString(R.string.pref_show_debug_title) prefShowDebug.title = getString(R.string.pref_show_debug_title)

View file

@ -154,6 +154,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""), device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""),
start_time=requested_start_time, start_time=requested_start_time,
end_time=requested_end_time, end_time=requested_end_time,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
rootView = inflater.inflate(R.layout.fragment_track, container, false) rootView = inflater.inflate(R.layout.fragment_track, container, false)
mapView = rootView.findViewById(R.id.map) mapView = rootView.findViewById(R.id.map)
@ -285,8 +286,9 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
set_datetime(track_query_start_date, track_query_start_time, Date(selected.time), _ending=false) set_datetime(track_query_start_date, track_query_start_time, Date(selected.time), _ending=false)
track.load_trkpts(trackbook.database.select_trkpt_start_end( track.load_trkpts(trackbook.database.select_trkpt_start_end(
track.device_id, track.device_id,
selected.time, start_time=selected.time,
track.trkpts.last().time, end_time=track.trkpts.last().time,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
deselect_trkpt() deselect_trkpt()
render_track() render_track()
@ -302,8 +304,9 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
set_datetime(track_query_end_date, track_query_end_time, Date(selected.time), _ending=true) set_datetime(track_query_end_date, track_query_end_time, Date(selected.time), _ending=true)
track.load_trkpts(trackbook.database.select_trkpt_start_end( track.load_trkpts(trackbook.database.select_trkpt_start_end(
track.device_id, track.device_id,
track.trkpts.first().time, start_time=track.trkpts.first().time,
selected.time, end_time=selected.time,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
deselect_trkpt() deselect_trkpt()
render_track() render_track()
@ -321,8 +324,9 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
{ {
track.load_trkpts(trackbook.database.select_trkpt_start_end( track.load_trkpts(trackbook.database.select_trkpt_start_end(
track.device_id, track.device_id,
(polyline.actualPoints.first() as Trkpt).time, start_time=(polyline.actualPoints.first() as Trkpt).time,
(polyline.actualPoints.last() as Trkpt).time, end_time=(polyline.actualPoints.last() as Trkpt).time,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
track.expand_to_trkseg_bounds() track.expand_to_trkseg_bounds()
@ -342,6 +346,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
south=mapView.boundingBox.actualSouth, south=mapView.boundingBox.actualSouth,
east=mapView.boundingBox.lonEast, east=mapView.boundingBox.lonEast,
west=mapView.boundingBox.lonWest, west=mapView.boundingBox.lonWest,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
set_datetimes_from_track() set_datetimes_from_track()
render_track() render_track()
@ -776,6 +781,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
track.device_id, track.device_id,
start_time=get_datetime(track_query_start_date, track_query_start_time, seconds=0).time, start_time=get_datetime(track_query_start_date, track_query_start_time, seconds=0).time,
end_time=get_datetime(track_query_end_date, track_query_end_time, seconds=59).time, end_time=get_datetime(track_query_end_date, track_query_end_time, seconds=59).time,
max_accuracy=PreferencesHelper.load_max_accuracy(),
)) ))
Log.i("VOUSSOIR", "TrackFragment.requery_and_render: Reloaded ${track.trkpts.size} trkpts.") Log.i("VOUSSOIR", "TrackFragment.requery_and_render: Reloaded ${track.trkpts.size} trkpts.")
render_track() render_track()

View file

@ -28,8 +28,6 @@ import android.hardware.*
import android.location.Location import android.location.Location
import android.location.LocationListener import android.location.LocationListener
import android.location.LocationManager import android.location.LocationManager
import android.media.AudioManager
import android.media.ToneGenerator
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@ -48,6 +46,7 @@ class TrackerService: Service()
var trackingState: Int = Keys.STATE_TRACKING_STOPPED var trackingState: Int = Keys.STATE_TRACKING_STOPPED
var useImperial: Boolean = false var useImperial: Boolean = false
var omitRests: Boolean = true var omitRests: Boolean = true
var max_accuracy: Float = Keys.DEFAULT_MAX_ACCURACY
var allow_sleep: Boolean = true var allow_sleep: Boolean = true
var device_id: String = random_device_id() var device_id: String = random_device_id()
var currentBestLocation: Location = getDefaultLocation() var currentBestLocation: Location = getDefaultLocation()
@ -318,11 +317,6 @@ class TrackerService: Service()
Log.i("VOUSSOIR", "Omitting due to not recent enough.") Log.i("VOUSSOIR", "Omitting due to not recent enough.")
return return
} }
if (! isAccurateEnough(location, Keys.DEFAULT_THRESHOLD_LOCATION_ACCURACY))
{
Log.i("VOUSSOIR", "Omitting due to not accurate enough.")
return
}
if (recent_displacement_locations.isEmpty()) if (recent_displacement_locations.isEmpty())
{ {
// pass // pass
@ -341,7 +335,10 @@ class TrackerService: Service()
val trkpt = Trkpt(device_id=device_id, location=location) val trkpt = Trkpt(device_id=device_id, location=location)
trackbook.database.insert_trkpt(trkpt, commit=false) trackbook.database.insert_trkpt(trkpt, commit=false)
recent_trackpoints_for_mapview.add(trkpt) if (trkpt.accuracy <= max_accuracy)
{
recent_trackpoints_for_mapview.add(trkpt)
}
while (recent_trackpoints_for_mapview.size > RECENT_TRKPT_COUNT) while (recent_trackpoints_for_mapview.size > RECENT_TRKPT_COUNT)
{ {
recent_trackpoints_for_mapview.removeFirst() recent_trackpoints_for_mapview.removeFirst()
@ -679,6 +676,10 @@ class TrackerService: Service()
{ {
omitRests = PreferencesHelper.loadOmitRests() omitRests = PreferencesHelper.loadOmitRests()
} }
Keys.PREF_MAX_ACCURACY ->
{
max_accuracy = PreferencesHelper.load_max_accuracy()
}
Keys.PREF_ALLOW_SLEEP -> Keys.PREF_ALLOW_SLEEP ->
{ {
allow_sleep = PreferencesHelper.loadAllowSleep() allow_sleep = PreferencesHelper.loadAllowSleep()

View file

@ -106,6 +106,10 @@ object PreferencesHelper
return sharedPreferences.getBoolean(Keys.PREF_SHOW_DEBUG, Keys.DEFAULT_SHOW_DEBUG) return sharedPreferences.getBoolean(Keys.PREF_SHOW_DEBUG, Keys.DEFAULT_SHOW_DEBUG)
} }
fun load_max_accuracy(): Float {
return sharedPreferences.getInt(Keys.PREF_MAX_ACCURACY, Keys.DEFAULT_MAX_ACCURACY.toInt() * 10) / 10f
}
/* Loads the state of a map */ /* Loads the state of a map */
fun loadCurrentBestLocation(): Location { fun loadCurrentBestLocation(): Location {
val provider: String = sharedPreferences.getString(Keys.PREF_CURRENT_BEST_LOCATION_PROVIDER, LocationManager.NETWORK_PROVIDER) ?: LocationManager.NETWORK_PROVIDER val provider: String = sharedPreferences.getString(Keys.PREF_CURRENT_BEST_LOCATION_PROVIDER, LocationManager.NETWORK_PROVIDER) ?: LocationManager.NETWORK_PROVIDER

View file

@ -0,0 +1,13 @@
<!--
Thank you
https://pictogrammers.com/library/mdi/icon/bullseye-arrow/
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="@color/icon_default"
android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,10.84 21.79,9.69 21.39,8.61L19.79,10.21C19.93,10.8 20,11.4 20,12A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4C12.6,4 13.2,4.07 13.79,4.21L15.4,2.6C14.31,2.21 13.16,2 12,2M19,2L15,6V7.5L12.45,10.05C12.3,10 12.15,10 12,10A2,2 0 0,0 10,12A2,2 0 0,0 12,14A2,2 0 0,0 14,12C14,11.85 14,11.7 13.95,11.55L16.5,9H18L22,5H19V2M12,6A6,6 0 0,0 6,12A6,6 0 0,0 12,18A6,6 0 0,0 18,12H16A4,4 0 0,1 12,16A4,4 0 0,1 8,12A4,4 0 0,1 12,8V6Z" />
</vector>

View file

@ -125,6 +125,8 @@
<string name="pref_fork_notice_summary">Thank you y20k.</string> <string name="pref_fork_notice_summary">Thank you y20k.</string>
<string name="pref_copyright_notice_title">Map data</string> <string name="pref_copyright_notice_title">Map data</string>
<string name="pref_copyright_notice_summary">© OpenStreetMap contributors.</string> <string name="pref_copyright_notice_summary">© OpenStreetMap contributors.</string>
<string name="pref_max_accuracy_title">Filter inaccurate points</string>
<string name="pref_max_accuracy_summary">Points with accuracy worse than this will be hidden (but still saved). Small numbers are highly accurate.</string>
<!-- Abbreviations --> <!-- Abbreviations -->
<string name="abbreviation_hours">hrs</string> <string name="abbreviation_hours">hrs</string>