diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index bf23fa9a8..b5c63aa0a 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -17,9 +17,11 @@ package de.dennisguse.opentracks; import android.app.ActivityOptions; +import android.app.AlertDialog; import android.app.SearchManager; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.database.Cursor; import android.graphics.drawable.AnimatedVectorDrawable; @@ -86,7 +88,7 @@ * @author Leif Hendrik Wilden */ public class TrackListActivity extends AbstractTrackDeleteActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller { - + public static String notifChoice = "speed"; private static final String TAG = TrackListActivity.class.getSimpleName(); private CountDownTimer delayTimer; private int selectedDelayInSeconds = 0; @@ -104,6 +106,14 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT; private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT; + private static final String NOTIFICATION_PREFERENCE_KEY = "notification_preference_key"; + + // Constants for notification options + private static final int SPEED_METRIC_CHOICE = 0; + private static final int HEART_RATE_METRIC_CHOICE = 1; + private static final int DISTANCE_METRIC_CHOICE = 2; + private static final int DEFAULT_CHOICE = SPEED_METRIC_CHOICE; + // Callback when an item is selected in the contextual action mode private final ActivityUtils.ContextualActionModeCallback contextualActionModeCallback = new ActivityUtils.ContextualActionModeCallback() { @@ -267,35 +277,8 @@ public void bindView(View view, Context context, Cursor cursor) { return; } - // Not Recording -> Recording - try { - runOnUiThread(() -> { - for (int i = selectedDelayInSeconds; i >= 0; i--) { - - final int secondsLeft = i; - Toast toast = Toast.makeText(TrackListActivity.this,"Recording starts in " + secondsLeft + " seconds", Toast.LENGTH_SHORT); - toast.show(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - toast.cancel(); - }}); - - } catch (Exception e) { - throw new RuntimeException(e); - } - updateGpsMenuItem(false, true); - new TrackRecordingServiceConnection((service, connection) -> { - Track.Id trackId = service.startNewTrack(); - - Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class); - newIntent.putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, trackId); - startActivity(newIntent); - - connection.unbind(this); - }).startAndBind(this, true); + // Show the notification dialog to select type of the metric to show in starting new track + showNotificationOptionsDialog(); }); viewBinding.trackListFabAction.setOnLongClickListener((view) -> { if (!recordingStatus.isRecording()) { @@ -681,4 +664,74 @@ private void onRecordingStatusChanged(RecordingStatus status) { recordingStatus = status; setFloatButton(); } -} \ No newline at end of file + + // Add a new method for handling the start recording action + private void startRecording() { + // Not Recording -> Recording + try { + runOnUiThread(() -> { + for (int i = selectedDelayInSeconds; i >= 0; i--) { + + final int secondsLeft = i; + Toast toast = Toast.makeText(TrackListActivity.this,"Recording starts in " + secondsLeft + " seconds", Toast.LENGTH_SHORT); + toast.show(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + toast.cancel(); + }}); + + } catch (Exception e) { + throw new RuntimeException(e); + } + updateGpsMenuItem(false, true); + new TrackRecordingServiceConnection((service, connection) -> { + Track.Id trackId = service.startNewTrack(); + + Intent newIntent = IntentUtils.newIntent(TrackListActivity.this, TrackRecordingActivity.class); + newIntent.putExtra(TrackRecordingActivity.EXTRA_TRACK_ID, trackId); + startActivity(newIntent); + + connection.unbind(this); + }).startAndBind(this, true); + } + + // Function to show the dialog for notification options + private void showNotificationOptionsDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.choose_notification_option) + .setItems(R.array.notification_options, (dialog, which) -> { + // Store the user's choice + saveNotificationPreference(which); + + // Update the notification based on the user's choice + updateNotification(); + + // Start recording after the user has made a choice + startRecording(); + }); + builder.create().show(); + } + + // Function to save the user's notification preference + private void saveNotificationPreference(int choice) { + SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt(NOTIFICATION_PREFERENCE_KEY, choice); + editor.apply(); + } + + // Function to update the notification based on user's choice + private void updateNotification() { + SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE); + int userChoice = preferences.getInt(NOTIFICATION_PREFERENCE_KEY, DEFAULT_CHOICE); + + switch (userChoice) { + case SPEED_METRIC_CHOICE -> notifChoice = "speed"; + case HEART_RATE_METRIC_CHOICE -> notifChoice = "heartRate"; + case DISTANCE_METRIC_CHOICE -> notifChoice = "distance"; + } + } +} diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java index 7c9eb13ee..331d06597 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java @@ -17,6 +17,7 @@ import de.dennisguse.opentracks.TrackListActivity; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.DistanceFormatter; +import de.dennisguse.opentracks.data.models.HeartRate; import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.settings.PreferencesUtils; @@ -93,9 +94,26 @@ void updateTrackPoint(Context context, TrackStatistics trackStatistics, TrackPoi previousLocationWasAccurate = currentLocationWasAccurate; } - notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance()))); - String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed()); - notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed)); + switch (TrackListActivity.notifChoice) { + case "distance" -> { + notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance()))); + } + case "speed" -> { + String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed()); + notificationBuilder.setContentTitle(context.getString(R.string.track_speed_notification, formattedSpeed)); + } + case "heartRate" -> { + if (trackPoint.hasHeartRate()) { + HeartRate heartRate = trackPoint.getHeartRate(); + String formattedHeartRate = String.valueOf(heartRate.getBPM()); + notificationBuilder.setContentTitle(context.getString(R.string.track_heart_rate_notification, formattedHeartRate)); + } else { + // Handle the case where no heart rate data is available + notificationBuilder.setContentTitle(context.getString(R.string.no_heart_rate_data)); + } + } + } + notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy)); updateNotification(); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 075da803f..344492de2 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -641,6 +641,7 @@ limitations under the License. Lap speed Average moving speed Total distance + Current time {n, plural, =1 {1 kilometer}