diff --git a/app/res/layout/start_basic.xml b/app/res/layout/start_basic.xml
index 545ac0ae3..9ebc39870 100644
--- a/app/res/layout/start_basic.xml
+++ b/app/res/layout/start_basic.xml
@@ -60,4 +60,22 @@
android:prompt="@string/Type"
android:text="@string/Target_heart_rate_zone"
android:visibility="gone" />
+
+
+
+
+
diff --git a/app/res/values/pref_keys.xml b/app/res/values/pref_keys.xml
index 279aae5b0..a5c2aab0f 100644
--- a/app/res/values/pref_keys.xml
+++ b/app/res/values/pref_keys.xml
@@ -81,6 +81,8 @@
basic_target_pace_max
basic_target_pace_min_range
basic_target_hrz
+ basic_enable_autolap_time
+ basic_autolap_time_duration
intervalAudio
intervalRepetitions
diff --git a/app/src/main/org/runnerup/view/StartFragment.java b/app/src/main/org/runnerup/view/StartFragment.java
index ed5bcb128..8c86ae38b 100644
--- a/app/src/main/org/runnerup/view/StartFragment.java
+++ b/app/src/main/org/runnerup/view/StartFragment.java
@@ -46,6 +46,7 @@
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -147,6 +148,8 @@ private enum GpsLevel {
TitleSpinner simpleTargetType = null;
TitleSpinner simpleTargetPaceValue = null;
TitleSpinner simpleTargetHrz = null;
+ CheckBox simpleEnableAutolapTime = null;
+ TitleSpinner simpleAutolapTime = null;
AudioSchemeListAdapter simpleAudioListAdapter = null;
HRZonesListAdapter hrZonesAdapter = null;
@@ -166,6 +169,7 @@ private enum GpsLevel {
AudioSchemeListAdapter advancedAudioListAdapter = null;
SQLiteDatabase mDB = null;
+ SharedPreferences prefs = null;
Formatter formatter = null;
private NotificationStateManager notificationStateManager;
@@ -190,6 +194,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
Context context = requireContext();
mDB = DBHelper.getWritableDatabase(context);
formatter = new Formatter(context);
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
bindGpsTracker();
mGpsStatus = new org.runnerup.tracker.GpsStatus(context);
@@ -206,7 +211,6 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
context, R.layout.actionbar_spinner, Sport.getStringArray(getResources()));
adapter.setDropDownViewResource(R.layout.actionbar_dropdown_spinner);
sportSpinner.setAdapter(adapter);
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
sportSpinner.setViewSelection(
prefs.getInt(getResources().getString(R.string.pref_sport), DB.ACTIVITY.SPORT_RUNNING));
@@ -271,6 +275,9 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
simpleTargetHrz = view.findViewById(R.id.tab_basic_target_hrz);
simpleTargetHrz.setAdapter(hrZonesAdapter);
simpleTargetType.setOnCloseDialogListener(simpleTargetTypeClick);
+ simpleEnableAutolapTime = view.findViewById(R.id.tab_basic_enable_autolap_time);
+ simpleAutolapTime = view.findViewById(R.id.tab_basic_autolap_time_duration);
+ simpleAutolapTime.setOnSetValueListener(onSetTimeValidator);
intervalType = view.findViewById(R.id.interval_type);
intervalTime = view.findViewById(R.id.start_interval_time);
@@ -321,6 +328,17 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
mWearNotifier = new TrackerWear.WearNotifier(requireActivity().getApplicationContext());
mWearNotifier.onViewCreated();
+ var enable_autolap_time_key = getString(R.string.pref_basic_enable_autolap_time);
+ simpleEnableAutolapTime.setChecked(prefs.getBoolean(enable_autolap_time_key, true));
+ simpleEnableAutolapTime.setOnCheckedChangeListener(
+ new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ prefs.edit().putBoolean(enable_autolap_time_key, b).apply();
+ simpleAutolapTime.setEnabled(b);
+ }
+ });
+
var listener = sportSpinner.getViewOnItemSelectedListener();
sportSpinner.setViewOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
@@ -555,9 +573,7 @@ private void onGpsTrackerBound() {
}
public boolean getAutoStartGps() {
- Context ctx = requireActivity().getApplicationContext();
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx);
- return pref.getBoolean(getString(R.string.pref_startgps), false);
+ return prefs.getBoolean(getString(R.string.pref_startgps), false);
}
private void startGps() {
@@ -611,7 +627,6 @@ private void notificationBatteryLevel(int batteryLevel) {
Context context = requireContext();
final String pref_key = getString(R.string.pref_battery_level_low_notification_discard);
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int batteryLevelHighThreshold =
SafeParse.parseInt(
@@ -689,6 +704,13 @@ private Workout prepareWorkout() {
}
if (w != null) {
WorkoutBuilder.prepareWorkout(getResources(), pref, w);
+ if (sportWithoutGps && simpleEnableAutolapTime.isChecked()) {
+ long seconds =
+ SafeParse.parseSeconds(String.valueOf(simpleAutolapTime.getViewValueText()), 0);
+ if (seconds > 0) {
+ WorkoutBuilder.setAutolapTime(w, seconds);
+ }
+ }
WorkoutBuilder.addAudioCuesToWorkout(getResources(), w, audioPref, pref);
}
return w;
@@ -742,7 +764,6 @@ private List getPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
requiredPerms.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
boolean enabled =
prefs.getBoolean(
this.getString(org.runnerup.R.string.pref_use_cadence_step_sensor), true);
@@ -755,7 +776,6 @@ private List getPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S /* Android12, sdk31*/
&& (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
|| packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH))) {
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
final String btDeviceName = prefs.getString(getString(R.string.pref_bt_name), null);
if (btDeviceName != null && !btDeviceName.isEmpty()) {
requiredPerms.add(Manifest.permission.BLUETOOTH_CONNECT);
@@ -856,7 +876,6 @@ private boolean checkPermissions(boolean popup) {
// https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
// Permission REQUEST_IGNORE_BATTERY_OPTIMIZATIONS requires special approval in Play
- final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
final Resources res = this.getResources();
final boolean suppressOptimizeBatteryPopup =
prefs.getBoolean(res.getString(R.string.pref_suppress_battery_optimization_popup), false);
@@ -947,6 +966,14 @@ public void updateView() {
} else {
noDevicesConnected.setVisibility(View.GONE);
}
+ if (sportWithoutGps) {
+ simpleEnableAutolapTime.setVisibility(View.VISIBLE);
+ simpleAutolapTime.setVisibility(View.VISIBLE);
+ simpleAutolapTime.setEnabled(simpleEnableAutolapTime.isChecked());
+ } else {
+ simpleEnableAutolapTime.setVisibility(View.GONE);
+ simpleAutolapTime.setVisibility(View.GONE);
+ }
}
private void updateStartButtonView() {
@@ -1195,7 +1222,6 @@ public String getGpsAccuracyString(float accuracy) {
private String getHRDetailString() {
StringBuilder str = new StringBuilder();
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
final String btDeviceName = prefs.getString(getString(R.string.pref_bt_name), null);
if (btDeviceName != null) {
diff --git a/app/src/main/org/runnerup/workout/Step.java b/app/src/main/org/runnerup/workout/Step.java
index 037bf3338..a33b4e7c4 100644
--- a/app/src/main/org/runnerup/workout/Step.java
+++ b/app/src/main/org/runnerup/workout/Step.java
@@ -42,7 +42,10 @@ public class Step implements TickComponent {
Range targetValue = null;
/** Autolap (m) */
- private double autolap = 0;
+ private double autolap_distance = 0;
+
+ /** Autolap (s) */
+ private double autolap_time = 0;
/** Triggers */
final ArrayList triggers = new ArrayList<>();
@@ -129,18 +132,19 @@ public void setIntensity(Intensity intensity) {
this.intensity = intensity;
}
- /**
- * @return the autolap distance (may be set in workouts too)
- */
- double getAutolap() {
- return autolap;
- }
-
/**
* @param val the autolap to set
*/
void setAutolap(double val) {
- this.autolap = val;
+ this.autolap_distance = val;
+ }
+
+ double getAutolapDistance() {
+ return autolap_distance;
+ }
+
+ void setAutolapTime(double val) {
+ this.autolap_time = val;
}
@Override
@@ -302,7 +306,7 @@ private boolean exceedDistance(
}
private boolean checkFinished(Workout s) {
- if (this.getAutolap() == 0 && durationType == null) {
+ if (autolap_distance == 0 && durationType == null) {
return false;
}
@@ -325,11 +329,18 @@ private boolean checkFinished(Workout s) {
newStep = s.get(Scope.STEP, durationType) + diff >= this.durationValue;
}
- if (!newStep && this.getAutolap() > 0) {
+ if (!newStep) {
double distance = s.getDistance(Scope.LAP);
- double lapDist = getAutolap();
- if (exceedDistance(distance, mPrevTickLapDistance, lapDist, time)) {
- newLap = true;
+ if (autolap_distance > 0) {
+ if (exceedDistance(distance, mPrevTickLapDistance, autolap_distance, time)) {
+ newLap = true;
+ }
+ }
+ if (autolap_time > 0) {
+ double lap_time = s.getTime(Scope.LAP);
+ if (lap_time >= autolap_time) {
+ newLap = true;
+ }
}
mPrevTickLapDistance = distance;
}
diff --git a/app/src/main/org/runnerup/workout/WorkoutBuilder.java b/app/src/main/org/runnerup/workout/WorkoutBuilder.java
index 7e9305b20..33a5215b4 100644
--- a/app/src/main/org/runnerup/workout/WorkoutBuilder.java
+++ b/app/src/main/org/runnerup/workout/WorkoutBuilder.java
@@ -270,7 +270,7 @@ private static void addAudioCuesToWorkout(
// Periodic distance/time and end of lap/step
// Some suppressions for each intensity for related lap started/completed
// endOfLap is related to the autolap
- boolean endOfLap = step.getIntensity() == Intensity.ACTIVE || step.getAutolap() > 0;
+ boolean endOfLap = step.getIntensity() == Intensity.ACTIVE || step.getAutolapDistance() > 0;
ArrayList defaultTriggers = createDefaultTriggers(res, audioPrefs, endOfLap);
step.triggers.addAll(defaultTriggers);
@@ -415,8 +415,8 @@ private static void checkDuplicateTriggers(Step step) {
* trigger
*/
ArrayList list = new ArrayList<>();
- if (step.getAutolap() > 0) {
- list.add(new EndOfLapSuppression(step.getAutolap()));
+ if (step.getAutolapDistance() > 0) {
+ list.add(new EndOfLapSuppression(step.getAutolapDistance()));
}
if (step.getDurationType() == Dimension.DISTANCE) {
@@ -663,6 +663,15 @@ public static void prepareWorkout(Resources res, SharedPreferences prefs, Workou
}
}
+ public static void setAutolapTime(Workout w, double seconds) {
+ for (StepListEntry s : w.getStepList()) {
+ if (s.step().getIntensity() == Intensity.ACTIVE
+ || s.step().getIntensity() == Intensity.COOLDOWN) {
+ s.step().setAutolapTime(seconds);
+ }
+ }
+ }
+
public static void addFeedbackFromPreferences(
SharedPreferences prefs, Resources res, ArrayList feedback) {
int feedbackStart = feedback.size();
diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml
index fb3a4eab2..6eff017f6 100644
--- a/common/src/main/res/values/strings.xml
+++ b/common/src/main/res/values/strings.xml
@@ -164,6 +164,8 @@
Heart rate monitor
Heart rate zones
Autolap
+ Enable autolap by time
+ time
Autolap (m)
Autopause
Autopause in basic workouts and Warmup and Cooldown steps