diff --git a/README.md b/README.md
index b31aba6..100cf62 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ The goal of this fork is to make 24/7 recording easier. I want to be able to run
trkpt has three states of power management. The states transition like this:
-1. **FULL POWER**: receives location updates as fast as Android provides them. A wakelock is used to prevent doze.
+1. **FULL POWER**: receives location updates as fast as Android provides them. A wakelock is used to resist doze (though I think some devices will doze anyway because they do not respect the user).
Stay near homepoint for a few minutes → Sleep
diff --git a/app/build.gradle b/app/build.gradle
index a1e648e..cfe2251 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -10,8 +10,8 @@ android {
applicationId 'net.voussoir.trkpt'
minSdkVersion 25
targetSdk 32
- versionCode 54
- versionName '1.0.3'
+ versionCode 55
+ versionName '1.1.0'
resConfigs "en", "da", "de", "fr", "hr", "id", "it", "ja", "nb-rNO", "nl", "pl", "pt-rBR", "ru", "sv", "tr", "zh-rCN"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a0830e4..f0c8f51 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -53,18 +53,6 @@
-
-
-
-
-
-
-
"stop"
+ Keys.STATE_FULL_RECORDING -> "recording"
+ Keys.STATE_ARRIVED_AT_HOME -> "home"
+ Keys.STATE_SLEEP -> "sleep"
+ Keys.STATE_DEAD -> "dead"
+ Keys.STATE_MAPVIEW -> "mapview"
+ else -> tracker.tracking_state.toString()
+ }
+ }
+
val redraw_runnable: Runnable = object : Runnable
{
override fun run()
diff --git a/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt b/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt
index f747ea1..d498870 100644
--- a/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt
+++ b/app/src/main/java/net/voussoir/trkpt/TrackFragment.kt
@@ -173,8 +173,8 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener
mapView.zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER)
if (track.trkpts.size > 0)
{
- val first = track.trkpts.first()
- controller.setCenter(GeoPoint(first.latitude, first.longitude))
+ val last = track.trkpts.last()
+ controller.setCenter(GeoPoint(last.latitude, last.longitude))
}
controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL)
diff --git a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt
index 2be5483..f9313ee 100644
--- a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt
+++ b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt
@@ -43,20 +43,20 @@ class TrackerService: Service()
lateinit var trackbook: Trackbook
val handler: Handler = Handler(Looper.getMainLooper())
- var trackingState: Int = Keys.STATE_TRACKING_STOPPED
+ var tracking_state: Int = Keys.STATE_STOP
var useImperial: Boolean = false
var omitRests: Boolean = true
var max_accuracy: Float = Keys.DEFAULT_MAX_ACCURACY
var allow_sleep: Boolean = true
var device_id: String = random_device_id()
var currentBestLocation: Location = getDefaultLocation()
- var lastCommit: Long = 0
+ var last_commit: Long = 0
+ var foreground_started: Long = 0
var listeners_enabled_at: Long = 0
var last_significant_motion: Long = 0
var last_watchdog: Long = 0
var gave_up_at: Long = 0
var arrived_at_home: Long = 0
- var location_interval: Long = 0
val TIME_UNTIL_SLEEP: Long = 5 * Keys.ONE_MINUTE_IN_MILLISECONDS
val TIME_UNTIL_DEAD: Long = 3 * Keys.ONE_MINUTE_IN_MILLISECONDS
val WATCHDOG_INTERVAL: Long = 61 * Keys.ONE_SECOND_IN_MILLISECONDS
@@ -67,7 +67,7 @@ class TrackerService: Service()
var bound: Boolean = false
private val binder = TrackerServiceBinder(this)
- private lateinit var notificationManager: NotificationManager
+ private lateinit var notification_manager: NotificationManager
private lateinit var notification_builder: NotificationCompat.Builder
private lateinit var locationManager: LocationManager
@@ -90,7 +90,7 @@ class TrackerService: Service()
lateinit var wakelock: PowerManager.WakeLock
- private fun addGpsLocationListener(interval: Long): Boolean
+ private fun add_gps_location_listener(interval: Long): Boolean
{
gpsLocationListenerRegistered = false
gpsProviderActive = isGpsEnabled(locationManager)
@@ -118,7 +118,7 @@ class TrackerService: Service()
return true
}
- private fun addNetworkLocationListener(interval: Long): Boolean
+ private fun add_network_location_listener(interval: Long): Boolean
{
networkLocationListenerRegistered = false
networkProviderActive = isNetworkEnabled(locationManager)
@@ -146,7 +146,7 @@ class TrackerService: Service()
return true
}
- fun removeGpsLocationListener()
+ fun remove_gps_location_listener()
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
@@ -160,7 +160,7 @@ class TrackerService: Service()
}
}
- fun removeNetworkLocationListener()
+ fun remove_network_location_listener()
{
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
@@ -174,67 +174,171 @@ class TrackerService: Service()
}
}
- fun reset_location_listeners(interval: Long)
+ fun load_tracking_state()
{
- Log.i("VOUSSOIR", "TrackerService.reset_location_listeners")
- location_interval = interval
- if (use_gps_location && interval != Keys.LOCATION_INTERVAL_DEAD && interval != Keys.LOCATION_INTERVAL_STOP)
+ tracking_state = PreferencesHelper.loadTrackingState()
+ when (tracking_state)
{
- addGpsLocationListener(interval)
+ Keys.STATE_STOP -> state_stop()
+ Keys.STATE_MAPVIEW -> state_mapview()
+ Keys.STATE_FULL_RECORDING -> state_full_recording()
+ Keys.STATE_ARRIVED_AT_HOME -> state_arrived_at_home()
+ Keys.STATE_SLEEP -> state_sleep()
+ Keys.STATE_DEAD -> state_dead()
}
- else if (gpsLocationListenerRegistered)
+ }
+
+ fun state_stop()
+ {
+ // This state is activated when the user intentionally stops the recording, or exits the
+ // mapfragment without starting to record.
+ Log.i("VOUSSOIR", "TrackerService.state_stop")
+ tracking_state = Keys.STATE_STOP
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_STOP)
+ trackbook.database.commit()
+ recent_displacement_locations.clear()
+ arrived_at_home = 0
+ gave_up_at = 0
+ if (foreground_started > 0)
{
- removeGpsLocationListener()
+ stopForeground(STOP_FOREGROUND_DETACH)
+ foreground_started = 0
}
- if (use_network_location && interval != Keys.LOCATION_INTERVAL_DEAD && interval != Keys.LOCATION_INTERVAL_STOP)
+ stop_wakelock()
+ displayNotification()
+ }
+ fun state_full_recording()
+ {
+ // This state is the only one that will record points into the database, and tracks location
+ // at full power. A wakelock is used to resist Android's doze. This state should be active
+ // while out and about.
+ Log.i("VOUSSOIR", "TrackerService.state_full_power")
+ tracking_state = Keys.STATE_FULL_RECORDING
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
+ arrived_at_home = 0
+ gave_up_at = 0
+ if (foreground_started == 0L)
+ {
+ startForeground(Keys.TRACKER_SERVICE_NOTIFICATION_ID, displayNotification())
+ foreground_started = System.currentTimeMillis()
+ }
+ if (gpsLocationListenerRegistered || networkLocationListenerRegistered)
{
- addNetworkLocationListener(interval)
+ start_wakelock()
}
- else if (networkLocationListenerRegistered)
+ else
{
- removeNetworkLocationListener()
+ state_dead()
}
+ displayNotification()
+ }
+ fun state_arrived_at_home()
+ {
+ // This state is activated when the user enters the radius of a homepoint. The GPS will
+ // remain at full power for a few minutes before we transition to sleep.
+ Log.i("VOUSSOIR", "TrackerService.state_arrived_at_home")
+ tracking_state = Keys.STATE_ARRIVED_AT_HOME
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
+ trackbook.database.commit()
+ arrived_at_home = System.currentTimeMillis()
+ gave_up_at = 0
+ stop_wakelock()
+ displayNotification()
+ }
+ fun state_sleep()
+ {
+ // This state is activated when the user stays at a homepoint for several minutes. It will
+ // be woken up again by the acceleromters or by plugging / unplugging power.
+ Log.i("VOUSSOIR", "TrackerService.state_sleep")
+ tracking_state = Keys.STATE_SLEEP
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_SLEEP)
+ arrived_at_home = arrived_at_home
+ gave_up_at = 0
+ stop_wakelock()
+ displayNotification()
+ }
+ fun state_dead()
+ {
+ // This state is activated when the device is struggling to receive a GPS fix due to being
+ // indoors / underground. It will be woken up again by the accelerometers or by plugging /
+ // unplugging power.
+ Log.i("VOUSSOIR", "TrackerService.state_dead")
+ tracking_state = Keys.STATE_DEAD
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_STOP)
+ trackbook.database.commit()
+ recent_displacement_locations.clear()
+ arrived_at_home = 0
+ gave_up_at = System.currentTimeMillis()
+ stop_wakelock()
+ displayNotification()
+ }
+ fun state_mapview()
+ {
+ // This state should be activated when the user has the app open to the mapfragment, but is
+ // not recording. If the user closes the app while in this state, we can go to stop.
+ Log.i("VOUSSOIR", "TrackerService.state_mapview")
+ tracking_state = Keys.STATE_MAPVIEW
+ PreferencesHelper.saveTrackingState(tracking_state)
+ reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
+ arrived_at_home = 0
+ gave_up_at = 0
+ stop_wakelock()
+ displayNotification()
+ if (!gpsLocationListenerRegistered && !networkLocationListenerRegistered)
+ {
+ state_dead()
+ }
+ }
- if (interval != Keys.LOCATION_INTERVAL_DEAD)
+ fun start_wakelock()
+ {
+ if (!wakelock.isHeld)
{
- gave_up_at = 0
+ wakelock.acquire()
}
+ }
- if (gpsLocationListenerRegistered || networkLocationListenerRegistered)
+ fun stop_wakelock()
+ {
+ if (wakelock.isHeld)
{
- listeners_enabled_at = System.currentTimeMillis()
- if (interval != Keys.LOCATION_INTERVAL_SLEEP)
- {
- arrived_at_home = 0
- }
+ wakelock.release()
}
- else if (interval == Keys.LOCATION_INTERVAL_STOP)
+ }
+
+ fun reset_location_listeners(interval: Long)
+ {
+ Log.i("VOUSSOIR", "TrackerService.reset_location_listeners")
+ if (use_gps_location && interval != Keys.LOCATION_INTERVAL_STOP)
{
- listeners_enabled_at = 0
+ add_gps_location_listener(interval)
}
- else
+ else if (gpsLocationListenerRegistered)
{
- listeners_enabled_at = 0
- location_interval = Keys.LOCATION_INTERVAL_DEAD
+ remove_gps_location_listener()
}
-
- val should_wakelock = (
- (gpsLocationListenerRegistered || networkLocationListenerRegistered) &&
- trackingState == Keys.STATE_TRACKING_ACTIVE &&
- interval == Keys.LOCATION_INTERVAL_FULL_POWER
- )
- if (should_wakelock)
+ if (use_network_location && interval != Keys.LOCATION_INTERVAL_STOP)
{
- if (! wakelock.isHeld)
- {
- wakelock.acquire()
- }
+ add_network_location_listener(interval)
}
- else if (wakelock.isHeld)
+ else if (networkLocationListenerRegistered)
{
- wakelock.release()
+ remove_network_location_listener()
}
+ if (gpsLocationListenerRegistered || networkLocationListenerRegistered)
+ {
+ listeners_enabled_at = System.currentTimeMillis()
+ }
+ else
+ {
+ listeners_enabled_at = 0
+ }
displayNotification()
}
@@ -253,10 +357,11 @@ class TrackerService: Service()
currentBestLocation = location
- if (trackingState != Keys.STATE_TRACKING_ACTIVE)
+ if (tracking_state == Keys.STATE_STOP || tracking_state == Keys.STATE_MAPVIEW)
{
return
}
+
if(! trackbook.database.ready)
{
Log.i("VOUSSOIR", "Omitting due to database not ready.")
@@ -283,34 +388,43 @@ class TrackerService: Service()
continue
}
Log.i("VOUSSOIR", "Omitting due to homepoint ${index} ${homepoint.name}.")
+
+ // Move this homepoint to the front of the list so that on subsequent location
+ // updates it hits on the first loop. I'm sure this is a trivial amount of
+ // savings but oh well.
if (index > 0)
{
trackbook.homepoints.remove(homepoint)
trackbook.homepoints.addFirst(homepoint)
}
- if (arrived_at_home == 0L)
+ if (tracking_state != Keys.STATE_ARRIVED_AT_HOME && tracking_state != Keys.STATE_SLEEP)
{
Log.i("VOUSSOIR", "Arrived at home.")
- arrived_at_home = System.currentTimeMillis()
- trackbook.database.commit()
+ state_arrived_at_home()
}
else if (
allow_sleep &&
has_motion_sensor &&
- location_interval != Keys.LOCATION_INTERVAL_SLEEP &&
+ tracking_state == Keys.STATE_ARRIVED_AT_HOME &&
(System.currentTimeMillis() - arrived_at_home) > TIME_UNTIL_SLEEP &&
(System.currentTimeMillis() - last_significant_motion) > TIME_UNTIL_SLEEP
)
{
Log.i("VOUSSOIR", "Staying at home, sleeping.")
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_SLEEP)
+ state_sleep()
}
return
}
- if (arrived_at_home > 0)
+
+ // All of the homepoint checks failed so we have left home and it's time to wake up.
+ // In practice we expect that the accelerometers would have triggered this change
+ // already, but this acts as a backup in case you somehow leave home without too
+ // much movement (maybe you sat in the car for several minutes before finally
+ // driving away or something).
+ if (tracking_state == Keys.STATE_ARRIVED_AT_HOME || tracking_state == Keys.STATE_SLEEP)
{
Log.i("VOUSSOIR", "Leaving home.")
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
if (! isRecentEnough(location))
@@ -351,10 +465,10 @@ class TrackerService: Service()
recent_displacement_locations.removeFirst()
}
- if (location.time - lastCommit > Keys.COMMIT_INTERVAL)
+ if ((location.time - last_commit) > Keys.COMMIT_INTERVAL)
{
trackbook.database.commit()
- lastCommit = location.time
+ last_commit = location.time
}
}
override fun onProviderEnabled(provider: String)
@@ -385,43 +499,34 @@ class TrackerService: Service()
}
val timestamp = iso8601_local_noms(currentBestLocation.time)
- if (trackingState == Keys.STATE_TRACKING_ACTIVE)
+ if (tracking_state == Keys.STATE_FULL_RECORDING)
{
- notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_running))
- if (location_interval == Keys.LOCATION_INTERVAL_FULL_POWER && arrived_at_home > 0)
- {
- notification_builder.setContentTitle("${timestamp} (home)")
- notification_builder.setSmallIcon(R.drawable.ic_satellite_24dp)
- }
- else if (location_interval == Keys.LOCATION_INTERVAL_FULL_POWER)
- {
- notification_builder.setContentTitle("${timestamp} (recording)")
- notification_builder.setSmallIcon(R.drawable.ic_satellite_24dp)
- }
- else if (location_interval == Keys.LOCATION_INTERVAL_SLEEP)
- {
- notification_builder.setContentTitle("${timestamp} (sleeping)")
- notification_builder.setSmallIcon(R.drawable.ic_sleep_24dp)
- }
- else if (location_interval == Keys.LOCATION_INTERVAL_DEAD)
- {
- notification_builder.setContentTitle("${timestamp} (dead)")
- notification_builder.setSmallIcon(R.drawable.ic_skull_24dp)
- }
- else
- {
- notification_builder.setContentText(timestamp)
- notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_record_inactive_24dp)
- }
+ notification_builder.setContentTitle("${timestamp} (recording)")
+ notification_builder.setSmallIcon(R.drawable.ic_satellite_24dp)
}
- else
+ else if (tracking_state == Keys.STATE_ARRIVED_AT_HOME)
+ {
+ notification_builder.setContentTitle("${timestamp} (home)")
+ notification_builder.setSmallIcon(R.drawable.ic_homepoint_24dp)
+ }
+ else if (tracking_state == Keys.STATE_SLEEP)
+ {
+ notification_builder.setContentTitle("${timestamp} (sleeping)")
+ notification_builder.setSmallIcon(R.drawable.ic_sleep_24dp)
+ }
+ else if (tracking_state == Keys.STATE_DEAD)
+ {
+ notification_builder.setContentTitle("${timestamp} (dead)")
+ notification_builder.setSmallIcon(R.drawable.ic_skull_24dp)
+ }
+ else if (tracking_state == Keys.STATE_STOP || tracking_state == Keys.STATE_MAPVIEW)
{
notification_builder.setContentTitle("${timestamp} (stopped)")
notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_stop_24dp)
}
val notification = notification_builder.build()
- notificationManager.notify(Keys.TRACKER_SERVICE_NOTIFICATION_ID, notification)
+ notification_manager.notify(Keys.TRACKER_SERVICE_NOTIFICATION_ID, notification)
return notification
}
@@ -430,7 +535,7 @@ class TrackerService: Service()
/* Checks if notification channel exists */
@RequiresApi(Build.VERSION_CODES.O)
- private fun nowPlayingChannelExists() = notificationManager.getNotificationChannel(Keys.NOTIFICATION_CHANNEL_RECORDING) != null
+ private fun nowPlayingChannelExists() = notification_manager.getNotificationChannel(Keys.NOTIFICATION_CHANNEL_RECORDING) != null
/* Create a notification channel */
@RequiresApi(Build.VERSION_CODES.O)
@@ -441,18 +546,21 @@ class TrackerService: Service()
this.getString(R.string.notification_channel_recording_name),
NotificationManager.IMPORTANCE_LOW
).apply { description = this@TrackerService.getString(R.string.notification_channel_recording_description) }
- notificationManager.createNotificationChannel(notificationChannel)
+ notification_manager.createNotificationChannel(notificationChannel)
}
/* Overrides onBind from Service */
override fun onBind(p0: Intent?): IBinder
{
Log.i("VOUSSOIR", "TrackerService.onBind")
- if (listeners_enabled_at == 0L && location_interval != Keys.LOCATION_INTERVAL_DEAD)
+ if (tracking_state == Keys.STATE_STOP)
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_mapview()
+ }
+ else
+ {
+ displayNotification()
}
- displayNotification()
bound = true
return binder
}
@@ -461,11 +569,14 @@ class TrackerService: Service()
override fun onRebind(intent: Intent?)
{
Log.i("VOUSSOIR", "TrackerService.onRebind")
- if (listeners_enabled_at == 0L && location_interval != Keys.LOCATION_INTERVAL_DEAD)
+ if (tracking_state == Keys.STATE_STOP)
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_mapview()
+ }
+ else
+ {
+ displayNotification()
}
- displayNotification()
bound = true
}
@@ -475,10 +586,11 @@ class TrackerService: Service()
super.onUnbind(intent)
Log.i("VOUSSOIR", "TrackerService.onUnbind")
bound = false
- // stop receiving location updates - if not tracking
- if (trackingState != Keys.STATE_TRACKING_ACTIVE)
+
+ // the user was only perusing the map and did not start recording, so we'll just stop.
+ if (tracking_state == Keys.STATE_MAPVIEW)
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_STOP)
+ state_stop()
}
// ensures onRebind is called
return true
@@ -498,9 +610,10 @@ class TrackerService: Service()
device_id = PreferencesHelper.load_device_id()
useImperial = PreferencesHelper.loadUseImperialUnits()
omitRests = PreferencesHelper.loadOmitRests()
+ max_accuracy = PreferencesHelper.load_max_accuracy()
allow_sleep = PreferencesHelper.loadAllowSleep()
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
- notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notification_manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notification_builder = NotificationCompat.Builder(this, Keys.NOTIFICATION_CHANNEL_RECORDING)
val showActionPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
addNextIntentWithParentStack(Intent(this@TrackerService, MainActivity::class.java))
@@ -512,7 +625,6 @@ class TrackerService: Service()
networkProviderActive = isNetworkEnabled(locationManager)
gpsLocationListener = createLocationListener()
networkLocationListener = createLocationListener()
- trackingState = PreferencesHelper.loadTrackingState()
currentBestLocation = getLastKnownLocation(this)
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
@@ -526,10 +638,10 @@ class TrackerService: Service()
override fun onTrigger(event: TriggerEvent?) {
Log.i("VOUSSOIR", "Significant motion")
last_significant_motion = System.currentTimeMillis()
- if (trackingState == Keys.STATE_TRACKING_ACTIVE && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
+ if (tracking_state == Keys.STATE_SLEEP || tracking_state == Keys.STATE_DEAD)
{
vibrator.vibrate(100)
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
sensor_manager.requestTriggerSensor(this, significant_motion_sensor)
}
@@ -546,11 +658,10 @@ class TrackerService: Service()
override fun onSensorChanged(event: SensorEvent?) {
Log.i("VOUSSOIR", "Step counter changed")
last_significant_motion = System.currentTimeMillis()
- if (trackingState == Keys.STATE_TRACKING_ACTIVE && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
+ if (tracking_state == Keys.STATE_SLEEP || tracking_state == Keys.STATE_DEAD)
{
- // beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150)
vibrator.vibrate(100)
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
}
@@ -574,9 +685,9 @@ class TrackerService: Service()
{
device_is_charging = false
}
- if (trackingState == Keys.STATE_TRACKING_ACTIVE)
+ if (tracking_state == Keys.STATE_SLEEP || tracking_state == Keys.STATE_DEAD)
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
}
}
@@ -588,6 +699,7 @@ class TrackerService: Service()
val powermanager = getSystemService(Context.POWER_SERVICE) as PowerManager
wakelock = powermanager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "trkpt::wakelock")
+ load_tracking_state()
handler.post(background_watchdog)
}
@@ -599,19 +711,19 @@ class TrackerService: Service()
// SERVICE RESTART (via START_STICKY)
if (intent == null)
{
- if (trackingState == Keys.STATE_TRACKING_ACTIVE)
+ if (tracking_state != Keys.STATE_STOP && tracking_state != Keys.STATE_MAPVIEW)
{
Log.w("VOUSSOIR", "Trackbook has been killed by the operating system. Trying to resume recording.")
- startTracking()
+ state_full_recording()
}
}
else if (intent.action == Keys.ACTION_STOP)
{
- stopTracking()
+ state_stop()
}
else if (intent.action == Keys.ACTION_START)
{
- startTracking()
+ state_full_recording()
}
// START_STICKY is used for services that are explicitly started and stopped as needed
@@ -623,51 +735,24 @@ class TrackerService: Service()
{
Log.i("VOUSSOIR", "TrackerService.onDestroy.")
super.onDestroy()
- if (trackingState == Keys.STATE_TRACKING_ACTIVE)
- {
- stopTracking()
- }
- stopForeground(STOP_FOREGROUND_REMOVE)
+ state_stop()
PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_DEAD)
handler.removeCallbacks(background_watchdog)
unregisterReceiver(charging_broadcast_receiver)
}
- fun startTracking()
- {
- Log.i("VOUSSOIR", "TrackerService.startTracking")
- trackingState = Keys.STATE_TRACKING_ACTIVE
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
- PreferencesHelper.saveTrackingState(trackingState)
- recent_displacement_locations.clear()
- startForeground(Keys.TRACKER_SERVICE_NOTIFICATION_ID, displayNotification())
- }
-
- fun stopTracking()
- {
- Log.i("VOUSSOIR", "TrackerService.stopTracking")
- trackbook.database.commit()
- trackingState = Keys.STATE_TRACKING_STOPPED
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
- PreferencesHelper.saveTrackingState(trackingState)
- recent_displacement_locations.clear()
- displayNotification()
- stopForeground(STOP_FOREGROUND_DETACH)
- }
-
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key)
{
Keys.PREF_LOCATION_GPS ->
{
use_gps_location = PreferencesHelper.load_location_gps()
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
Keys.PREF_LOCATION_NETWORK ->
{
use_network_location = PreferencesHelper.load_location_network()
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
Keys.PREF_USE_IMPERIAL_UNITS ->
{
@@ -684,9 +769,9 @@ class TrackerService: Service()
Keys.PREF_ALLOW_SLEEP ->
{
allow_sleep = PreferencesHelper.loadAllowSleep()
- if (! allow_sleep && trackingState == Keys.STATE_TRACKING_ACTIVE && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
+ if (! allow_sleep && (tracking_state == Keys.STATE_SLEEP || tracking_state == Keys.STATE_DEAD))
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
+ state_full_recording()
}
}
Keys.PREF_DEVICE_ID ->
@@ -723,21 +808,19 @@ class TrackerService: Service()
has_motion_sensor &&
!device_is_charging &&
// We only go to dead during active tracking because if you are looking at the
- // device in non-tracking mode you are probably waiting for your signal to recover.
- trackingState == Keys.STATE_TRACKING_ACTIVE &&
+ // device in mapview state you are probably waiting for your signal to recover.
// We only go to dead from full power because in the sleep state, the wakelock is
// turned off and the device may go into doze. During doze, the device stops
// updating the location listeners anyway, so there is no benefit in going to dead.
// When the user interacts with the device and it leaves doze, it's better to come
// from sleep state than dead state.
- location_interval == Keys.LOCATION_INTERVAL_FULL_POWER &&
+ tracking_state == Keys.STATE_FULL_RECORDING &&
(now - listeners_enabled_at) > TIME_UNTIL_DEAD &&
(now - currentBestLocation.time) > TIME_UNTIL_DEAD &&
(now - last_significant_motion) > TIME_UNTIL_DEAD
)
{
- reset_location_listeners(interval=Keys.LOCATION_INTERVAL_DEAD)
- gave_up_at = now
+ state_dead()
}
}
}
diff --git a/app/src/main/java/net/voussoir/trkpt/TrackingToggleTileService.kt b/app/src/main/java/net/voussoir/trkpt/TrackingToggleTileService.kt
deleted file mode 100644
index 07f4d0e..0000000
--- a/app/src/main/java/net/voussoir/trkpt/TrackingToggleTileService.kt
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * TrackingToggleTileService.kt
- * Implements the TrackingToggleTileService service
- * A TrackingToggleTileService toggles the recording state from a quick settings tile
- *
- * This file is part of
- * TRACKBOOK - Movement Recorder for Android
- *
- * Copyright (c) 2016-22 - Y20K.org
- * Licensed under the MIT-License
- * http://opensource.org/licenses/MIT
- *
- * Trackbook uses osmdroid - OpenStreetMap-Tools for Android
- * https://github.com/osmdroid/osmdroid
- */
-
-/*
- * Modified by voussoir for trkpt, forked from Trackbook.
- */
-
-package net.voussoir.trkpt
-
-import android.content.Intent
-import android.content.SharedPreferences
-import android.graphics.drawable.Icon
-import android.os.Build
-import android.service.quicksettings.Tile
-import android.service.quicksettings.TileService
-import net.voussoir.trkpt.helpers.PreferencesHelper
-
-/*
- * TrackingToggleTileService class
- */
-class TrackingToggleTileService: TileService()
-{
- /* Main class variables */
- private var bound: Boolean = false
- private var trackingState: Int = Keys.STATE_TRACKING_STOPPED
- private lateinit var trackerService: TrackerService
-
- /* Overrides onTileAdded from TileService */
- override fun onTileAdded() {
- super.onTileAdded()
- // get saved tracking state
- trackingState = PreferencesHelper.loadTrackingState()
- // set up tile
- updateTile()
- }
-
- /* Overrides onTileRemoved from TileService */
- override fun onTileRemoved() {
- super.onTileRemoved()
- }
-
- /* Overrides onStartListening from TileService (tile becomes visible) */
- override fun onStartListening() {
- super.onStartListening()
- // get saved tracking state
- trackingState = PreferencesHelper.loadTrackingState()
- // set up tile
- updateTile()
- // register listener for changes in shared preferences
- PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
- }
-
- /* Overrides onClick from TileService */
- override fun onClick() {
- super.onClick()
- when (trackingState) {
- Keys.STATE_TRACKING_ACTIVE -> stopTracking()
- else -> startTracking()
- }
- }
-
- /* Overrides onStopListening from TileService (tile no longer visible) */
- override fun onStopListening() {
- super.onStopListening()
- // unregister listener for changes in shared preferences
- PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
- }
-
- /* Overrides onDestroy from Service */
- override fun onDestroy() {
- super.onDestroy()
- }
-
- /* Update quick settings tile */
- private fun updateTile() {
- val tile: Tile = qsTile
- tile.icon = Icon.createWithResource(this, R.drawable.ic_notification_icon_small_24dp)
- when (trackingState) {
- Keys.STATE_TRACKING_ACTIVE -> {
- tile.label = getString(R.string.quick_settings_tile_title_pause)
- tile.contentDescription = getString(R.string.descr_quick_settings_tile_title_pause)
- tile.state = Tile.STATE_ACTIVE
- }
- else -> {
- tile.label = getString(R.string.quick_settings_tile_title_start)
- tile.contentDescription = getString(R.string.descr_quick_settings_tile_title_start)
- tile.state = Tile.STATE_INACTIVE
- }
- }
- tile.updateTile()
- }
-
- /* Start tracking */
- private fun startTracking() {
- val intent = Intent(application, TrackerService::class.java)
- intent.action = Keys.ACTION_START
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- // ... start service in foreground to prevent it being killed on Oreo
- application.startForegroundService(intent)
- } else {
- application.startService(intent)
- }
- }
-
- /* Stop tracking */
- private fun stopTracking() {
- val intent = Intent(application, TrackerService::class.java)
- intent.action = Keys.ACTION_STOP
- application.startService(intent)
- }
-
- /*
- * Defines the listener for changes in shared preferences
- */
- private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
- when (key) {
- Keys.PREF_TRACKING_STATE -> {
- trackingState = PreferencesHelper.loadTrackingState()
- updateTile()
- }
- }
- }
- /*
- * End of declaration
- */
-
-
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/net/voussoir/trkpt/helpers/PreferencesHelper.kt b/app/src/main/java/net/voussoir/trkpt/helpers/PreferencesHelper.kt
index ee2626c..86f6827 100644
--- a/app/src/main/java/net/voussoir/trkpt/helpers/PreferencesHelper.kt
+++ b/app/src/main/java/net/voussoir/trkpt/helpers/PreferencesHelper.kt
@@ -75,7 +75,7 @@ object PreferencesHelper
}
fun loadTrackingState(): Int {
- return sharedPreferences.getInt(Keys.PREF_TRACKING_STATE, Keys.STATE_TRACKING_STOPPED)
+ return sharedPreferences.getInt(Keys.PREF_TRACKING_STATE, Keys.STATE_STOP)
}
fun saveTrackingState(trackingState: Int) {
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 1e112c4..c7f766d 100644
--- a/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt
+++ b/app/src/main/java/net/voussoir/trkpt/tracklist/TracklistAdapter.kt
@@ -30,6 +30,7 @@ import net.voussoir.trkpt.Keys
import net.voussoir.trkpt.R
import net.voussoir.trkpt.Database
import net.voussoir.trkpt.Track
+import net.voussoir.trkpt.helpers.PreferencesHelper
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
@@ -53,9 +54,10 @@ class TracklistAdapter(val fragment: Fragment, val database: Database) : Recycle
{
return
}
+ val max_accuracy = PreferencesHelper.load_max_accuracy()
val cursor: Cursor = database.connection.rawQuery(
- "SELECT distinct(date(time/1000, 'unixepoch', 'localtime')) as thedate, device_id FROM trkpt ORDER BY thedate DESC",
- arrayOf()
+ "SELECT distinct(date(time/1000, 'unixepoch', 'localtime')) as thedate, device_id FROM trkpt WHERE accuracy <= ? ORDER BY thedate DESC",
+ arrayOf(max_accuracy.toString())
)
try
{
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f310bb2..d64dc73 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -91,7 +91,7 @@
Advanced
Delete all recordings in \"Tracks\" that are not starred.
Delete Non-Starred Recordings
- General
+ Settings
Maintenance
Use GPS location
GPS location enabled.