diff --git a/app/src/main/org/runnerup/tracker/component/TrackerGPS.java b/app/src/main/org/runnerup/tracker/component/TrackerGPS.java index ca04ded20..b4263c196 100644 --- a/app/src/main/org/runnerup/tracker/component/TrackerGPS.java +++ b/app/src/main/org/runnerup/tracker/component/TrackerGPS.java @@ -110,22 +110,22 @@ private Integer parseAndFixInteger( String s = preferences.getString(context.getString(resId), def); if (TextUtils.isEmpty(s)) { // Update the settings - SharedPreferences.Editor prefedit = preferences.edit(); - prefedit.putString(context.getString(resId), def); - prefedit.apply(); + SharedPreferences.Editor prefs = preferences.edit(); + prefs.putString(context.getString(resId), def); + prefs.apply(); s = def; } return Integer.parseInt(s); } - static Location getLastKnownLocation(LocationManager lm, Context context) { + private static Location getLastKnownLocation(LocationManager lm, Context context) { String[] list = {GPS_PROVIDER, NETWORK_PROVIDER, PASSIVE_PROVIDER}; Location lastLocation = null; for (String s : list) { - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED - && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - // User has deactivated location permission during the workout. - continue; + if (s.equals(GPS_PROVIDER) + && (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED + && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { + continue; } Location tmp = lm.getLastKnownLocation(s); if (tmp == null) { @@ -151,7 +151,7 @@ static Location getLastKnownLocation(LocationManager lm, Context context) { @Override public ResultCode onConnecting(final Callback callback, Context context) { - if (mWithoutGps == false && + if (!mWithoutGps && ContextCompat.checkSelfPermission(this.tracker, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { mWithoutGps = true; @@ -253,7 +253,7 @@ public void run() { @Override public void onTick() { - if (mWithoutGps == false) { + if (!mWithoutGps) { if (mGpsStatus == null) { return; } @@ -269,8 +269,10 @@ public void onTick() { Callback tmp = mConnectCallback; mConnectCallback = null; - mGpsStatus.stop(this); - // note: Don't reset mGpsStatus, it's used for isConnected() + if (mGpsStatus != null) { + mGpsStatus.stop(this); + // note: Don't reset mGpsStatus, it's used for isConnected() + } tmp.run(this, ResultCode.RESULT_OK); } diff --git a/app/src/main/org/runnerup/view/MainLayout.java b/app/src/main/org/runnerup/view/MainLayout.java index 708dccdc6..4d64e9b9d 100644 --- a/app/src/main/org/runnerup/view/MainLayout.java +++ b/app/src/main/org/runnerup/view/MainLayout.java @@ -39,6 +39,8 @@ import android.view.View.OnClickListener; import android.webkit.WebView; import android.widget.Toast; + +import androidx.activity.EdgeToEdge; import androidx.activity.OnBackPressedCallback; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; @@ -76,6 +78,7 @@ private enum UpgradeState { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setContentView(R.layout.main); diff --git a/app/src/main/org/runnerup/view/ManageWorkoutsActivity.java b/app/src/main/org/runnerup/view/ManageWorkoutsActivity.java index 8455d34f2..d511e4638 100644 --- a/app/src/main/org/runnerup/view/ManageWorkoutsActivity.java +++ b/app/src/main/org/runnerup/view/ManageWorkoutsActivity.java @@ -162,12 +162,11 @@ private String getFilename(Uri data) { } else if (ContentResolver.SCHEME_CONTENT.contentEquals(data.getScheme())) { String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME}; Cursor c = getContentResolver().query(data, projection, null, null, null); - if (c != null) { - c.moveToFirst(); + if (c != null && c.moveToFirst()) { final int fileNameColumnId = c.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME); if (fileNameColumnId >= 0) name = c.getString(fileNameColumnId); - c.close(); } + c.close(); } return name; } diff --git a/app/src/main/org/runnerup/workout/TargetTrigger.java b/app/src/main/org/runnerup/workout/TargetTrigger.java index fae5b0518..9738fca5f 100644 --- a/app/src/main/org/runnerup/workout/TargetTrigger.java +++ b/app/src/main/org/runnerup/workout/TargetTrigger.java @@ -248,6 +248,7 @@ public void onRepeat(int current, int limit) {} @Override public void onStart(Scope what, Workout s) { if (this.scope == what) { + paused = false; reset(); for (Feedback f : triggerAction) { f.onStart(s); diff --git a/app/src/main/org/runnerup/workout/Workout.java b/app/src/main/org/runnerup/workout/Workout.java index ecc5fda3c..c0b949048 100644 --- a/app/src/main/org/runnerup/workout/Workout.java +++ b/app/src/main/org/runnerup/workout/Workout.java @@ -139,6 +139,12 @@ public void onEnd(Workout w) { @Override public void onRepeat(int current, int limit) {} + /** + * Start the ACTIVITY, the tracker starts this once. The activity starts the steps for STEP/LAP. + * + * @param s always ACTIVITY + * @param w current workout + */ public void onStart(Scope s, Workout w) { if (BuildConfig.DEBUG && w != this) { throw new AssertionError(); @@ -151,10 +157,11 @@ public void onStart(Scope s, Workout w) { } currentStepNo = 0; - if (steps.size() > 0) { + if (!steps.isEmpty()) { setCurrentStep(steps.get(currentStepNo)); } + // start STEP and LAP if (currentStep != null) { currentStep.onStart(Scope.ACTIVITY, this); currentStep.onStart(Scope.STEP, this); diff --git a/app/src/main/org/runnerup/workout/WorkoutBuilder.java b/app/src/main/org/runnerup/workout/WorkoutBuilder.java index 502bdb941..24f24429d 100644 --- a/app/src/main/org/runnerup/workout/WorkoutBuilder.java +++ b/app/src/main/org/runnerup/workout/WorkoutBuilder.java @@ -185,17 +185,14 @@ public static Workout createDefaultIntervalWorkout(Resources res, SharedPreferen } repeat.steps.add(step); - Step rest = null; - switch (intervalRestType) { - case 0: // Time - rest = Step.createRestStep(Dimension.TIME, intervalRestTime, convertRestToRecovery); - break; - case 1: // Distance - rest = - Step.createRestStep(Dimension.DISTANCE, intervalRestDistance, convertRestToRecovery); - break; - } - repeat.steps.add(rest); + Step rest = switch (intervalRestType) { + case 0 -> // Time + Step.createRestStep(Dimension.TIME, intervalRestTime, convertRestToRecovery); + case 1 -> // Distance + Step.createRestStep(Dimension.DISTANCE, intervalRestDistance, convertRestToRecovery); + default -> null; + }; + repeat.steps.add(rest); } w.steps.add(repeat); @@ -214,7 +211,7 @@ public static boolean validateSeconds(String newValue) { // TODO move this somewhere long seconds = SafeParse.parseSeconds(newValue, -1); long seconds2 = SafeParse.parseSeconds(DateUtils.formatElapsedTime(seconds), -1); - return seconds == seconds2; + return seconds >= 0 && seconds == seconds2; } public static SharedPreferences getAudioCuePreferences( @@ -552,7 +549,7 @@ private static void createAudioCountdown(Step step) { } // Remove all values in list close to the step - while (list.size() > 0 && step.getDurationValue() < list.get(0) * 1.1d) { + while (!list.isEmpty() && step.getDurationValue() < list.get(0) * 1.1d) { list.remove(0); } list.add(0, step.getDurationValue()); diff --git a/wear/src/main/java/org/runnerup/service/StateService.java b/wear/src/main/java/org/runnerup/service/StateService.java index ee54d52e0..0d414707f 100644 --- a/wear/src/main/java/org/runnerup/service/StateService.java +++ b/wear/src/main/java/org/runnerup/service/StateService.java @@ -41,6 +41,8 @@ import org.runnerup.view.MainActivity; import org.runnerup.wear.WearableClient; +import java.util.Objects; + public class StateService extends Service implements MessageApi.MessageListener, DataApi.DataListener, ValueModel.ChangeListener { @@ -213,7 +215,7 @@ public void onDataChanged(DataEventBuffer dataEvents) { } private void setPhoneNode(DataEvent ev) { - if (ev.getType() == DataEvent.TYPE_CHANGED) { + if (ev.getType() == DataEvent.TYPE_CHANGED && Objects.requireNonNull(ev.getDataItem().getData()).length > 0) { phoneNode = new String(ev.getDataItem().getData()); } else if (ev.getType() == DataEvent.TYPE_DELETED) { phoneNode = null; diff --git a/wear/src/main/java/org/runnerup/view/RunInfoFragment.java b/wear/src/main/java/org/runnerup/view/RunInfoFragment.java index d630e67a7..c309df51b 100644 --- a/wear/src/main/java/org/runnerup/view/RunInfoFragment.java +++ b/wear/src/main/java/org/runnerup/view/RunInfoFragment.java @@ -88,21 +88,20 @@ public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { int[] ids = null; - int card = 0; - switch (rowsOnScreen) { - case 3: - ids = card3ids; - card = R.layout.card3; - break; - case 2: - ids = card2ids; - card = R.layout.card2; - break; - case 1: - ids = card1ids; - card = R.layout.card1; - break; - } + int card = switch (rowsOnScreen) { + case 2 -> { + ids = card2ids; + yield R.layout.card2; + } + case 1 -> { + ids = card1ids; + yield R.layout.card1; + } + default -> { + ids = card3ids; + yield R.layout.card3; + } + }; View view = inflater.inflate(card, container, false); for (int i = 0; i < rowsOnScreen; i++) { textViews.add(