Add preference max accuracy, filters inaccurate points from view.
This commit is contained in:
parent
3b1ccb7781
commit
a181d67150
8 changed files with 76 additions and 28 deletions
|
@ -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())
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
13
app/src/main/res/drawable/ic_bullseye_24dp.xml
Normal file
13
app/src/main/res/drawable/ic_bullseye_24dp.xml
Normal 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>
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue