TrackRecordingService: must be stopped via TrackRecordingServiceConnection and handles Preference changes.

This commit is contained in:
Dennis Guse
2023-08-08 23:22:35 +02:00
parent 0a5b46655a
commit 4d5c59be96
10 changed files with 96 additions and 101 deletions
+1
View File
@@ -53,6 +53,7 @@ captures/
.idea/.name
.idea/caches/
.idea/compiler.xml
.idea/androidTestResultsUserPreferences.xml
.idea/copyright/profiles_settings.xml
.idea/dataSources.ids
.idea/datasources.xml
@@ -132,7 +132,7 @@ public class TrackRecordingServiceStateMachineTest {
assertEquals(GpsStatusValue.GPS_ENABLED, service.getGpsStatusObservable().getValue());
// when
service.stopSensorsAndShutdown();
service.stopSensors();
Thread.sleep(1000);
// then
@@ -177,7 +177,7 @@ public class TrackRecordingServiceStateMachineTest {
// then
assertFalse(service.isRecording());
assertEquals(TrackRecordingService.STATUS_DEFAULT, service.getRecordingStatusObservable().getValue());
assertEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertNotEquals(TrackRecordingService.NOT_RECORDING, service.getRecordingDataObservable().getValue());
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue());
@@ -47,7 +47,7 @@ import de.dennisguse.opentracks.util.PermissionRequester;
*
* @author Sandor Dornbush
*/
public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBluetoothConnectionManager.SensorDataObserver {
public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBluetoothConnectionManager.SensorDataObserver, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = BluetoothRemoteSensorManager.class.getSimpleName();
@@ -65,39 +65,6 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl
private final BluetoothConnectionManagerCyclingPower cyclingPower = new BluetoothConnectionManagerCyclingPower(this);
private final BluetoothConnectionRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothConnectionRunningSpeedAndCadence(this);
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
if (!started) return;
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_heart_rate_key, key)) {
String address = PreferencesUtils.getBluetoothHeartRateSensorAddress();
connect(heartRate, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_cadence_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingCadenceSensorAddress();
connect(cyclingCadence, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_speed_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingSpeedSensorAddress();
connect(cyclingSpeed, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_power_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingPowerSensorAddress();
connect(cyclingPower, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_running_speed_and_cadence_key, key)) {
String address = PreferencesUtils.getBluetoothRunningSpeedAndCadenceAddress();
connect(runningSpeedAndCadence, address);
}
};
public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @Nullable SensorManager.SensorDataChangedObserver observer) {
this.context = context;
this.handler = handler;
@@ -109,8 +76,8 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl
public void start(Context context, Handler handler) {
started = true;
//Registering triggers connection startup
PreferencesUtils.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
// Triggers connection startup
onSharedPreferenceChanged(null, null);
}
@Override
@@ -121,7 +88,6 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl
cyclingPower.disconnect();
runningSpeedAndCadence.disconnect();
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
started = false;
}
@@ -175,4 +141,37 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl
public Handler getHandler() {
return handler;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences unused, @Nullable String key) {
if (!started) return;
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_heart_rate_key, key)) {
String address = PreferencesUtils.getBluetoothHeartRateSensorAddress();
connect(heartRate, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_cadence_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingCadenceSensorAddress();
connect(cyclingCadence, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_speed_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingSpeedSensorAddress();
connect(cyclingSpeed, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_power_key, key)) {
String address = PreferencesUtils.getBluetoothCyclingPowerSensorAddress();
connect(cyclingPower, address);
}
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_running_speed_and_cadence_key, key)) {
String address = PreferencesUtils.getBluetoothRunningSpeedAndCadenceAddress();
connect(runningSpeedAndCadence, address);
}
}
}
@@ -1,9 +1,11 @@
package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -12,7 +14,7 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.handlers.GPSManager;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
public class SensorManager {
public class SensorManager implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = SensorManager.class.getSimpleName();
@@ -49,11 +51,12 @@ public class SensorManager {
public void start(Context context, Handler handler) {
gpsManager = new GPSManager(observer); //TODO Pass listener
gpsManager.start(context, handler);
altitudeSumManager = new AltitudeSumManager();
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, listener);
onSharedPreferenceChanged(null, null);
gpsManager.start(context, handler);
altitudeSumManager.start(context, handler);
bluetoothSensorManager.start(context, handler);
}
@@ -114,6 +117,14 @@ public class SensorManager {
this.altitudeSumManager = altitudeSumManager;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
if (gpsManager != null) {
gpsManager.onSharedPreferenceChanged(sharedPreferences, key);
bluetoothSensorManager.onSharedPreferenceChanged(sharedPreferences, key);
}
}
public interface SensorDataChangedObserver {
void onChange(SensorData<?> sensorData);
@@ -58,14 +58,6 @@ class TrackRecordingManager implements SharedPreferences.OnSharedPreferenceChang
contentProviderUtils = new ContentProviderUtils(context);
}
public void start() {
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
}
public void stop() {
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
}
Track.Id startNewTrack() {
TrackPoint segmentStartTrackPoint = trackPointCreator.createSegmentStartManual();
// Create new track
@@ -18,6 +18,7 @@ package de.dennisguse.opentracks.services;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Handler;
@@ -26,6 +27,7 @@ import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
@@ -40,9 +42,10 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.announcement.VoiceAnnouncementManager;
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.SystemUtils;
public class TrackRecordingService extends Service implements TrackPointCreator.Callback {
public class TrackRecordingService extends Service implements TrackPointCreator.Callback, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = TrackRecordingService.class.getSimpleName();
@@ -81,7 +84,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
private MutableLiveData<RecordingData> recordingDataObservable;
// The following variables are set when recording:
private WakeLock wakeLock;
private WakeLock wakeLock; //TODO Move to SensorManager
private Handler handler;
private TrackPointCreator trackPointCreator;
@@ -93,6 +96,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Create");
handler = new Handler(Looper.getMainLooper());
@@ -103,40 +107,39 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
trackPointCreator = new TrackPointCreator(this, this, handler);
trackRecordingManager = new TrackRecordingManager(this, trackPointCreator);
trackRecordingManager.start();
voiceAnnouncementManager = new VoiceAnnouncementManager(this);
notificationManager = new TrackRecordingServiceNotificationManager(this);
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onDestroy() {
trackPointCreator.stop();
Log.d(TAG, "Destroying");
if (isRecording()) {
endCurrentTrack();
}
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
trackPointCreator = null;
handler.removeCallbacksAndMessages(null); //Some tests do not finish the recording completely
handler = null;
trackRecordingManager.stop();
trackRecordingManager = null;
// Reverse order from onCreate
stopForeground(true);
notificationManager.stop();
notificationManager = null;
voiceAnnouncementManager.stop();
voiceAnnouncementManager = null;
// This should be the next to last operation
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
updateRecordingStatus(STATUS_DEFAULT);
recordingStatusObservable = null;
gpsStatusObservable = null;
recordingDataObservable = null;
Log.d(TAG, "Destroyed");
super.onDestroy();
}
@@ -210,34 +213,15 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
updateRecordingStatus(STATUS_DEFAULT);
trackRecordingManager.end();
endRecording();
stopSelf();
}
private void endRecording() {
stopUpdateRecordingData();
recordingDataObservable.postValue(NOT_RECORDING);
voiceAnnouncementManager.stop();
// Update instance variables
trackPointCreator.stop();
stopSensors();
}
public void stopSensorsAndShutdown() {
if (isRecording()) {
return;
}
stopSensors();
stopSelf();
}
void stopSensors() {
if (!isRecording()) return;
trackPointCreator.stop();
stopForeground(true);
notificationManager.cancelNotification();
@@ -258,6 +242,8 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
@Override
public void newGpsStatus(GpsStatusValue gpsStatusValue) {
Log.e(TAG, "newGpsStatus: " + gpsStatusValue.message);
notificationManager.updateContent(getString(gpsStatusValue.message));
gpsStatusObservable.postValue(gpsStatusValue);
}
@@ -291,7 +277,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
}
private void updateRecordingDataWhileRecording() {
if (!recordingStatus.isRecording()) {
if (!isRecording()) {
Log.w(TAG, "Currently not recording; cannot update data.");
return;
}
@@ -323,4 +309,12 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
public boolean isRecording() {
return recordingStatus.isRecording();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
voiceAnnouncementManager.onSharedPreferenceChanged(sharedPreferences, key);
trackRecordingManager.onSharedPreferenceChanged(sharedPreferences, key);
trackPointCreator.onSharedPreferenceChanged(sharedPreferences, key);
notificationManager.onSharedPreferenceChanged(sharedPreferences, key);
}
}
@@ -42,7 +42,6 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
private UnitSystem unitSystem = null;
TrackRecordingServiceNotificationManager(Context context) {
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, context.getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
@@ -65,7 +64,6 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
void stop() {
cancelNotification();
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
}
@VisibleForTesting
@@ -60,7 +60,6 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
public VoiceAnnouncementManager(@NonNull TrackRecordingService trackRecordingService) {
this.trackRecordingService = trackRecordingService;
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
}
public void start(@Nullable TrackStatistics trackStatistics) {
@@ -106,7 +105,6 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
}
public void stop() {
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
if (voiceAnnouncement != null) {
voiceAnnouncement.stop();
voiceAnnouncement = null;
@@ -48,7 +48,8 @@ public class GPSManager implements SensorConnector, LocationListenerCompat, GpsS
this.context = context;
this.handler = handler;
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(null, null);
gpsStatusManager = new GpsStatusManager(context, this, handler);
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
registerLocationListener();
@@ -62,20 +63,15 @@ public class GPSManager implements SensorConnector, LocationListenerCompat, GpsS
@SuppressWarnings({"MissingPermission"})
//TODO upgrade to AGP7.0.0/API31 started complaining about removeUpdates.
public void stop(Context context) {
if (locationManager != null && context != null) {
if (PermissionRequester.GPS.hasPermission(context)) {
LocationManagerCompat.removeUpdates(locationManager, this);
}
locationManager = null;
context = null;
handler = null;
if (locationManager != null) {
LocationManagerCompat.removeUpdates(locationManager, this);
}
locationManager = null;
this.context = null;
handler = null;
if (gpsStatusManager != null) {
gpsStatusManager.stop();
gpsStatusManager = null;
}
PreferencesUtils.unregisterOnSharedPreferenceChangeListener(this);
gpsStatusManager.stop();
gpsStatusManager = null;
}
@Override
@@ -1,6 +1,7 @@
package de.dennisguse.opentracks.services.handlers;
import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Handler;
import android.util.Log;
@@ -23,7 +24,7 @@ import de.dennisguse.opentracks.settings.PreferencesUtils;
/**
* Creates TrackPoints while recording by fusing data from different sensors (e.g., GNSS, barometer, BLE sensors).
*/
public class TrackPointCreator {
public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = TrackPointCreator.class.getSimpleName();
@@ -150,6 +151,11 @@ public class TrackPointCreator {
service.newGpsStatus(gpsStatusValue);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
sensorManager.onSharedPreferenceChanged(sharedPreferences, key);
}
public interface Callback {
/**
* @return Was TrackPoint stored (not discarded)?