From ebfbf05006ee7a07f486f8ce69561fe019b047f6 Mon Sep 17 00:00:00 2001 From: Ethan Dalool Date: Fri, 24 Mar 2023 22:37:16 -0700 Subject: [PATCH] Add "when was I here?" button. --- README.md | 10 +- .../main/java/net/voussoir/trkpt/Database.kt | 58 +++++++ app/src/main/java/net/voussoir/trkpt/Track.kt | 160 ++++++------------ .../java/net/voussoir/trkpt/TrackFragment.kt | 91 +++++----- .../java/net/voussoir/trkpt/TrackerService.kt | 41 +++-- .../net/voussoir/trkpt/TracklistFragment.kt | 5 +- .../main/java/net/voussoir/trkpt/functions.kt | 6 + .../voussoir/trkpt/helpers/DateTimeHelper.kt | 3 - .../trkpt/tracklist/TracklistAdapter.kt | 8 +- app/src/main/res/layout/fragment_track.xml | 37 ++-- 10 files changed, 238 insertions(+), 181 deletions(-) diff --git a/README.md b/README.md index 74631cf..0812f3d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ The goal of this fork is to make 24/7 recording easier. I want to be able to run 1. trkpt stores points in an SQLite database instead of json files. - • Instead of storing the database in the app's private area (`/Android/data/...`), you can put the database in a folder that you sync to your PC with [Syncthing](https://f-droid.org/en/packages/com.nutomic.syncthingandroid/). + • You can put the database in a folder that you sync to your PC with [Syncthing](https://f-droid.org/en/packages/com.nutomic.syncthingandroid/). 2. trkpt does not store "tracks" as objects. Instead, tracks are rendered and exported on the fly by querying the database of trackpoints. @@ -16,3 +16,11 @@ The goal of this fork is to make 24/7 recording easier. I want to be able to run • Although Trackbook has a feature to omit points that are close together, natural GPS inaccuracy and drift is large enough to create points that are far apart, leading to clouds over time. 4. trkpt removes the feature of "starring" waypoints. I recommend using [OsmAnd](https://f-droid.org/en/packages/net.osmand.plus/) to store your favorite places. + +## Mirrors + +https://github.com/voussoir/trkpt + +https://gitlab.com/voussoir/trkpt + +https://codeberg.org/voussoir/trkpt diff --git a/app/src/main/java/net/voussoir/trkpt/Database.kt b/app/src/main/java/net/voussoir/trkpt/Database.kt index e9a85d2..7308c43 100644 --- a/app/src/main/java/net/voussoir/trkpt/Database.kt +++ b/app/src/main/java/net/voussoir/trkpt/Database.kt @@ -60,6 +60,14 @@ class Database(val trackbook: net.voussoir.trkpt.Trackbook) commit() } + fun delete_trkpt_start_end(device_id: String, start_time: Long, end_time: Long) + { + Log.i("VOUSSOIR", "Track.delete ${device_id} ${start_time} -- ${end_time}.") + this.begin_transaction() + this.connection.delete("trkpt", "device_id = ? AND time > ? AND time < ?", arrayOf(device_id, start_time.toString(), end_time.toString())) + this.commit() + } + fun insert_trkpt(trkpt: net.voussoir.trkpt.Trkpt) { Log.i("VOUSSOIR", "Database.insert_trkpt") @@ -76,6 +84,56 @@ class Database(val trackbook: net.voussoir.trkpt.Trackbook) connection.insert("trkpt", null, values) } + fun select_trkpt_start_end(device_id: String, start_time: Long, end_time: Long): Iterator + { + Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between ${start_time} -- ${end_time}.") + return _trkpt_generator(this.connection.rawQuery( + "SELECT device_id, lat, lon, time, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND time > ? AND time < ? ORDER BY time ASC", + arrayOf(device_id, start_time.toString(), end_time.toString()) + )) + } + + fun select_trkpt_bounding_box(device_id: String, north: Double, south: Double, east: Double, west: Double): Iterator + { + Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between $north, $south, $east, $west.") + return _trkpt_generator(this.connection.rawQuery( + "SELECT device_id, lat, lon, time, 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()) + )) + } + + fun _trkpt_generator(cursor: Cursor) = iterator + { + val COLUMN_DEVICE = cursor.getColumnIndex("device_id") + val COLUMN_LAT = cursor.getColumnIndex("lat") + val COLUMN_LON = cursor.getColumnIndex("lon") + val COLUMN_ELE = cursor.getColumnIndex("ele") + val COLUMN_SAT = cursor.getColumnIndex("sat") + val COLUMN_ACCURACY = cursor.getColumnIndex("accuracy") + val COLUMN_TIME = cursor.getColumnIndex("time") + try + { + while (cursor.moveToNext()) + { + val trkpt = Trkpt( + device_id=cursor.getString(COLUMN_DEVICE), + provider="", + latitude=cursor.getDouble(COLUMN_LAT), + longitude=cursor.getDouble(COLUMN_LON), + altitude=cursor.getDouble(COLUMN_ELE), + accuracy=cursor.getFloat(COLUMN_ACCURACY), + time=cursor.getLong(COLUMN_TIME), + numberSatellites=cursor.getInt(COLUMN_SAT), + ) + yield(trkpt) + } + } + finally + { + cursor.close() + } + } + fun delete_homepoint(id: Long) { Log.i("VOUSSOIR", "Database.delete_homepoint") diff --git a/app/src/main/java/net/voussoir/trkpt/Track.kt b/app/src/main/java/net/voussoir/trkpt/Track.kt index 3b6b814..b874179 100644 --- a/app/src/main/java/net/voussoir/trkpt/Track.kt +++ b/app/src/main/java/net/voussoir/trkpt/Track.kt @@ -21,7 +21,6 @@ package net.voussoir.trkpt import android.content.Context -import android.database.Cursor import android.net.Uri import android.os.Handler import android.os.Looper @@ -34,23 +33,13 @@ import java.util.* data class Track ( val database: net.voussoir.trkpt.Database, val device_id: String, - var start_time: Date, - var end_time: Date, var name: String = "", + var _start_time: Long = 0L, + var _end_time: Long = 0L, val trkpts: ArrayList = ArrayList(), - var view_latitude: Double = Keys.DEFAULT_LATITUDE, - var view_longitude: Double = Keys.DEFAULT_LONGITUDE, var trackFormatVersion: Int = Keys.CURRENT_TRACK_FORMAT_VERSION, ) { - fun delete() - { - Log.i("VOUSSOIR", "Track.delete ${device_id} ${start_time} -- ${end_time}.") - database.begin_transaction() - database.connection.delete("trkpt", "device_id = ? AND time > ? AND time < ?", arrayOf(device_id, start_time.time.toString(), end_time.time.toString())) - database.commit() - } - fun export_gpx(context: Context, fileuri: Uri): Uri? { if (! database.ready) @@ -88,7 +77,7 @@ data class Track ( write("\t\t") var previous: Trkpt? = null - for (trkpt in trkpt_generator()) + for (trkpt in this.trkpts) { if (previous != null && (trkpt.time - previous.time) > (Keys.STOP_OVER_THRESHOLD)) { @@ -96,9 +85,10 @@ data class Track ( write("\t\t") } write("\t\t\t") - write("\t\t\t\t${trkpt.altitude}") write("\t\t\t\t") write("\t\t\t\t${trkpt.time}") + write("\t\t\t\t${trkpt.altitude}") + write("\t\t\t\t${trkpt.accuracy}") write("\t\t\t\t${trkpt.numberSatellites}") write("\t\t\t") previous = trkpt @@ -114,107 +104,65 @@ data class Track ( return fileuri } - fun load_trkpts() + fun load_trkpts(points: Iterator) { this.trkpts.clear() - trkpt_generator().forEach { trkpt -> this.trkpts.add(trkpt) } - if (this.trkpts.size > 0) - { - this.view_latitude = this.trkpts.first().latitude - this.view_longitude = this.trkpts.first().longitude - } - } - - fun statistics(): TrackStatistics - { - Log.i("VOUSSOIR", "Track.statistics") - var first: Trkpt? = null - var last: Trkpt? = null - var previous: Trkpt? = null - val stats = TrackStatistics() - for (trkpt in trkpt_generator()) - { - if (previous == null) - { - first = trkpt - previous = trkpt - stats.max_altitude = trkpt.altitude - stats.min_altitude = trkpt.altitude - continue - } - stats.distance += previous.toLocation().distanceTo(trkpt.toLocation()) - val ascentdiff = trkpt.altitude - previous.altitude - if (ascentdiff > 0) - { - stats.total_ascent += ascentdiff - } - else - { - stats.total_descent += ascentdiff - } - if (trkpt.altitude > stats.max_altitude) - { - stats.max_altitude = trkpt.altitude - } - if (trkpt.altitude < stats.min_altitude) - { - stats.min_altitude = trkpt.altitude - } - previous = trkpt - last = trkpt - } - if (first == null || last == null) - { - return stats - } - stats.duration = last.time - first.time - stats.velocity = stats.distance / (stats.duration / 1000) - return stats - } - - fun trkpt_generator() = iterator - { - var cursor: Cursor = database.connection.rawQuery( - "SELECT lat, lon, time, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND time > ? AND time < ? ORDER BY time ASC", - arrayOf(device_id, start_time.time.toString(), end_time.time.toString()) - ) - Log.i("VOUSSOIR", "Track.trkpt_generator: Querying points between ${start_time} -- ${end_time}, ${cursor.count} results") - val COLUMN_LAT = cursor.getColumnIndex("lat") - val COLUMN_LON = cursor.getColumnIndex("lon") - val COLUMN_ELE = cursor.getColumnIndex("ele") - val COLUMN_SAT = cursor.getColumnIndex("sat") - val COLUMN_ACCURACY = cursor.getColumnIndex("accuracy") - val COLUMN_TIME = cursor.getColumnIndex("time") - try - { - while (cursor.moveToNext()) - { - val trkpt = Trkpt( - device_id=device_id, - provider="", - latitude=cursor.getDouble(COLUMN_LAT), - longitude=cursor.getDouble(COLUMN_LON), - altitude=cursor.getDouble(COLUMN_ELE), - accuracy=cursor.getFloat(COLUMN_ACCURACY), - time=cursor.getLong(COLUMN_TIME), - numberSatellites=cursor.getInt(COLUMN_SAT), - ) - yield(trkpt) - } - } - finally - { - cursor.close() - } + points.forEach { trkpt -> this.trkpts.add(trkpt) } } } data class TrackStatistics( + val trkpts: ArrayList, var distance: Double = 0.0, var duration: Long = 0, var velocity: Double = 0.0, var total_ascent: Double = 0.0, var total_descent: Double = 0.0, var max_altitude: Double = 0.0, - var min_altitude: Double = 0.0, + var min_altitude: Double = 0.0 ) +{ + init + { + Log.i("VOUSSOIR", "Track.statistics") + var first: Trkpt? = null + var last: Trkpt? = null + var previous: Trkpt? = null + for (trkpt in trkpts) + { + if (previous == null) + { + first = trkpt + previous = trkpt + max_altitude = trkpt.altitude + min_altitude = trkpt.altitude + continue + } + distance += previous.toLocation().distanceTo(trkpt.toLocation()) + val ascentdiff = trkpt.altitude - previous.altitude + if (ascentdiff > 0) + { + total_ascent += ascentdiff + } + else + { + total_descent += ascentdiff + } + if (trkpt.altitude > max_altitude) + { + max_altitude = trkpt.altitude + } + if (trkpt.altitude < min_altitude) + { + min_altitude = trkpt.altitude + } + previous = trkpt + last = trkpt + } + if (first != null && last != null) + { + duration = last.time - first.time + velocity = distance / (duration / 1000) + } + } +} diff --git a/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt b/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt index a65f637..54714d4 100644 --- a/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt +++ b/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt @@ -64,8 +64,7 @@ import net.voussoir.trkpt.helpers.LengthUnitHelper import net.voussoir.trkpt.helpers.PreferencesHelper import net.voussoir.trkpt.helpers.UiHelper import net.voussoir.trkpt.helpers.create_start_end_markers -import net.voussoir.trkpt.helpers.iso8601 -import net.voussoir.trkpt.helpers.iso8601_parse +import net.voussoir.trkpt.helpers.iso8601_local import java.text.SimpleDateFormat import java.util.* @@ -85,6 +84,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener lateinit var track_query_end_date: DatePicker lateinit var track_query_end_time: TimePicker lateinit var delete_selected_trkpt_button: ImageButton + lateinit var when_was_i_here_button: ImageButton var track_query_start_time_previous: Int = 0 var track_query_end_time_previous: Int = 0 private lateinit var mapView: MapView @@ -118,15 +118,18 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { this.trackbook = (requireContext().applicationContext as Trackbook) - val database: net.voussoir.trkpt.Database = (requireActivity().applicationContext as Trackbook).database + val requested_start_time = this.requireArguments().getString(Keys.ARG_TRACK_START_TIME)!!.toLong() + val requested_end_time = this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!.toLong() track = Track( - database=database, - name=this.requireArguments().getString(Keys.ARG_TRACK_TITLE, ""), + database=this.trackbook.database, device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""), - start_time=iso8601_parse(this.requireArguments().getString(Keys.ARG_TRACK_START_TIME)!!), - end_time=iso8601_parse(this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!), + name=this.requireArguments().getString(Keys.ARG_TRACK_TITLE, ""), ) - track.load_trkpts() + track.load_trkpts(this.trackbook.database.select_trkpt_start_end( + device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""), + start_time=requested_start_time, + end_time=requested_end_time, + )) rootView = inflater.inflate(R.layout.fragment_track, container, false) mapView = rootView.findViewById(R.id.map) save_track_button = rootView.findViewById(R.id.save_button) @@ -142,7 +145,11 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener mapView.isVerticalMapRepetitionEnabled = false mapView.setMultiTouchControls(true) mapView.zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER) - controller.setCenter(GeoPoint(track.view_latitude, track.view_longitude)) + if (track.trkpts.size > 0) + { + val first = track.trkpts.first() + controller.setCenter(GeoPoint(first.latitude, first.longitude)) + } controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL) // trkpt_infowindow = MarkerInfoWindow(R.layout.trkpt_infowindow, mapView) @@ -170,8 +177,8 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener mapView.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS) } - val actual_start_time: Date = if (track.trkpts.isEmpty()) track.start_time else Date(track.trkpts.first().time) - val actual_end_time: Date = if (track.trkpts.isEmpty()) track.end_time else Date(track.trkpts.last().time) + val actual_start_time: Date = if (track.trkpts.isEmpty()) Date(requested_start_time) else Date(track.trkpts.first().time) + val actual_end_time: Date = if (track.trkpts.isEmpty()) Date(requested_end_time) else Date(track.trkpts.last().time) track_query_start_date = rootView.findViewById(R.id.track_query_start_date) val start_cal = GregorianCalendar() @@ -263,6 +270,18 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener mapView.invalidate() } } + when_was_i_here_button = rootView.findViewById(R.id.when_was_i_here_button) + when_was_i_here_button.setOnClickListener { + Log.i("VOUSSOIR", "when_was_i_here_button.") + track.load_trkpts(trackbook.database.select_trkpt_bounding_box( + device_id=track.device_id, + north=mapView.boundingBox.actualNorth, + south=mapView.boundingBox.actualSouth, + east=mapView.boundingBox.lonEast, + west=mapView.boundingBox.lonWest, + )) + render_track() + } save_track_button.setOnClickListener { openSaveGpxDialog() @@ -303,6 +322,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener fun render_track() { Log.i("VOUSSOIR", "TrackFragment.render_track") + mapView.invalidate() mapView.overlays.clear() track_segment_overlays.clear() delete_selected_trkpt_button.visibility = View.GONE @@ -362,7 +382,7 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener } val trkpt = (points[point]) as Trkpt Log.i("VOUSSOIR", "Clicked ${trkpt.device_id} ${trkpt.time}") - selected_trkpt_info.text = "${trkpt.time}\n${iso8601(trkpt.time)}\n${trkpt.latitude}\n${trkpt.longitude}" + selected_trkpt_info.text = "${trkpt.time}\n${iso8601_local(trkpt.time)}\n${trkpt.latitude}\n${trkpt.longitude}" delete_selected_trkpt_button.visibility = View.VISIBLE return } @@ -406,14 +426,17 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener private fun setupStatisticsViews() { - val stats: TrackStatistics = track.statistics() + val stats: TrackStatistics = TrackStatistics(track.trkpts) trackNameView.text = track.name distanceView.text = LengthUnitHelper.convertDistanceToString(stats.distance, useImperialUnits) waypointsView.text = track.trkpts.size.toString() durationView.text = DateTimeHelper.convertToReadableTime(requireContext(), stats.duration) velocityView.text = LengthUnitHelper.convertToVelocityString(stats.velocity, useImperialUnits) - recordingStartView.text = DateTimeHelper.convertToReadableDateAndTime(track.start_time) - recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(track.end_time) + if (track.trkpts.isNotEmpty()) + { + recordingStartView.text = DateTimeHelper.convertToReadableDateAndTime(Date(track.trkpts.first().time)) + recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(Date(track.trkpts.last().time)) + } maxAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.max_altitude, useImperialUnits) minAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.min_altitude, useImperialUnits) positiveElevationView.text = LengthUnitHelper.convertDistanceToString(stats.total_ascent, useImperialUnits) @@ -464,12 +487,13 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener override fun run() { Log.i("VOUSSOIR", "TrackFragment.requery_and_render") - track.start_time = get_datetime(track_query_start_date, track_query_start_time, seconds=0) - track.end_time = get_datetime(track_query_end_date, track_query_end_time, seconds=59) - track.load_trkpts() + track.load_trkpts(trackbook.database.select_trkpt_start_end( + track.device_id, + 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, + )) Log.i("VOUSSOIR", "TrackFragment.requery_and_render: Reloaded ${track.trkpts.size} trkpts.") render_track() - mapView.invalidate() } } @@ -499,33 +523,22 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener /* Overrides onYesNoDialog from YesNoDialogListener */ override fun onYesNoDialog(type: Int, dialogResult: Boolean, payload: Int, payloadString: String) { - when (type) + if (type == Keys.DIALOG_DELETE_TRACK && dialogResult && track.trkpts.isNotEmpty()) { - Keys.DIALOG_DELETE_TRACK -> { - when (dialogResult) - { - // user tapped remove track - true -> { - track.delete() - handler.removeCallbacks(requery_and_render) - handler.postDelayed(requery_and_render, RERENDER_DELAY) - // switch to TracklistFragment and remove track there - // val bundle: Bundle = bundleOf(Keys.ARG_TRACK_ID to layout.track.id) - // findNavController().navigate(R.id.tracklist_fragment, bundle) - } - else -> - { - ; - } - } - } + trackbook.database.delete_trkpt_start_end(track.device_id, track.trkpts.first().time, track.trkpts.last().time) + handler.removeCallbacks(requery_and_render) + handler.postDelayed(requery_and_render, RERENDER_DELAY) } } /* Opens up a file picker to select the save location */ private fun openSaveGpxDialog() { - val export_name: String = SimpleDateFormat("yyyy-MM-dd", Locale.US).format(track.start_time) + " " + track.device_id + Keys.GPX_FILE_EXTENSION + if (track.trkpts.isEmpty()) + { + return + } + val export_name: String = SimpleDateFormat("yyyy-MM-dd", Locale.US).format(track.trkpts.first().time) + " " + track.device_id + Keys.GPX_FILE_EXTENSION val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = Keys.MIME_TYPE_GPX diff --git a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt index 65c213c..45c078b 100644 --- a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt +++ b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt @@ -20,30 +20,44 @@ package net.voussoir.trkpt +import android.Manifest import android.app.Notification +import android.app.NotificationChannel import android.app.NotificationManager +import android.app.PendingIntent import android.app.Service +import android.app.TaskStackBuilder import android.content.Context import android.content.Intent -import android.content.pm.PackageManager import android.content.SharedPreferences +import android.content.pm.PackageManager import android.location.Location import android.location.LocationListener import android.location.LocationManager -import android.Manifest -import android.app.NotificationChannel -import android.app.PendingIntent -import android.app.TaskStackBuilder -import android.os.* +import android.media.AudioManager +import android.media.ToneGenerator +import android.os.Binder +import android.os.Build +import android.os.IBinder import android.util.Log import androidx.annotation.RequiresApi import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toBitmap +import net.voussoir.trkpt.helpers.PreferencesHelper +import net.voussoir.trkpt.helpers.getDefaultLocation +import net.voussoir.trkpt.helpers.getLastKnownLocation +import net.voussoir.trkpt.helpers.isAccurateEnough +import net.voussoir.trkpt.helpers.isBetterLocation +import net.voussoir.trkpt.helpers.isDifferentEnough +import net.voussoir.trkpt.helpers.isGpsEnabled +import net.voussoir.trkpt.helpers.isNetworkEnabled +import net.voussoir.trkpt.helpers.isRecentEnough +import net.voussoir.trkpt.helpers.iso8601 +import net.voussoir.trkpt.helpers.random_device_id import org.osmdroid.util.GeoPoint import java.util.* -import net.voussoir.trkpt.helpers.* class TrackerService: Service() { @@ -64,6 +78,7 @@ class TrackerService: Service() private lateinit var notificationManager: NotificationManager private lateinit var notification_builder: NotificationCompat.Builder + val beeper = ToneGenerator(AudioManager.STREAM_MUSIC, 100) private lateinit var locationManager: LocationManager private lateinit var gpsLocationListener: LocationListener @@ -189,16 +204,18 @@ class TrackerService: Service() { Log.i("VOUSSOIR", "Processing point ${location.time} ${location.latitude}, ${location.longitude}.") + // beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150) + if (location.time == currentBestLocation.time) { return } - // if (! isBetterLocation(location, currentBestLocation)) - // { - // Log.i("VOUSSOIR", "Not better than previous.") - // return - // } + if (! isBetterLocation(location, currentBestLocation)) + { + Log.i("VOUSSOIR", "Not better than previous.") + return + } currentBestLocation = location diff --git a/app/src/main/java/net/voussoir/trkpt/TracklistFragment.kt b/app/src/main/java/net/voussoir/trkpt/TracklistFragment.kt index f1c3359..4a19974 100644 --- a/app/src/main/java/net/voussoir/trkpt/TracklistFragment.kt +++ b/app/src/main/java/net/voussoir/trkpt/TracklistFragment.kt @@ -35,7 +35,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers.Main -import net.voussoir.trkpt.helpers.iso8601 import net.voussoir.trkpt.tracklist.TracklistAdapter /* @@ -80,8 +79,8 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, val bundle: Bundle = bundleOf( Keys.ARG_TRACK_TITLE to track.name, Keys.ARG_TRACK_DEVICE_ID to track.device_id, - Keys.ARG_TRACK_START_TIME to iso8601(track.start_time), - Keys.ARG_TRACK_STOP_TIME to iso8601(track.end_time), + Keys.ARG_TRACK_START_TIME to track._start_time.toString(), + Keys.ARG_TRACK_STOP_TIME to track._end_time.toString(), ) findNavController().navigate(R.id.fragment_track, bundle) } diff --git a/app/src/main/java/net/voussoir/trkpt/functions.kt b/app/src/main/java/net/voussoir/trkpt/functions.kt index d86f587..c43815d 100644 --- a/app/src/main/java/net/voussoir/trkpt/functions.kt +++ b/app/src/main/java/net/voussoir/trkpt/functions.kt @@ -14,6 +14,12 @@ fun iso8601(timestamp: Long): String return iso8601_format.format(timestamp) } +fun iso8601_local(timestamp: Long): String +{ + val iso8601_format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS") + return iso8601_format.format(timestamp) +} + fun iso8601(datetime: Date): String { return iso8601(datetime.time) diff --git a/app/src/main/java/net/voussoir/trkpt/helpers/DateTimeHelper.kt b/app/src/main/java/net/voussoir/trkpt/helpers/DateTimeHelper.kt index 72fe319..e4cb267 100644 --- a/app/src/main/java/net/voussoir/trkpt/helpers/DateTimeHelper.kt +++ b/app/src/main/java/net/voussoir/trkpt/helpers/DateTimeHelper.kt @@ -23,9 +23,6 @@ import java.text.DateFormat import java.util.* import java.util.concurrent.TimeUnit -/* - * DateTimeHelper object - */ object DateTimeHelper { /* Converts milliseconds to mm:ss or hh:mm:ss */ diff --git a/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt b/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt index df693d3..bbe3dd4 100644 --- a/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt +++ b/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt @@ -64,12 +64,12 @@ class TracklistAdapter(val fragment: Fragment, val database: net.voussoir.trkpt. { val trackdate = cursor.getString(0) val device_id = cursor.getString(1) - val start_time: Date? = df.parse(trackdate + "T00:00:00.000") - val stop_time: Date? = df.parse(trackdate + "T23:59:59.999") + val start_time: Long? = df.parse(trackdate + "T00:00:00.000").time + val stop_time: Long? = df.parse(trackdate + "T23:59:59.999").time Log.i("VOUSSOIR", "TracklistAdapter prep track ${trackdate}") if (start_time != null && stop_time != null) { - val track = Track(database=database, device_id=device_id, start_time=start_time, end_time=stop_time) + val track = Track(database=database, device_id=device_id, _start_time=start_time, _end_time=stop_time) track.name = "$trackdate $device_id" tracks.add(track) } @@ -115,7 +115,7 @@ class TracklistAdapter(val fragment: Fragment, val database: net.voussoir.trkpt. /* Get track name for given position */ fun getTrackName(positionInRecyclerView: Int): String { - return SimpleDateFormat("yyyy-MM-dd", Locale.US).format(tracks[positionInRecyclerView].start_time) + return SimpleDateFormat("yyyy-MM-dd", Locale.US).format(tracks[positionInRecyclerView]._start_time) } fun delete_track_at_position(context: Context, index: Int) diff --git a/app/src/main/res/layout/fragment_track.xml b/app/src/main/res/layout/fragment_track.xml index 3ad0ac4..ddb0551 100755 --- a/app/src/main/res/layout/fragment_track.xml +++ b/app/src/main/res/layout/fragment_track.xml @@ -21,22 +21,12 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - - + + + app:layout_constraintTop_toBottomOf="@+id/trackfragment_tools_constraint_layout"/> - +