diff --git a/app/src/main/java/org/y20k/trackbook/Database.kt b/app/src/main/java/org/y20k/trackbook/Database.kt index b53a3ba..f1b15db 100644 --- a/app/src/main/java/org/y20k/trackbook/Database.kt +++ b/app/src/main/java/org/y20k/trackbook/Database.kt @@ -6,9 +6,8 @@ import android.util.Log import java.io.File import java.util.* -class Database(trackbook: Trackbook) +class Database(val trackbook: Trackbook) { - val trackbook = trackbook var ready: Boolean = false lateinit var file: File lateinit var connection: SQLiteDatabase @@ -96,8 +95,12 @@ class Database(trackbook: Trackbook) fun update_homepoint(id: Long, name: String, radius: Double) { Log.i("VOUSSOIR", "Database.update_homepoint") + val values = ContentValues().apply { + put("name", name) + put("radius", radius) + } begin_transaction() - connection.rawQuery("UPDATE homepoints SET name = ?, radius = ? WHERE id = ?", arrayOf(name, radius.toString(), id.toString())) + connection.update("homepoints", values, "id = ?", arrayOf(id.toString())) commit() } @@ -107,6 +110,7 @@ class Database(trackbook: Trackbook) this.connection.execSQL("CREATE TABLE IF NOT EXISTS meta(name TEXT PRIMARY KEY, value TEXT)") this.connection.execSQL("CREATE TABLE IF NOT EXISTS trkpt(lat REAL NOT NULL, lon REAL NOT NULL, time INTEGER NOT NULL, accuracy REAL, device_id INTEGER NOT NULL, ele INTEGER, sat INTEGER, PRIMARY KEY(lat, lon, time, device_id))") this.connection.execSQL("CREATE TABLE IF NOT EXISTS homepoints(id INTEGER PRIMARY KEY, lat REAL NOT NULL, lon REAL NOT NULL, radius REAL NOT NULL, name TEXT)") + this.connection.execSQL("PRAGMA user_version = ${Keys.CURRENT_TRACKLIST_FORMAT_VERSION}") this.connection.setTransactionSuccessful() this.connection.endTransaction() } diff --git a/app/src/main/java/org/y20k/trackbook/Keys.kt b/app/src/main/java/org/y20k/trackbook/Keys.kt index d202ff5..9ba6289 100644 --- a/app/src/main/java/org/y20k/trackbook/Keys.kt +++ b/app/src/main/java/org/y20k/trackbook/Keys.kt @@ -77,18 +77,9 @@ object Keys { const val DIALOG_EMPTY_PAYLOAD_STRING: String = "" const val DIALOG_EMPTY_PAYLOAD_INT: Int = -1 - // folder names - const val FOLDER_TEMP: String = "temp" - const val FOLDER_TRACKS: String = "tracks" - const val FOLDER_GPX: String = "gpx" - // file names and extensions const val MIME_TYPE_GPX: String = "application/gpx+xml" const val GPX_FILE_EXTENSION: String = ".gpx" - const val TRACKBOOK_LEGACY_FILE_EXTENSION: String = ".trackbook" - const val TRACKBOOK_FILE_EXTENSION: String = ".json" - const val TEMP_FILE: String = "temp.json" - const val TRACKLIST_FILE: String = "tracklist.json" // view types const val VIEW_TYPE_STATISTICS: Int = 1 @@ -96,13 +87,11 @@ object Keys { // default values val DEFAULT_DATE: Date = Date(0L) - const val DEFAULT_RFC2822_DATE: String = "Thu, 01 Jan 1970 01:00:00 +0100" // --> Date(0) 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 REQUEST_CURRENT_LOCATION_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS - const val TRACKING_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS const val SAVE_TEMP_TRACK_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS const val SIGNIFICANT_TIME_DIFFERENCE: Long = 1 * ONE_MINUTE_IN_MILLISECONDS const val STOP_OVER_THRESHOLD: Long = 5 * ONE_MINUTE_IN_MILLISECONDS @@ -113,7 +102,6 @@ object Keys { const val DEFAULT_ALTITUDE: Double = 0.0 const val DEFAULT_TIME: Long = 0L const val COMMIT_INTERVAL: Int = 30 - const val DEFAULT_ALTITUDE_SMOOTHING_VALUE: Int = 13 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_DISTANCE: Float = 15f // 15 meters diff --git a/app/src/main/java/org/y20k/trackbook/MapFragment.kt b/app/src/main/java/org/y20k/trackbook/MapFragment.kt index 4d5894a..e2bbb5c 100644 --- a/app/src/main/java/org/y20k/trackbook/MapFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/MapFragment.kt @@ -138,6 +138,7 @@ class MapFragment : Fragment() // basic map setup controller = mapView.controller mapView.isTilesScaledToDpi = true + mapView.isVerticalMapRepetitionEnabled = false mapView.setTileSource(TileSourceFactory.MAPNIK) mapView.setMultiTouchControls(true) mapView.zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER) @@ -538,7 +539,8 @@ class MapFragment : Fragment() dialog.dismiss() } save_button.setOnClickListener { - trackbook.database.update_homepoint(homepoint.id, name=name_input.text.toString(), radius=radius_input.text.toString().toDouble()) + val radius = radius_input.text.toString().toDoubleOrNull() ?: 25.0 + trackbook.database.update_homepoint(homepoint.id, name=name_input.text.toString(), radius=radius) trackbook.load_homepoints() create_homepoint_overlays(requireContext(), mapView, trackbook.homepoints) dialog.dismiss() @@ -568,8 +570,8 @@ class MapFragment : Fragment() mapView.overlays.remove(currentTrackSpecialMarkerOverlay) } if (trkpts.isNotEmpty()) { - createTrackOverlay(requireContext(), mapView, trkpts, trackingState) - createSpecialMakersTrackOverlay(requireContext(), mapView, trkpts, trackingState) + currentTrackOverlay = createTrackOverlay(requireContext(), mapView, trkpts, trackingState) + currentTrackSpecialMarkerOverlay = createSpecialMakersTrackOverlay(requireContext(), mapView, trkpts, trackingState) } } diff --git a/app/src/main/java/org/y20k/trackbook/Track.kt b/app/src/main/java/org/y20k/trackbook/Track.kt index 70f73ab..f974ed0 100644 --- a/app/src/main/java/org/y20k/trackbook/Track.kt +++ b/app/src/main/java/org/y20k/trackbook/Track.kt @@ -85,7 +85,7 @@ data class Track ( var previous: Trkpt? = null for (trkpt in trkpt_generator()) { - if (previous != null && (trkpt.time - previous.time) > (5 * Keys.ONE_MINUTE_IN_MILLISECONDS)) + if (previous != null && (trkpt.time - previous.time) > (Keys.STOP_OVER_THRESHOLD)) { write("\t\t") write("\t\t") diff --git a/app/src/main/java/org/y20k/trackbook/TrackerService.kt b/app/src/main/java/org/y20k/trackbook/TrackerService.kt index 287b4f6..b3583f0 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackerService.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackerService.kt @@ -57,7 +57,7 @@ class TrackerService: Service(), SensorEventListener var recording_started: Date = GregorianCalendar.getInstance().time var commitInterval: Int = Keys.COMMIT_INTERVAL var currentBestLocation: Location = getDefaultLocation() - var lastCommit: Date = Keys.DEFAULT_DATE + var lastCommit: Long = 0 var location_min_time_ms: Long = 0 private val RECENT_TRKPT_COUNT = 7200 var stepCountOffset: Float = 0f @@ -150,9 +150,36 @@ class TrackerService: Service(), SensorEventListener return object : LocationListener { override fun onLocationChanged(location: Location) { - if (isBetterLocation(location, currentBestLocation)) { - currentBestLocation = location + if (! isBetterLocation(location, currentBestLocation)) + { + return } + currentBestLocation = location + if (trackingState != Keys.STATE_TRACKING_ACTIVE) + { + return + } + Log.i("VOUSSOIR", "Processing point ${location.latitude}, ${location.longitude} ${location.time}.") + if (should_keep_point((location))) + { + val now: Long = location.time + // val now: Date = GregorianCalendar.getInstance().time + val trkpt = Trkpt(location=location) + trackbook.database.insert_trkpt(device_id, trkpt) + recent_trkpts.add(trkpt) + + while (recent_trkpts.size > RECENT_TRKPT_COUNT) + { + recent_trkpts.removeFirst() + } + + if (now - lastCommit > Keys.SAVE_TEMP_TRACK_INTERVAL) + { + trackbook.database.commit() + lastCommit = now + } + } + displayNotification() } override fun onProviderEnabled(provider: String) { @@ -353,7 +380,6 @@ class TrackerService: Service(), SensorEventListener } PreferencesHelper.saveTrackingState(trackingState) startStepCounter() - handler.postDelayed(periodicTrackUpdate, 0) startForeground(Keys.TRACKER_SERVICE_NOTIFICATION_ID, displayNotification()) } @@ -365,7 +391,6 @@ class TrackerService: Service(), SensorEventListener PreferencesHelper.saveTrackingState(trackingState) sensorManager.unregisterListener(this) - handler.removeCallbacks(periodicTrackUpdate) displayNotification() stopForeground(STOP_FOREGROUND_DETACH) @@ -452,31 +477,4 @@ class TrackerService: Service(), SensorEventListener } return true } - - private val periodicTrackUpdate: Runnable = object : Runnable - { - override fun run() { - val now: Date = GregorianCalendar.getInstance().time - val trkpt = Trkpt(location=currentBestLocation) - Log.i("VOUSSOIR", "Processing point ${currentBestLocation.latitude}, ${currentBestLocation.longitude} ${now.time}.") - if (should_keep_point((currentBestLocation))) - { - trackbook.database.insert_trkpt(device_id, trkpt) - recent_trkpts.add(trkpt) - - while (recent_trkpts.size > RECENT_TRKPT_COUNT) - { - recent_trkpts.removeFirst() - } - - if (now.time - lastCommit.time > Keys.SAVE_TEMP_TRACK_INTERVAL) - { - trackbook.database.commit() - lastCommit = now - } - } - displayNotification() - handler.postDelayed(this, Keys.TRACKING_INTERVAL) - } - } } diff --git a/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt index 08692ea..5c86297 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt @@ -37,7 +37,7 @@ import java.text.SimpleDateFormat import java.util.* /* Creates icon overlay for track */ -fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection, trackingState: Int) +fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection, trackingState: Int): SimpleFastPointOverlay { val color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.default_red) else context.getColor(R.color.default_blue) val points: MutableList = mutableListOf() @@ -64,10 +64,11 @@ fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection10k points), use 15. val overlay = SimpleFastPointOverlay(pointTheme, overlayOptions) map_view.overlays.add(overlay) + return overlay } /* Creates overlay containing start, stop, stopover and starred markers for track */ -fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts: Collection, trackingState: Int, displayStartEndMarker: Boolean = false) +fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts: Collection, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay { val overlayItems: ArrayList = ArrayList() val trackingActive: Boolean = trackingState == Keys.STATE_TRACKING_ACTIVE @@ -110,7 +111,9 @@ fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts: overlayItems.add(overlayItem) } } - map_view.overlays.add(createOverlay(context, overlayItems)) + val overlay: ItemizedIconOverlay = createOverlay(context, overlayItems) + map_view.overlays.add(overlay) + return overlay } fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 30c1364..2d02442 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -86,7 +86,7 @@ Altitude Smoothing Automatically export GPX file after this many hours. A unique ID to distinguish tracks recorded across multiple devices: - Directory to contain your database file. You could use Syncthing to sync with your PC! + Directory to contain your database file. You could use Syncthing to sync with your PC. Auto Export Interval Device ID Database directory @@ -96,8 +96,8 @@ General Maintenance Restrict to GPS - Currently using GPS and Network for localization. - Currently using only GPS for localization. + Currently using GPS and Network for location. + Currently using only GPS for location. Currently using metric units (Kilometer, Meter). Currently using imperial units (Miles, Feet). Use Imperial Measurements