Also watch step counter movement, notification icon by status.

master
voussoir 2023-04-01 13:56:27 -07:00
parent 59389accc5
commit 6ad4c2dbe5
7 changed files with 178 additions and 154 deletions

View File

@ -5,6 +5,7 @@
<!-- USE GPS AND NETWORK - EXCLUDE NON-GPS DEVICES -->
<uses-feature android:name="android.hardware.location.gps" android:required="true" />
<uses-feature android:name="android.hardware.location.network" />
<uses-feature android:name="android.hardware.sensor.stepcounter" />
<!-- NORMAL PERMISSIONS, automatically granted -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
@ -15,6 +16,7 @@
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<!-- DANGEROUS PERMISSIONS, must request -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

View File

@ -26,6 +26,11 @@ object Keys {
// application name
const val APPLICATION_NAME: String = "trkpt"
// axioms
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
// version numbers
const val CURRENT_TRACK_FORMAT_VERSION: Int = 4
const val DATABASE_VERSION: Int = 1
@ -63,6 +68,9 @@ object Keys {
// states
const val STATE_TRACKING_STOPPED: Int = 0
const val STATE_TRACKING_ACTIVE: Int = 1
const val LOCATION_INTERVAL_FULL_POWER: Long = 0
const val LOCATION_INTERVAL_SLEEP: Long = ONE_MINUTE_IN_MILLISECONDS
const val LOCATION_INTERVAL_GIVE_UP: Long = -1
const val STATE_THEME_FOLLOW_SYSTEM: String = "stateFollowSystem"
const val STATE_THEME_LIGHT_MODE: String = "stateLightMode"
const val STATE_THEME_DARK_MODE: String = "stateDarkMode"
@ -85,9 +93,6 @@ object Keys {
// default values
val DEFAULT_DATE: Date = Date(0L)
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 SAVE_TEMP_TRACK_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS

View File

@ -107,6 +107,7 @@ class MainActivity: AppCompatActivity()
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACTIVITY_RECOGNITION,
)
val permissions_needed = ArrayList<String>()
for (permission in permissions_wanted)

View File

@ -71,7 +71,6 @@ class MapFragment : Fragment()
lateinit var zoom_out_button: FloatingActionButton
lateinit var currentLocationButton: FloatingActionButton
lateinit var map_current_time: TextView
lateinit var power_level_indicator: ImageButton
private var current_track_overlay: Polyline? = null
private var current_position_overlays = ArrayList<Overlay>()
private var homepoints_overlays = ArrayList<Overlay>()
@ -113,7 +112,6 @@ class MapFragment : Fragment()
zoom_in_button = rootView.findViewById(R.id.zoom_in_button)
zoom_out_button = rootView.findViewById(R.id.zoom_out_button)
map_current_time = rootView.findViewById(R.id.map_current_time)
power_level_indicator = rootView.findViewById(R.id.power_level_indicator)
mainButton = rootView.findViewById(R.id.main_button)
locationErrorBar = Snackbar.make(mapView, String(), Snackbar.LENGTH_INDEFINITE)
@ -390,38 +388,74 @@ class MapFragment : Fragment()
}
/* Mark current position on map */
fun create_current_position_overlays(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
fun create_current_position_overlays()
{
clear_current_position_overlays()
val locationIsOld: Boolean = !(isRecentEnough(location))
val tracker = trackerService
if (tracker == null)
{
return
}
val locationIsOld: Boolean = !(isRecentEnough(tracker.currentBestLocation))
val newMarker: Drawable
val fillcolor: Int
if (locationIsOld)
val description: String
if (tracker.listeners_enabled_at == 0L)
{
fillcolor = Color.argb(64, 0, 0, 0)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_skull_24dp)!!
description = "No location listeners are enabled"
}
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE && tracker.location_interval == Keys.LOCATION_INTERVAL_GIVE_UP)
{
fillcolor = Color.argb(64, 0, 0, 0)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_skull_24dp)!!
description = "GPS is struggling; disabled until movement"
}
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE && tracker.location_interval == Keys.LOCATION_INTERVAL_SLEEP)
{
fillcolor = Color.argb(64, 220, 61, 51)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_sleep_24dp)!!
description = "GPS sleeping until movement"
}
else if (locationIsOld)
{
fillcolor = Color.argb(64, 0, 0, 0)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_black_24dp)!!
description = "GPS tracking at full power"
}
else if (trackingState == Keys.STATE_TRACKING_ACTIVE)
else if (tracker.trackingState == Keys.STATE_TRACKING_ACTIVE)
{
fillcolor = Color.argb(64, 220, 61, 51)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_red_24dp)!!
description = "GPS tracking at full power"
}
else
{
fillcolor = Color.argb(64, 60, 152, 219)
newMarker = ContextCompat.getDrawable(requireContext(), R.drawable.ic_marker_location_blue_24dp)!!
description = "GPS tracking at full power"
}
val current_location_radius = Polygon()
current_location_radius.points = Polygon.pointsAsCircle(GeoPoint(location.latitude, location.longitude), location.accuracy.toDouble())
current_location_radius.points = Polygon.pointsAsCircle(
GeoPoint(tracker.currentBestLocation.latitude, tracker.currentBestLocation.longitude),
tracker.currentBestLocation.accuracy.toDouble()
)
current_location_radius.fillPaint.color = fillcolor
current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0)
current_position_overlays.add(current_location_radius)
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
val overlayItem: OverlayItem = createOverlayItem(requireContext(), location.latitude, location.longitude, location.accuracy, location.provider.toString(), location.time)
val overlayItem: OverlayItem = createOverlayItem(
tracker.currentBestLocation.latitude,
tracker.currentBestLocation.longitude,
title="Current location",
description=description,
)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
current_position_overlays.add(createOverlay(requireContext(), overlayItems))
@ -478,12 +512,10 @@ class MapFragment : Fragment()
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
val overlayItem: OverlayItem = createOverlayItem(
context,
homepoint.location.latitude,
homepoint.location.longitude,
homepoint.location.accuracy,
homepoint.location.provider.toString(),
homepoint.location.time
title=homepoint.name,
description="Radius ${homepoint.radius}"
)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
@ -615,7 +647,7 @@ class MapFragment : Fragment()
{
return
}
create_current_position_overlays(tracker.currentBestLocation, tracker.trackingState)
create_current_position_overlays()
if (current_track_overlay == null)
{
create_track_overlay()
@ -629,28 +661,7 @@ class MapFragment : Fragment()
map_current_time.text = iso8601_local_noms(tracker.currentBestLocation.time)
if (tracker.location_interval == tracker.LOCATION_INTERVAL_FULL_POWER)
{
power_level_indicator.setImageResource(R.drawable.ic_satellite_24dp)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
power_level_indicator.tooltipText = "GPS tracking at full power"
}
}
else if (tracker.location_interval == tracker.LOCATION_INTERVAL_SLEEP)
{
power_level_indicator.setImageResource(R.drawable.ic_sleep_24dp)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
power_level_indicator.tooltipText = "GPS sleeping until movement"
}
}
else if (tracker.location_interval == tracker.LOCATION_INTERVAL_GIVE_UP)
{
power_level_indicator.setImageResource(R.drawable.ic_skull_24dp)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
power_level_indicator.tooltipText = "GPS is struggling; disabled until movement"
}
}
mapView.invalidate()
}
val redraw_runnable: Runnable = object : Runnable

View File

@ -31,10 +31,7 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.SensorManager
import android.hardware.TriggerEvent
import android.hardware.TriggerEventListener
import android.hardware.*
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
@ -68,9 +65,9 @@ class TrackerService: Service()
var last_significant_motion: Long = 0
var arrived_at_home: Long = 0
var location_interval: Long = 0
val LOCATION_INTERVAL_FULL_POWER: Long = 0
val LOCATION_INTERVAL_SLEEP: Long = Keys.ONE_MINUTE_IN_MILLISECONDS
val LOCATION_INTERVAL_GIVE_UP: Long = -1
val TIME_UNTIL_SLEEP: Long = 2 * Keys.ONE_MINUTE_IN_MILLISECONDS
val TIME_UNTIL_GIVE_UP: Long = 3 * Keys.ONE_MINUTE_IN_MILLISECONDS
val WATCHDOG_INTERVAL: Long = 30 * Keys.ONE_SECOND_IN_MILLISECONDS
private val RECENT_TRKPT_COUNT = 3600
private val DISPLACEMENT_LOCATION_COUNT = 5
lateinit var recent_displacement_locations: Deque<Location>
@ -94,27 +91,23 @@ class TrackerService: Service()
private lateinit var sensor_manager: SensorManager
private var significant_motion_sensor: Sensor? = null
private var step_counter_sensor: Sensor? = null
var has_motion_sensor: Boolean = false
private fun addGpsLocationListener(interval: Long)
private fun addGpsLocationListener(interval: Long): Boolean
{
if (! use_gps_location)
{
Log.i("VOUSSOIR", "Skipping GPS listener.")
return
}
gpsProviderActive = isGpsEnabled(locationManager)
if (! gpsProviderActive)
{
Log.w("VOUSSOIR", "Device GPS is not enabled.")
return
return false
}
val has_permission: Boolean = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (! has_permission)
{
Log.w("VOUSSOIR", "Location permission is not granted.")
return
return false
}
locationManager.requestLocationUpdates(
@ -125,28 +118,23 @@ class TrackerService: Service()
)
gpsLocationListenerRegistered = true
Log.i("VOUSSOIR", "Added GPS location listener.")
return true
}
private fun addNetworkLocationListener(interval: Long)
private fun addNetworkLocationListener(interval: Long): Boolean
{
if (! use_network_location)
{
Log.i("VOUSSOIR", "Skipping Network listener.")
return
}
networkProviderActive = isNetworkEnabled(locationManager)
if (!networkProviderActive)
{
Log.w("VOUSSOIR", "Unable to add Network location listener.")
return
return false
}
val has_permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
if (! has_permission)
{
Log.w("VOUSSOIR", "Unable to add Network location listener. Location permission is not granted.")
return
return false
}
locationManager.requestLocationUpdates(
@ -157,6 +145,7 @@ class TrackerService: Service()
)
networkLocationListenerRegistered = true
Log.i("VOUSSOIR", "Added Network location listener.")
return true
}
fun removeGpsLocationListener()
@ -193,19 +182,17 @@ class TrackerService: Service()
location_interval = interval
var gps_added = false
var network_added = false
if (use_gps_location && interval != LOCATION_INTERVAL_GIVE_UP)
if (use_gps_location && interval != Keys.LOCATION_INTERVAL_GIVE_UP)
{
addGpsLocationListener(interval)
gps_added = true
gps_added = addGpsLocationListener(interval)
}
else if (gpsLocationListenerRegistered)
{
removeGpsLocationListener()
}
if (use_network_location && interval != LOCATION_INTERVAL_GIVE_UP)
if (use_network_location && interval != Keys.LOCATION_INTERVAL_GIVE_UP)
{
addNetworkLocationListener(interval)
network_added = true
network_added = addNetworkLocationListener(interval)
}
else if (networkLocationListenerRegistered)
{
@ -219,7 +206,9 @@ class TrackerService: Service()
else
{
listeners_enabled_at = 0
location_interval = Keys.LOCATION_INTERVAL_GIVE_UP
}
displayNotification()
}
private fun createLocationListener(): LocationListener
@ -277,16 +266,20 @@ class TrackerService: Service()
Log.i("VOUSSOIR", "Arrived at home.")
arrived_at_home = System.currentTimeMillis()
}
else if (location_interval == LOCATION_INTERVAL_SLEEP || significant_motion_sensor == null)
else if (location_interval == Keys.LOCATION_INTERVAL_SLEEP)
{
// If we are already asleep, do not reset the listeners again because
// that immediately fetches a new location.
// If we cannot rely on the motion sensor, then don't sleep!
}
else if (allow_sleep && (System.currentTimeMillis() - arrived_at_home) > Keys.ONE_MINUTE_IN_MILLISECONDS)
else if (
allow_sleep &&
has_motion_sensor &&
(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=LOCATION_INTERVAL_SLEEP)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_SLEEP)
}
return
}
@ -295,7 +288,7 @@ class TrackerService: Service()
{
Log.i("VOUSSOIR", "Leaving home.")
arrived_at_home = 0
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
}
if (! isRecentEnough(location))
@ -365,31 +358,41 @@ class TrackerService: Service()
private fun displayNotification(): Notification
{
val timestamp = iso8601_local_noms(currentBestLocation.time)
notification_builder.setWhen(currentBestLocation.time)
if (shouldCreateNotificationChannel())
{
createNotificationChannel()
}
if (location_interval == LOCATION_INTERVAL_SLEEP)
{
notification_builder.setContentText("${timestamp} (sleeping)")
}
else
{
notification_builder.setContentText(timestamp)
}
notification_builder.setWhen(currentBestLocation.time)
val timestamp = iso8601_local_noms(currentBestLocation.time)
if (trackingState == Keys.STATE_TRACKING_ACTIVE)
{
notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_running))
notification_builder.setLargeIcon(AppCompatResources.getDrawable(this, R.drawable.ic_notification_icon_large_tracking_active_48dp)!!.toBitmap())
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_GIVE_UP)
{
notification_builder.setContentTitle("${timestamp} (deadzone)")
notification_builder.setSmallIcon(R.drawable.ic_skull_24dp)
}
else
{
notification_builder.setContentText(timestamp)
notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_record_inactive_24dp)
}
}
else
{
notification_builder.setContentTitle(this.getString(R.string.notification_title_trackbook_not_running))
notification_builder.setLargeIcon(AppCompatResources.getDrawable(this, R.drawable.ic_notification_icon_large_tracking_stopped_48dp)!!.toBitmap())
notification_builder.setContentTitle("${timestamp} (stopped)")
notification_builder.setSmallIcon(R.drawable.ic_fiber_manual_stop_24dp)
}
val notification = notification_builder.build()
@ -452,8 +455,9 @@ class TrackerService: Service()
Log.i("VOUSSOIR", "TrackerService.onBind")
if (listeners_enabled_at == 0L)
{
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
}
displayNotification()
bound = true
return binder
}
@ -464,8 +468,9 @@ class TrackerService: Service()
Log.i("VOUSSOIR", "TrackerService.onRebind")
if (listeners_enabled_at == 0L)
{
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
}
displayNotification()
bound = true
}
@ -478,7 +483,7 @@ class TrackerService: Service()
// stop receiving location updates - if not tracking
if (trackingState != Keys.STATE_TRACKING_ACTIVE)
{
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_GIVE_UP)
}
// ensures onRebind is called
return true
@ -516,6 +521,52 @@ class TrackerService: Service()
currentBestLocation = getLastKnownLocation(this)
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
has_motion_sensor = false
sensor_manager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
significant_motion_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
if (significant_motion_sensor != null)
{
val significant_motion_listener = object : TriggerEventListener() {
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)
{
vibrator.vibrate(100)
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
}
sensor_manager.requestTriggerSensor(this, significant_motion_sensor)
}
}
Log.i("VOUSSOIR", "Got significant motion sensor.")
sensor_manager.requestTriggerSensor(significant_motion_listener, significant_motion_sensor)
has_motion_sensor = true
}
step_counter_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
if (step_counter_sensor != null)
{
val step_counter_listener = object: SensorEventListener {
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)
{
// beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150)
vibrator.vibrate(100)
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
}
}
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {
}
}
Log.i("VOUSSOIR", "Got step count sensor.")
sensor_manager.registerListener(step_counter_listener, step_counter_sensor, 5_000_000, 5_000_000)
has_motion_sensor = true
}
handler.post(background_watchdog)
}
@ -524,28 +575,6 @@ class TrackerService: Service()
{
Log.i("VOUSSOIR", "TrackerService.onStartCommand")
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
sensor_manager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
significant_motion_sensor = sensor_manager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
if (significant_motion_sensor != null)
{
val triggerEventListener = object : TriggerEventListener() {
override fun onTrigger(event: TriggerEvent?) {
Log.i("VOUSSOIR", "Significant motion")
last_significant_motion = System.currentTimeMillis()
arrived_at_home = 0L
if (location_interval != LOCATION_INTERVAL_FULL_POWER)
{
// beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150)
vibrator.vibrate(100)
reset_location_listeners(LOCATION_INTERVAL_FULL_POWER)
}
sensor_manager.requestTriggerSensor(this, significant_motion_sensor)
}
}
sensor_manager.requestTriggerSensor(triggerEventListener, significant_motion_sensor)
}
// SERVICE RESTART (via START_STICKY)
if (intent == null)
{
@ -580,7 +609,7 @@ class TrackerService: Service()
stopForeground(STOP_FOREGROUND_REMOVE)
notificationManager.cancel(Keys.TRACKER_SERVICE_NOTIFICATION_ID) // this call was not necessary prior to Android 12
PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener)
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_GIVE_UP)
handler.removeCallbacks(background_watchdog)
}
@ -588,7 +617,7 @@ class TrackerService: Service()
{
Log.i("VOUSSOIR", "TrackerService.startTracking")
arrived_at_home = 0
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
trackingState = Keys.STATE_TRACKING_ACTIVE
PreferencesHelper.saveTrackingState(trackingState)
recent_displacement_locations.clear()
@ -600,7 +629,7 @@ class TrackerService: Service()
Log.i("VOUSSOIR", "TrackerService.stopTracking")
trackbook.database.commit()
arrived_at_home = 0
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
trackingState = Keys.STATE_TRACKING_STOPPED
PreferencesHelper.saveTrackingState(trackingState)
recent_displacement_locations.clear()
@ -614,12 +643,12 @@ class TrackerService: Service()
Keys.PREF_LOCATION_GPS ->
{
use_gps_location = PreferencesHelper.load_location_gps()
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
}
Keys.PREF_LOCATION_NETWORK ->
{
use_network_location = PreferencesHelper.load_location_network()
reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(interval=Keys.LOCATION_INTERVAL_FULL_POWER)
}
Keys.PREF_USE_IMPERIAL_UNITS ->
{
@ -632,9 +661,9 @@ class TrackerService: Service()
Keys.PREF_ALLOW_SLEEP ->
{
allow_sleep = PreferencesHelper.loadAllowSleep()
if (! allow_sleep && location_interval != LOCATION_INTERVAL_FULL_POWER)
if (! allow_sleep && location_interval != Keys.LOCATION_INTERVAL_FULL_POWER)
{
reset_location_listeners(LOCATION_INTERVAL_FULL_POWER)
reset_location_listeners(Keys.LOCATION_INTERVAL_FULL_POWER)
}
}
Keys.PREF_DEVICE_ID ->
@ -649,28 +678,19 @@ class TrackerService: Service()
override fun run()
{
Log.i("VOUSSOIR", "TrackerService.background_watchdog")
handler.postDelayed(this, 30 * Keys.ONE_SECOND_IN_MILLISECONDS)
handler.postDelayed(this, WATCHDOG_INTERVAL)
val now = System.currentTimeMillis()
val struggletime: Long
if (location_interval == LOCATION_INTERVAL_FULL_POWER)
{
struggletime = 2 * Keys.ONE_MINUTE_IN_MILLISECONDS
}
else
{
struggletime = 4 * Keys.ONE_MINUTE_IN_MILLISECONDS
}
if (
allow_sleep &&
has_motion_sensor &&
trackingState == Keys.STATE_TRACKING_ACTIVE &&
location_interval != LOCATION_INTERVAL_GIVE_UP &&
significant_motion_sensor != null &&
(now - listeners_enabled_at) > struggletime &&
(now - currentBestLocation.time) > struggletime &&
(now - last_significant_motion) > struggletime
location_interval != Keys.LOCATION_INTERVAL_GIVE_UP &&
(now - listeners_enabled_at) > TIME_UNTIL_GIVE_UP &&
(now - currentBestLocation.time) > TIME_UNTIL_GIVE_UP &&
(now - last_significant_motion) > TIME_UNTIL_GIVE_UP
)
{
reset_location_listeners(LOCATION_INTERVAL_GIVE_UP)
reset_location_listeners(Keys.LOCATION_INTERVAL_GIVE_UP)
}
}
}

View File

@ -34,12 +34,12 @@ fun create_start_end_markers(context: Context, map_view: MapView, startpoint: Tr
{
Log.i("VOUSSOIR", "MapOverlayHelper.create_start_end_markers")
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
val startmarker: OverlayItem = createOverlayItem(context, startpoint.latitude, startpoint.longitude, startpoint.accuracy, startpoint.provider, startpoint.time)
val startmarker: OverlayItem = createOverlayItem(startpoint.latitude, startpoint.longitude, title="Start", iso8601_local_noms(startpoint.time))
startmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_48dp)!!)
overlayItems.add(startmarker)
if (startpoint != endpoint)
{
val endmarker: OverlayItem = createOverlayItem(context, endpoint.latitude, endpoint.longitude, endpoint.accuracy, endpoint.provider, endpoint.time)
val endmarker: OverlayItem = createOverlayItem(endpoint.latitude, endpoint.longitude, title="End", description= iso8601_local_noms(endpoint.time))
endmarker.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_48dp)!!)
overlayItems.add(endmarker)
}
@ -48,10 +48,8 @@ fun create_start_end_markers(context: Context, map_view: MapView, startpoint: Tr
return overlay
}
fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem
fun createOverlayItem(latitude: Double, longitude: Double, title: String, description: String): OverlayItem
{
val title = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"
val description = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
val position = GeoPoint(latitude, longitude)
val item = OverlayItem(title, description, position)
item.markerHotspot = OverlayItem.HotspotPlace.CENTER

View File

@ -97,19 +97,6 @@
app:layout_constraintTop_toTopOf="parent"
/>
<ImageButton
android:id="@+id/power_level_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:src="@drawable/ic_satellite_24dp"
app:backgroundTint="@color/default_transparent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_satellite_24dp"
app:tint="@color/location_button_icon" />
<!-- GROUPS -->
</androidx.constraintlayout.widget.ConstraintLayout>