From eec0caf59d6c33d1f37c7c63b415251a79a4d457 Mon Sep 17 00:00:00 2001 From: Ethan Dalool Date: Fri, 31 Mar 2023 22:32:29 -0700 Subject: [PATCH] Kill GPS if it is struggling for several minutes, wait for motion. Still testing. --- .../java/net/voussoir/trkpt/MapFragment.kt | 39 +++--- .../java/net/voussoir/trkpt/TrackerService.kt | 124 +++++++++++------- app/src/main/res/drawable/ic_skull_24dp.xml | 13 ++ 3 files changed, 106 insertions(+), 70 deletions(-) create mode 100644 app/src/main/res/drawable/ic_skull_24dp.xml diff --git a/app/src/main/java/net/voussoir/trkpt/MapFragment.kt b/app/src/main/java/net/voussoir/trkpt/MapFragment.kt index 9c350e6..7bdefb6 100644 --- a/app/src/main/java/net/voussoir/trkpt/MapFragment.kt +++ b/app/src/main/java/net/voussoir/trkpt/MapFragment.kt @@ -52,7 +52,6 @@ import org.osmdroid.views.overlay.TilesOverlay import org.osmdroid.views.overlay.compass.CompassOverlay import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider import net.voussoir.trkpt.helpers.* -import net.voussoir.trkpt.R class MapFragment : Fragment() { @@ -205,7 +204,6 @@ class MapFragment : Fragment() false } - update_main_button() mainButton.setOnClickListener { val tracker = trackerService if (tracker == null) @@ -220,7 +218,7 @@ class MapFragment : Fragment() { startTracking() } - handler.postDelayed(location_update_redraw, 0) + handler.postDelayed(redraw_runnable, 0) } currentLocationButton.setOnClickListener { val tracker = trackerService @@ -238,6 +236,7 @@ class MapFragment : Fragment() } requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + handler.post(redraw_runnable) return rootView } @@ -253,6 +252,7 @@ class MapFragment : Fragment() } // bind to TrackerService activity?.bindService(Intent(activity, TrackerService::class.java), connection, Context.BIND_AUTO_CREATE) + handler.post(redraw_runnable) } /* Overrides onResume from Fragment */ @@ -260,7 +260,7 @@ class MapFragment : Fragment() { Log.i("VOUSSOIR", "MapFragment.onResume") super.onResume() - redraw() + handler.post(redraw_runnable) requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) // if (bound) { // trackerService.addGpsLocationListener() @@ -281,30 +281,26 @@ class MapFragment : Fragment() return } saveBestLocationState(tracker.currentBestLocation) - tracker.mapfragment = null if (bound && tracker.trackingState != Keys.STATE_TRACKING_ACTIVE) { tracker.removeGpsLocationListener() tracker.removeNetworkLocationListener() tracker.trackbook.database.commit() } + handler.removeCallbacks(redraw_runnable) } /* Overrides onStop from Fragment */ override fun onStop() { super.onStop() - val tracker = trackerService - if (tracker != null) - { - tracker.mapfragment = null - } // unbind from TrackerService if (bound) { activity?.unbindService(connection) handleServiceUnbind() } + handler.removeCallbacks(redraw_runnable) } override fun onDestroyView() @@ -315,17 +311,15 @@ class MapFragment : Fragment() { trackbook.database_changed_listeners.remove(database_changed_listener) } + handler.removeCallbacks(redraw_runnable) } override fun onDestroy() { Log.i("VOUSSOIR", "MapFragment.onDestroy") super.onDestroy() - if (trackerService != null) - { - trackerService!!.mapfragment = null - } requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + handler.removeCallbacks(redraw_runnable) } private val requestLocationPermissionLauncher = registerForActivityResult(RequestPermission()) { isGranted: Boolean -> @@ -372,10 +366,6 @@ class MapFragment : Fragment() bound = false // unregister listener for changes in shared preferences PreferencesHelper.unregisterPreferenceChangeListener(sharedPreferenceChangeListener) - if (trackerService != null) - { - trackerService!!.mapfragment = null - } } private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> @@ -618,7 +608,6 @@ class MapFragment : Fragment() } bound = true trackerService = serviceref - trackerService!!.mapfragment = thismapfragment // get state of tracking and update button if necessary redraw() // register listener for changes in shared preferences @@ -655,7 +644,8 @@ class MapFragment : Fragment() map_current_time.text = iso8601_local_noms(tracker.currentBestLocation.time) - if (tracker.arrived_at_home == 0L) + + 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) { @@ -669,19 +659,20 @@ class MapFragment : Fragment() power_level_indicator.tooltipText = "GPS sleeping until movement" } } - else + else if (tracker.location_interval == tracker.LOCATION_INTERVAL_GIVE_UP) { - power_level_indicator.setImageResource(R.drawable.ic_homepoint_24dp) + power_level_indicator.setImageResource(R.drawable.ic_skull_24dp) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - power_level_indicator.tooltipText = "You are at home" + power_level_indicator.tooltipText = "GPS is struggling; disabled until movement" } } } - val location_update_redraw: Runnable = object : Runnable + val redraw_runnable: Runnable = object : Runnable { override fun run() { + handler.postDelayed(this, 975) redraw() } } diff --git a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt index 3153b26..c7129a7 100644 --- a/app/src/main/java/net/voussoir/trkpt/TrackerService.kt +++ b/app/src/main/java/net/voussoir/trkpt/TrackerService.kt @@ -40,10 +40,7 @@ import android.location.LocationListener import android.location.LocationManager import android.media.AudioManager import android.media.ToneGenerator -import android.os.Binder -import android.os.Build -import android.os.IBinder -import android.os.Vibrator +import android.os.* import android.util.Log import androidx.annotation.RequiresApi import androidx.appcompat.content.res.AppCompatResources @@ -58,6 +55,7 @@ import java.util.* class TrackerService: Service() { lateinit var trackbook: Trackbook + val handler: Handler = Handler(Looper.getMainLooper()) var trackingState: Int = Keys.STATE_TRACKING_STOPPED var useImperial: Boolean = false @@ -65,11 +63,13 @@ class TrackerService: Service() var device_id: String = random_device_id() var currentBestLocation: Location = getDefaultLocation() var lastCommit: Long = 0 + var listeners_enabled_at: Long = 0 var last_significant_motion: Long = 0 var arrived_at_home: Long = 0 var location_interval: Long = 0 - val LOCATION_INTERVAL_FULLPOWER: 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 private val RECENT_TRKPT_COUNT = 3600 private val DISPLACEMENT_LOCATION_COUNT = 5 lateinit var recent_displacement_locations: Deque @@ -91,8 +91,6 @@ class TrackerService: Service() var gpsLocationListenerRegistered: Boolean = false var networkLocationListenerRegistered: Boolean = false - var mapfragment: MapFragment? = null - private lateinit var sensor_manager: SensorManager private var significant_motion_sensor: Sensor? = null @@ -104,12 +102,6 @@ class TrackerService: Service() return } - if (gpsLocationListenerRegistered) - { - Log.i("VOUSSOIR", "GPS location listener has already been added.") - return - } - gpsProviderActive = isGpsEnabled(locationManager) if (! gpsProviderActive) { @@ -142,12 +134,6 @@ class TrackerService: Service() return } - if (networkLocationListenerRegistered) - { - Log.i("VOUSSOIR", "Network location listener has already been added.") - return - } - networkProviderActive = isNetworkEnabled(locationManager) if (!networkProviderActive) { @@ -202,22 +188,36 @@ class TrackerService: Service() fun reset_location_listeners(interval: Long) { + Log.i("VOUSSOIR", "TrackerService.reset_location_listeners") location_interval = interval - if (gpsLocationListenerRegistered) + var gps_added = false + var network_added = false + if (use_gps_location && interval != LOCATION_INTERVAL_GIVE_UP) + { + addGpsLocationListener(interval) + gps_added = true + } + else if (gpsLocationListenerRegistered) { removeGpsLocationListener() } - if (networkLocationListenerRegistered) + if (use_network_location && interval != LOCATION_INTERVAL_GIVE_UP) + { + addNetworkLocationListener(interval) + network_added = true + } + else if (networkLocationListenerRegistered) { removeNetworkLocationListener() } - if (use_gps_location) + + if (gps_added || network_added) { - addGpsLocationListener(interval) + listeners_enabled_at = System.currentTimeMillis() } - if (use_network_location) + else { - addNetworkLocationListener(interval) + listeners_enabled_at = 0 } } @@ -238,9 +238,6 @@ class TrackerService: Service() currentBestLocation = location - val mf = mapfragment - mf?.handler?.postDelayed(mf.location_update_redraw, 0) - if (trackingState != Keys.STATE_TRACKING_ACTIVE) { return @@ -287,7 +284,7 @@ class TrackerService: Service() } else if ((System.currentTimeMillis() - arrived_at_home) > Keys.ONE_MINUTE_IN_MILLISECONDS) { - Log.i("VOUSSOIR", "Staying at home.") + Log.i("VOUSSOIR", "Staying at home, sleeping.") reset_location_listeners(interval=LOCATION_INTERVAL_SLEEP) } return @@ -297,7 +294,7 @@ class TrackerService: Service() { Log.i("VOUSSOIR", "Leaving home.") arrived_at_home = 0 - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) } if (! isRecentEnough(location)) @@ -452,8 +449,11 @@ class TrackerService: Service() override fun onBind(p0: Intent?): IBinder { Log.i("VOUSSOIR", "TrackerService.onBind") + if (listeners_enabled_at == 0L) + { + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) + } bound = true - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) return binder } @@ -461,8 +461,11 @@ class TrackerService: Service() override fun onRebind(intent: Intent?) { Log.i("VOUSSOIR", "TrackerService.onRebind") + if (listeners_enabled_at == 0L) + { + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) + } bound = true - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) } /* Overrides onUnbind from Service */ @@ -474,8 +477,7 @@ class TrackerService: Service() // stop receiving location updates - if not tracking if (trackingState != Keys.STATE_TRACKING_ACTIVE) { - removeGpsLocationListener() - removeNetworkLocationListener() + reset_location_listeners(LOCATION_INTERVAL_GIVE_UP) } // ensures onRebind is called return true @@ -511,6 +513,8 @@ class TrackerService: Service() trackingState = PreferencesHelper.loadTrackingState() currentBestLocation = getLastKnownLocation(this) PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener) + + handler.post(background_watchdog) } /* Overrides onStartCommand from Service */ @@ -526,15 +530,13 @@ class TrackerService: Service() val triggerEventListener = object : TriggerEventListener() { override fun onTrigger(event: TriggerEvent?) { Log.i("VOUSSOIR", "Significant motion") - // beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150) - vibrator.vibrate(50) last_significant_motion = System.currentTimeMillis() arrived_at_home = 0L - if (location_interval == LOCATION_INTERVAL_SLEEP) + if (location_interval != LOCATION_INTERVAL_FULL_POWER) { - reset_location_listeners(LOCATION_INTERVAL_FULLPOWER) - val mf = mapfragment - mf?.handler?.postDelayed(mf.location_update_redraw, 0) + // beeper.startTone(ToneGenerator.TONE_PROP_ACK, 150) + vibrator.vibrate(100) + reset_location_listeners(LOCATION_INTERVAL_FULL_POWER) } sensor_manager.requestTriggerSensor(this, significant_motion_sensor) } @@ -576,15 +578,15 @@ 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) - removeGpsLocationListener() - removeNetworkLocationListener() + reset_location_listeners(LOCATION_INTERVAL_GIVE_UP) + handler.removeCallbacks(background_watchdog) } fun startTracking() { Log.i("VOUSSOIR", "TrackerService.startTracking") arrived_at_home = 0 - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) trackingState = Keys.STATE_TRACKING_ACTIVE PreferencesHelper.saveTrackingState(trackingState) recent_displacement_locations.clear() @@ -596,7 +598,7 @@ class TrackerService: Service() Log.i("VOUSSOIR", "TrackerService.stopTracking") trackbook.database.commit() arrived_at_home = 0 - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) trackingState = Keys.STATE_TRACKING_STOPPED PreferencesHelper.saveTrackingState(trackingState) recent_displacement_locations.clear() @@ -610,12 +612,12 @@ class TrackerService: Service() Keys.PREF_LOCATION_GPS -> { use_gps_location = PreferencesHelper.load_location_gps() - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) } Keys.PREF_LOCATION_NETWORK -> { use_network_location = PreferencesHelper.load_location_network() - reset_location_listeners(interval=LOCATION_INTERVAL_FULLPOWER) + reset_location_listeners(interval=LOCATION_INTERVAL_FULL_POWER) } Keys.PREF_USE_IMPERIAL_UNITS -> { @@ -631,6 +633,36 @@ class TrackerService: Service() } } } + + val background_watchdog: Runnable = object : Runnable + { + override fun run() + { + Log.i("VOUSSOIR", "TrackerService.background_watchdog") + handler.postDelayed(this, 30 * Keys.ONE_SECOND_IN_MILLISECONDS) + 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 ( + 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 + ) + { + reset_location_listeners(LOCATION_INTERVAL_GIVE_UP) + } + } + } } class TrackerServiceBinder(trackerservice: TrackerService) : Binder() { diff --git a/app/src/main/res/drawable/ic_skull_24dp.xml b/app/src/main/res/drawable/ic_skull_24dp.xml new file mode 100644 index 0000000..ff7c945 --- /dev/null +++ b/app/src/main/res/drawable/ic_skull_24dp.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file