forked from upstream-mirrors/OpenTracks
Added GPS Status to the service so activities can access to the GPS Status.
This commit is contained in:
@@ -48,8 +48,10 @@ import androidx.loader.content.Loader;
|
|||||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
||||||
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment;
|
||||||
|
import de.dennisguse.opentracks.services.BoundServiceListener;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||||
|
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
@@ -168,8 +170,10 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
boolean isRecording = PreferencesUtils.isRecording(recordingTrackId);
|
||||||
|
|
||||||
// After binding changes (e.g., becomes available), update the total time in trackController.
|
// 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) {
|
if (!startGps) {
|
||||||
return;
|
return;
|
||||||
@@ -184,6 +188,12 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
service.startGps();
|
service.startGps();
|
||||||
startGps = false;
|
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 isGpsStarted true if gps is started
|
||||||
* @param isRecording true if recording
|
* @param isRecording true if recording
|
||||||
*/
|
*/
|
||||||
private void updateMenuItems(boolean isGpsStarted, boolean isRecording) {
|
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) {
|
if (startGpsMenuItem != null) {
|
||||||
startGpsMenuItem.setVisible(!isRecording);
|
startGpsMenuItem.setVisible(!isRecording);
|
||||||
if (!isRecording) {
|
if (!isRecording) {
|
||||||
startGpsMenuItem.setTitle(isGpsStarted ? R.string.menu_stop_gps : R.string.menu_start_gps);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.view.MenuItem;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
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.ChartFragment;
|
||||||
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
|
||||||
import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
|
import de.dennisguse.opentracks.fragments.StatisticsRecordingFragment;
|
||||||
|
import de.dennisguse.opentracks.services.BoundServiceListener;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||||
|
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
import de.dennisguse.opentracks.util.IntentDashboardUtils;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
@@ -91,6 +94,16 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
trackController.update(true, false);
|
trackController.update(true, false);
|
||||||
trackController.onResume(true, recordingTrackPaused);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -33,6 +33,9 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.app.TaskStackBuilder;
|
import androidx.core.app.TaskStackBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.TrackListActivity;
|
import de.dennisguse.opentracks.TrackListActivity;
|
||||||
import de.dennisguse.opentracks.TrackRecordingActivity;
|
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.CustomContentProvider;
|
||||||
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
||||||
import de.dennisguse.opentracks.content.sensor.SensorDataSet;
|
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.handlers.HandlerServer;
|
||||||
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
|
||||||
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
|
import de.dennisguse.opentracks.services.tasks.AnnouncementPeriodicTaskFactory;
|
||||||
@@ -120,6 +124,8 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
|
|
||||||
private HandlerServer handlerServer;
|
private HandlerServer handlerServer;
|
||||||
|
|
||||||
|
private List<BoundServiceListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
@@ -153,6 +159,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
handlerServer.stop(this);
|
handlerServer.stop(this);
|
||||||
|
handlerServer = null;
|
||||||
|
|
||||||
if (remoteSensorManager != null) {
|
if (remoteSensorManager != null) {
|
||||||
remoteSensorManager.stop();
|
remoteSensorManager.stop();
|
||||||
@@ -581,6 +588,18 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
|||||||
lastTrackPoint = trackPoint;
|
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.
|
* Inserts a trackPoint if this trackPoint is different than lastValidTrackPoint.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
|
|||||||
this.trackRecordingService = trackRecordingService;
|
this.trackRecordingService = trackRecordingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setListener(BoundServiceListener listener) {
|
||||||
|
trackRecordingService.addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startGps() {
|
public void startGps() {
|
||||||
trackRecordingService.tryStartGps();
|
trackRecordingService.tryStartGps();
|
||||||
|
|||||||
@@ -110,4 +110,6 @@ public interface TrackRecordingServiceInterface {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void newTrackPoint(TrackPoint trackPoint, int recordingGpsAccuracy);
|
void newTrackPoint(TrackPoint trackPoint, int recordingGpsAccuracy);
|
||||||
|
|
||||||
|
void setListener(BoundServiceListener listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,15 +56,18 @@ public class HandlerServer {
|
|||||||
serviceExecutor.execute(() -> service.newTrackPoint(trackPoint, recordingGpsAccuracy));
|
serviceExecutor.execute(() -> service.newTrackPoint(trackPoint, recordingGpsAccuracy));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendGpsStatus(GpsStatusValue gpsStatusValue) {
|
||||||
|
service.newGpsStatus(gpsStatusValue);
|
||||||
|
}
|
||||||
|
|
||||||
public interface HandlerServerInterface {
|
public interface HandlerServerInterface {
|
||||||
void newTrackPoint(TrackPoint trackPoint, int gpsAccuracy);
|
void newTrackPoint(TrackPoint trackPoint, int gpsAccuracy);
|
||||||
|
void newGpsStatus(GpsStatusValue gpsStatusValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Handler {
|
public interface Handler {
|
||||||
void onStart(Context context);
|
void onStart(Context context);
|
||||||
|
|
||||||
void onStop(Context context);
|
void onStop(Context context);
|
||||||
|
|
||||||
void onSharedPreferenceChanged(Context context, SharedPreferences preferences, String key);
|
void onSharedPreferenceChanged(Context context, SharedPreferences preferences, String key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,13 @@ import de.dennisguse.opentracks.util.PreferencesUtils;
|
|||||||
import de.dennisguse.opentracks.util.TrackPointUtils;
|
import de.dennisguse.opentracks.util.TrackPointUtils;
|
||||||
import de.dennisguse.opentracks.util.UnitConversions;
|
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 final String TAG = LocationHandler.class.getSimpleName();
|
||||||
|
|
||||||
private LocationManager locationManager;
|
private LocationManager locationManager;
|
||||||
private final HandlerServer handlerServer;
|
private final HandlerServer handlerServer;
|
||||||
|
private GpsStatus gpsStatus;
|
||||||
private LocationListenerPolicy locationListenerPolicy;
|
private LocationListenerPolicy locationListenerPolicy;
|
||||||
private long currentRecordingInterval;
|
private long currentRecordingInterval;
|
||||||
private int recordingGpsAccuracy;
|
private int recordingGpsAccuracy;
|
||||||
@@ -34,6 +35,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart(Context context) {
|
public void onStart(Context context) {
|
||||||
|
gpsStatus = new GpsStatus(context, this, PreferencesUtils.getMinRecordingInterval(context));
|
||||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||||
registerLocationListener();
|
registerLocationListener();
|
||||||
}
|
}
|
||||||
@@ -42,6 +44,10 @@ class LocationHandler implements HandlerServer.Handler, LocationListener {
|
|||||||
public void onStop(Context context) {
|
public void onStop(Context context) {
|
||||||
locationManager = null;
|
locationManager = null;
|
||||||
unregisterLocationListener();
|
unregisterLocationListener();
|
||||||
|
if (gpsStatus != null) {
|
||||||
|
gpsStatus.stop();
|
||||||
|
gpsStatus = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,6 +71,16 @@ class LocationHandler implements HandlerServer.Handler, LocationListener {
|
|||||||
if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) {
|
if (PreferencesUtils.isKey(context, R.string.recording_gps_accuracy_key, key)) {
|
||||||
recordingGpsAccuracy = PreferencesUtils.getRecordingGPSAccuracy(context);
|
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.removeUpdates(this);
|
||||||
locationManager = null;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,8 @@ limitations under the License.
|
|||||||
<string name="gps_starting">Starting GPS</string>
|
<string name="gps_starting">Starting GPS</string>
|
||||||
<string name="gps_wait_for_better_signal">Waiting for a better GPS signal</string>
|
<string name="gps_wait_for_better_signal">Waiting for a better GPS signal</string>
|
||||||
<string name="gps_wait_for_signal">Waiting for GPS signal</string>
|
<string name="gps_wait_for_signal">Waiting for GPS signal</string>
|
||||||
|
<string name="gps_disabled_msg">GPS disabled</string>
|
||||||
|
<string name="gps_fixed_and_ready">GPS fixed and ready</string>
|
||||||
<!-- Image -->
|
<!-- Image -->
|
||||||
<string name="image_application">Application</string>
|
<string name="image_application">Application</string>
|
||||||
<string name="image_arrow">Arrow</string>
|
<string name="image_arrow">Arrow</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user