From e2b741dd08406b8d39c6bc6e8b5579de400abcab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n?= Date: Fri, 17 Jul 2020 15:48:53 +0200 Subject: [PATCH] Added GPS Status to the service so activities can access to the GPS Status. --- .../opentracks/TrackListActivity.java | 27 ++- .../opentracks/TrackRecordingActivity.java | 13 ++ .../services/BoundServiceListener.java | 10 + .../services/TrackRecordingService.java | 19 ++ .../services/TrackRecordingServiceBinder.java | 5 + .../TrackRecordingServiceInterface.java | 2 + .../services/handlers/GpsStatus.java | 217 ++++++++++++++++++ .../services/handlers/GpsStatusValue.java | 23 ++ .../services/handlers/HandlerServer.java | 7 +- .../services/handlers/LocationHandler.java | 29 ++- src/main/res/values/strings.xml | 2 + 11 files changed, 348 insertions(+), 6 deletions(-) create mode 100644 src/main/java/de/dennisguse/opentracks/services/BoundServiceListener.java create mode 100644 src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatus.java create mode 100644 src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index e5fcce564..27a68970f 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -48,8 +48,10 @@ import androidx.loader.content.Loader; import de.dennisguse.opentracks.content.data.TracksColumns; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; +import de.dennisguse.opentracks.services.BoundServiceListener; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceInterface; +import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.ActivityUtils; import de.dennisguse.opentracks.util.IntentDashboardUtils; @@ -168,8 +170,10 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe private final Runnable bindChangedCallback = new Runnable() { @Override public void run() { + boolean isRecording = PreferencesUtils.isRecording(recordingTrackId); + // After binding changes (e.g., becomes available), update the total time in trackController. - runOnUiThread(() -> trackController.update(PreferencesUtils.isRecording(recordingTrackId), recordingTrackPaused)); + runOnUiThread(() -> trackController.update(isRecording, recordingTrackPaused)); if (!startGps) { return; @@ -184,6 +188,12 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe service.startGps(); startGps = false; } + service.setListener(new BoundServiceListener() { + @Override + public void onGpsStatusChange(GpsStatusValue newStatus) { + updateGpsMenuItem(true, isRecording, newStatus.icon); + } + }); } }; @@ -432,17 +442,28 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe } /** - * Updates the menu items. + * Updates the menu items with not fixed icon for gps option. * * @param isGpsStarted true if gps is started * @param isRecording true if recording */ private void updateMenuItems(boolean isGpsStarted, boolean isRecording) { + updateGpsMenuItem(isGpsStarted, isRecording, R.drawable.ic_gps_not_fixed_24dp); + } + + /** + * Updates the menu items with the icon specified. + * + * @param isGpsStarted true if gps is started + * @param isRecording true if recording + * @param icon the icon drawable value + */ + private void updateGpsMenuItem(boolean isGpsStarted, boolean isRecording, int icon) { if (startGpsMenuItem != null) { startGpsMenuItem.setVisible(!isRecording); if (!isRecording) { startGpsMenuItem.setTitle(isGpsStarted ? R.string.menu_stop_gps : R.string.menu_start_gps); - startGpsMenuItem.setIcon(isGpsStarted ? R.drawable.ic_gps_fixed_24dp : R.drawable.ic_gps_off_24dp); + startGpsMenuItem.setIcon(isGpsStarted ? icon : R.drawable.ic_gps_off_24dp); } } } diff --git a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java index 907cdd268..987f27413 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackRecordingActivity.java @@ -11,6 +11,7 @@ import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; @@ -26,8 +27,10 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.fragments.ChartFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment; +import de.dennisguse.opentracks.services.BoundServiceListener; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceInterface; +import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.settings.SettingsActivity; import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentUtils; @@ -91,6 +94,16 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc trackController.update(true, false); trackController.onResume(true, recordingTrackPaused); } + service.setListener(new BoundServiceListener() { + @Override + public void onGpsStatusChange(GpsStatusValue newStatus) { + // TODO 2020-07-17 Add some visible View in the Layout to inform about this and then delete the Toast message. + // Inform through Toast the bad news: GPS is not fixed. + if (newStatus == GpsStatusValue.GPS_NONE || newStatus == GpsStatusValue.GPS_DISABLED || newStatus == GpsStatusValue.GPS_SIGNAL_LOST) { + Toast.makeText(getApplicationContext(), getString(newStatus.message), Toast.LENGTH_LONG).show(); + } + } + }); } }; diff --git a/src/main/java/de/dennisguse/opentracks/services/BoundServiceListener.java b/src/main/java/de/dennisguse/opentracks/services/BoundServiceListener.java new file mode 100644 index 000000000..6b03f14bf --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/services/BoundServiceListener.java @@ -0,0 +1,10 @@ +package de.dennisguse.opentracks.services; + +import de.dennisguse.opentracks.services.handlers.GpsStatusValue; + +/** + * Interface all activities have to implements to receive information from the service. + */ +public interface BoundServiceListener { + void onGpsStatusChange(GpsStatusValue newStatus); +} diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 4dffac656..4b428dd3b 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -33,6 +33,9 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.core.app.TaskStackBuilder; +import java.util.ArrayList; +import java.util.List; + import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.TrackListActivity; import de.dennisguse.opentracks.TrackRecordingActivity; @@ -43,6 +46,7 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils; import de.dennisguse.opentracks.content.provider.CustomContentProvider; import de.dennisguse.opentracks.content.provider.TrackPointIterator; import de.dennisguse.opentracks.content.sensor.SensorDataSet; +import de.dennisguse.opentracks.services.handlers.GpsStatusValue; import de.dennisguse.opentracks.services.handlers.HandlerServer; import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager; import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory; @@ -120,6 +124,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand private HandlerServer handlerServer; + private List listeners = new ArrayList<>(); + @Override public void onCreate() { super.onCreate(); @@ -153,6 +159,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand @Override public void onDestroy() { handlerServer.stop(this); + handlerServer = null; if (remoteSensorManager != null) { remoteSensorManager.stop(); @@ -581,6 +588,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand lastTrackPoint = trackPoint; } + @Override + public void newGpsStatus(GpsStatusValue gpsStatusValue) { + notificationManager.updateContent(getString(gpsStatusValue.message)); + for (BoundServiceListener listener : listeners) { + listener.onGpsStatusChange(gpsStatusValue); + } + } + + public void addListener(BoundServiceListener listener) { + listeners.add(listener); + } + /** * Inserts a trackPoint if this trackPoint is different than lastValidTrackPoint. * diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java index b6e9ea49d..b5b74ef1a 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceBinder.java @@ -22,6 +22,11 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco this.trackRecordingService = trackRecordingService; } + @Override + public void setListener(BoundServiceListener listener) { + trackRecordingService.addListener(listener); + } + @Override public void startGps() { trackRecordingService.tryStartGps(); diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java index 6fa847e52..cad07cd0e 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceInterface.java @@ -110,4 +110,6 @@ public interface TrackRecordingServiceInterface { */ @VisibleForTesting void newTrackPoint(TrackPoint trackPoint, int recordingGpsAccuracy); + + void setListener(BoundServiceListener listener); } diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatus.java b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatus.java new file mode 100644 index 000000000..b096d4cde --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatus.java @@ -0,0 +1,217 @@ +package de.dennisguse.opentracks.services.handlers; + +import android.content.Context; +import android.location.Location; +import android.location.LocationManager; +import android.os.Handler; +import android.util.Log; + +import de.dennisguse.opentracks.util.PreferencesUtils; +import de.dennisguse.opentracks.util.UnitConversions; + +/** + * This class handle GPS status according to received locations and some thresholds. + */ +// TODO 2020-07-17 Delete all Log.d messages before merge with main branch. For now it's useful for debugging. +class GpsStatus { + + private static final String TAG = GpsStatus.class.getSimpleName(); + + // The quantity of milliseconds that GpsStatus waits from minimal interval to consider GPS lost. + private static final int SIGNAL_LOST_THRESHOLD = 10000; + + // Threshold for accuracy. + private double signalBadThreshold; + // Threshold for time without points. + private int signalLostThreshold; + + private GpsStatusValue gpsStatus = GpsStatusValue.GPS_NONE; + private GpsStatusListener client; + private Context context; + private Location lastLocation = null; + private Location lastValidLocation = null; + + private class GpsStatusRunner implements Runnable { + private boolean stopped = false; + + @Override + public void run() { + if (gpsStatus != null && !stopped) { + onLocationChanged(null); + gpsStatusHandler.postDelayed(gpsStatusRunner, getIntervalThreshold()); + } + } + + public void stop() { + stopped = true; + } + } + + private Handler gpsStatusHandler = null; + private GpsStatusRunner gpsStatusRunner = null; + + /** + * @param context The context object. + * @param client The client. + * @param minRecordingInterval Value of min recording interval preference. + */ + public GpsStatus(Context context, GpsStatusListener client, int minRecordingInterval) { + this.client = client; + this.context = context; + signalBadThreshold = PreferencesUtils.getRecordingDistanceInterval(context); + signalLostThreshold = minRecordingInterval > 0 ? minRecordingInterval * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD; + gpsStatusHandler = new Handler(); + } + + /** + * The client that uses GpsStatus has to call this method to stop the Runnable if needed. + */ + public void stop() { + if (gpsStatusRunner != null) { + gpsStatusRunner.stop(); + gpsStatusRunner = null; + } + } + + /** + * Method to change the bad threshold from outside. + * + * @param value New preference value to signalBadThreshold. + */ + public void onRecordingDistanceChanged(int value) { + signalBadThreshold = value; + } + + /** + * Method to change the lost threshold from outside. + * + * @param value Minimal recording interval preference value in seconds or an special value: -1, -2, 0. + */ + public void onMinRecordingIntervalChanged(int value) { + signalLostThreshold = value > 0 ? value * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD; + } + + /** + * This method must be called from the client every time a new location is received. + * Receive new location and calculate the new status if needed. + * It look for GPS changes in lastLocation if it's not null. If it's null then look for in lastValidLocation if any. + */ + public void onLocationChanged(final Location location) { + if (lastLocation != null) { + checkStatusFromLastLocation(); + } else if (lastValidLocation != null) { + checkStatusFromLastValidLocation(); + } + + lastLocation = location; + if (location != null) { + lastValidLocation = location; + } + } + + /** + * Checks if lastLocation has new GPS status looking up time and accuracy. + * It depends of signalLostThreshold and signalBadThreshold. + * If there is any change then it does the change. + * Also, it'll run the runnable if signal is bad or stop it if the signal is lost. + */ + private void checkStatusFromLastLocation() { + if (System.currentTimeMillis() - lastLocation.getTime() > signalLostThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) { + // So much time without receiving signal -> signal lost. + Log.d(TAG, "Signal LOST. signalLostThreshold: " + signalLostThreshold + " - System.currentTimeMillis() - lastLocation.getTime() > " + (System.currentTimeMillis() - lastLocation.getTime())); + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST; + client.onGpsStatusChanged(oldStatus, gpsStatus); + stopStatusRunner(); + } else if (lastLocation.getAccuracy() > signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_BAD) { + // Too little accuracy -> bad signal. + Log.d(TAG, "Signal BAD. signalBadThreshold: " + signalBadThreshold + " - lastLocation.getAccuracy() = " + lastLocation.getAccuracy()); + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_SIGNAL_BAD; + client.onGpsStatusChanged(oldStatus, gpsStatus); + startStatusRunner(); + } else if (lastLocation.getAccuracy() <= signalBadThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_FIX) { + Log.d(TAG, "Signal FIX. signalBadThreshold: " + signalBadThreshold + " - lastLocation.getAccuracy() = " + lastLocation.getAccuracy()); + // Gps okay. + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_SIGNAL_FIX; + client.onGpsStatusChanged(oldStatus, gpsStatus); + startStatusRunner(); + } + } + + /** + * Checks if lastValidLocation has a new GPS status looking up time. + * It depends on signalLostThreshold. + * If there is any change then it does the change. + */ + private void checkStatusFromLastValidLocation() { + if (System.currentTimeMillis() - lastValidLocation.getTime() > signalLostThreshold) { + // Too much time without locations -> lost signal? (wait signalLostThreshold from last valid location). + Log.d(TAG, "Signal LOST. signalLostThreshold: " + signalLostThreshold + " - System.currentTimeMillis() - lastValidLocation.getTime() > " + signalLostThreshold); + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST; + client.onGpsStatusChanged(oldStatus, gpsStatus); + stopStatusRunner(); + lastValidLocation = null; + } + } + + /** + * This method must be called from the client every time the GPS sensor is enabled. + * Anyway, it checks that GPS is enabled because the client assumes that if it's on then GPS is enabled but user can disable GPS by hand. + */ + public void onGpsEnabled() { + if (gpsStatus != GpsStatusValue.GPS_ENABLED) { + LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + if (locationManager != null && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_ENABLED; + client.onGpsStatusChanged(oldStatus, gpsStatus); + startStatusRunner(); + } else { + onGpsDisabled(); + } + } + } + + /** + * This method must be called from service every time the GPS sensor is disabled. + */ + public void onGpsDisabled() { + if (gpsStatus != GpsStatusValue.GPS_DISABLED) { + GpsStatusValue oldStatus = gpsStatus; + gpsStatus = GpsStatusValue.GPS_DISABLED; + client.onGpsStatusChanged(oldStatus, gpsStatus); + lastLocation = null; + lastValidLocation = null; + stopStatusRunner(); + } + } + + private void startStatusRunner() { + if (gpsStatusRunner == null) { + gpsStatusRunner = new GpsStatusRunner(); + gpsStatusRunner.run(); + } + } + + private void stopStatusRunner() { + if (gpsStatusRunner != null) { + gpsStatusRunner.stop(); + gpsStatusRunner = null; + } + } + + public int getIntervalThreshold() { + return signalLostThreshold; + } + + public GpsStatusValue getGpsStatus() { + return gpsStatus; + } + + public interface GpsStatusListener { + void onGpsStatusChanged(GpsStatusValue prevStatus, GpsStatusValue currentStatus); + } +} diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java new file mode 100644 index 000000000..53777d11f --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/GpsStatusValue.java @@ -0,0 +1,23 @@ +package de.dennisguse.opentracks.services.handlers; + +import de.dennisguse.opentracks.R; + +/** + * For each status value set an icon and id message. + */ +public enum GpsStatusValue { + GPS_NONE(R.drawable.ic_gps_off_24dp, R.string.gps_disabled_msg), + GPS_ENABLED(R.drawable.ic_gps_not_fixed_24dp, R.string.gps_wait_for_signal), + GPS_DISABLED(R.drawable.ic_gps_off_24dp, R.string.gps_disabled_msg), + GPS_SIGNAL_FIX(R.drawable.ic_gps_fixed_24dp, R.string.gps_fixed_and_ready), + GPS_SIGNAL_BAD(R.drawable.ic_gps_fixed_24dp, R.string.gps_wait_for_better_signal), + GPS_SIGNAL_LOST(R.drawable.ic_gps_not_fixed_24dp, R.string.gps_wait_for_signal); + + public final int icon; + public final int message; + + GpsStatusValue(int icon, int message) { + this.icon = icon; + this.message = message; + } +} diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java b/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java index 99ecd5187..f49b17a17 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java @@ -56,15 +56,18 @@ public class HandlerServer { serviceExecutor.execute(() -> service.newTrackPoint(trackPoint, recordingGpsAccuracy)); } + void sendGpsStatus(GpsStatusValue gpsStatusValue) { + service.newGpsStatus(gpsStatusValue); + } + public interface HandlerServerInterface { void newTrackPoint(TrackPoint trackPoint, int gpsAccuracy); + void newGpsStatus(GpsStatusValue gpsStatusValue); } public interface Handler { void onStart(Context context); - void onStop(Context context); - void onSharedPreferenceChanged(Context context, SharedPreferences preferences, String key); } } diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java b/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java index 5c00eb821..a140c1994 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java @@ -17,12 +17,13 @@ import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.TrackPointUtils; import de.dennisguse.opentracks.util.UnitConversions; -class LocationHandler implements HandlerServer.Handler, LocationListener { +class LocationHandler implements HandlerServer.Handler, LocationListener, GpsStatus.GpsStatusListener { private final String TAG = LocationHandler.class.getSimpleName(); private LocationManager locationManager; private final HandlerServer handlerServer; + private GpsStatus gpsStatus; private LocationListenerPolicy locationListenerPolicy; private long currentRecordingInterval; private int recordingGpsAccuracy; @@ -34,6 +35,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener { @Override public void onStart(Context context) { + gpsStatus = new GpsStatus(context, this, PreferencesUtils.getMinRecordingInterval(context)); locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); registerLocationListener(); } @@ -42,6 +44,10 @@ class LocationHandler implements HandlerServer.Handler, LocationListener { public void onStop(Context context) { locationManager = null; unregisterLocationListener(); + if (gpsStatus != null) { + gpsStatus.stop(); + gpsStatus = null; + } } @Override @@ -65,6 +71,16 @@ class LocationHandler implements HandlerServer.Handler, LocationListener { if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) { recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context); } + if (PreferencesUtils.isKey(context, R.string.min_recording_interval_key, key)) { + if (gpsStatus != null) { + gpsStatus.onMinRecordingIntervalChanged(PreferencesUtils.getMinRecordingInterval(context)); + } + } + if (PreferencesUtils.isKey(context, R.string.recording_distance_interval_key, key)) { + if (gpsStatus != null) { + gpsStatus.onRecordingDistanceChanged(PreferencesUtils.getRecordingDistanceInterval(context)); + } + } } /** @@ -134,4 +150,15 @@ class LocationHandler implements HandlerServer.Handler, LocationListener { locationManager.removeUpdates(this); locationManager = null; } + + /** + * Called from {@link GpsStatus} to inform that GPS status has changed from prevStatus to currentStatus. + * + * @param prevStatus previous {@link GpsStatusValue}. + * @param currentStatus current {@link GpsStatusValue}. + */ + @Override + public void onGpsStatusChanged(GpsStatusValue prevStatus, GpsStatusValue currentStatus) { + handlerServer.sendGpsStatus(currentStatus); + } } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 561155dbc..853c4bcce 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -251,6 +251,8 @@ limitations under the License. Starting GPS Waiting for a better GPS signal Waiting for GPS signal + GPS disabled + GPS fixed and ready Application Arrow