From ca24e46eefaf43a9db57220203b204caced499c9 Mon Sep 17 00:00:00 2001 From: Gerhard Olsson Date: Mon, 19 Oct 2026 22:00:16 +0200 Subject: [PATCH 1/4] fix: use streamed json parsing occasional out-of-memory crashes --- .../org/runnerup/export/util/SyncHelper.java | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/app/src/main/org/runnerup/export/util/SyncHelper.java b/app/src/main/org/runnerup/export/util/SyncHelper.java index 1bd619ea8..951573841 100644 --- a/app/src/main/org/runnerup/export/util/SyncHelper.java +++ b/app/src/main/org/runnerup/export/util/SyncHelper.java @@ -34,7 +34,6 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import java.util.Scanner; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -125,24 +124,31 @@ public static void setName(ContentValues c, String string) { } public static JSONObject parse(String in) throws JSONException { - final Scanner s = new Scanner(in); - final JSONObject o = new JSONObject(s.useDelimiter("\\A").next()); - s.close(); - return o; + return new JSONObject(in); } public static JSONObject parse(InputStream in) throws JSONException { - final Scanner s = new Scanner(in); - final JSONObject o = new JSONObject(s.useDelimiter("\\A").next()); - s.close(); - return o; + return parse( + new BufferedReader(new InputStreamReader(in, java.nio.charset.StandardCharsets.UTF_8))); } public static JSONObject parse(Reader in) throws JSONException { - final Scanner s = new Scanner(in); - final JSONObject o = new JSONObject(s.useDelimiter("\\A").next()); - s.close(); - return o; + BufferedReader reader = + in instanceof BufferedReader ? (BufferedReader) in : new BufferedReader(in); + StringBuilder sb = new StringBuilder(); + String line; + try { + while ((line = reader.readLine()) != null) { + sb.append(line).append('\n'); + } + } catch (IOException e) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + throw new JSONException(e); + } else { + throw new JSONException(e.getMessage()); + } + } + return new JSONObject(sb.toString()); } public static JSONObject parse(HttpURLConnection conn, String name) From 66969c2637a2f1c21eb9521442e318a25029427a Mon Sep 17 00:00:00 2001 From: Gerhard Olsson Date: Mon, 19 Oct 2026 22:12:57 +0200 Subject: [PATCH 2/4] fix: ensure dB is writable after pause exception seen in Play --- app/src/main/org/runnerup/tracker/Tracker.java | 13 ++++++++++++- .../runnerup/tracker/component/TrackerReceiver.java | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/org/runnerup/tracker/Tracker.java b/app/src/main/org/runnerup/tracker/Tracker.java index f880989a3..3910aa04f 100644 --- a/app/src/main/org/runnerup/tracker/Tracker.java +++ b/app/src/main/org/runnerup/tracker/Tracker.java @@ -130,6 +130,14 @@ public class Tracker extends Service implements LocationListenerCompat, Constant private SQLiteDatabase mDB = null; private PersistentGpsLoggerListener mDBWriter = null; private PowerManager.WakeLock mWakeLock = null; + + public SQLiteDatabase getDatabase() { + if (mDB == null) { + mDB = DBHelper.getWritableDatabase(this); + } + return mDB; + } + private final List liveLoggers = new ArrayList<>(); private Workout workout = null; @@ -574,7 +582,10 @@ public void completeActivity(boolean save, Double manualDistance) { private void saveActivity(Double manualDistance) { if (mDB == null) { - Log.e("Tracker", "saveActivity called but mDB is null"); + mDB = DBHelper.getWritableDatabase(this); + } + if (mDB == null) { + Log.e("Tracker", "saveActivity: mDB is still null after attempting to reopen"); return; } ContentValues tmp = new ContentValues(); diff --git a/app/src/main/org/runnerup/tracker/component/TrackerReceiver.java b/app/src/main/org/runnerup/tracker/component/TrackerReceiver.java index cd1d7f0ca..372e9bf1d 100644 --- a/app/src/main/org/runnerup/tracker/component/TrackerReceiver.java +++ b/app/src/main/org/runnerup/tracker/component/TrackerReceiver.java @@ -86,6 +86,9 @@ private void onReceive(Context context, Intent intent) { Workout workout = tracker.getWorkout(); if (workout == null) return; + // Ensure database is available if we receive an action that might cause activity saving/pausing + tracker.getDatabase(); + if (Constants.Intents.PAUSE_RESUME.contentEquals(action)) { if (workout.isPaused()) workout.onResume(workout); else workout.onPause(workout); From 654da6cc496a8970d998bcae8e935bde0a77b751 Mon Sep 17 00:00:00 2001 From: Gerhard Olsson Date: Mon, 19 Oct 2026 22:57:12 +0200 Subject: [PATCH 3/4] fix(purgeActivities): abort if dialog is dismissed exception seen in Play if starting activity just after dismissing the dialog --- app/src/main/org/runnerup/db/DBHelper.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/org/runnerup/db/DBHelper.java b/app/src/main/org/runnerup/db/DBHelper.java index 296e4d4f5..19dd052b1 100644 --- a/app/src/main/org/runnerup/db/DBHelper.java +++ b/app/src/main/org/runnerup/db/DBHelper.java @@ -639,6 +639,9 @@ public static void purgeDeletedActivities( () -> { int currentProgress = 0; for (Long id : list) { + if (!dialog.isShowing()) { + break; + } deleteActivity(db, id); currentProgress++; final int progressToShow = currentProgress; @@ -648,8 +651,11 @@ public static void purgeDeletedActivities( // Post-execution step (runs on the main thread) handler.post( () -> { - db.close(); - mDBHelper.close(); + try { + db.close(); + mDBHelper.close(); + } catch (Exception ignored) { + } if (onComplete != null) { onComplete.run(); } @@ -657,8 +663,11 @@ public static void purgeDeletedActivities( }); } else { // No activities to delete, just clean up - db.close(); - mDBHelper.close(); + try { + db.close(); + mDBHelper.close(); + } catch (Exception ignored) { + } if (onComplete != null) { onComplete.run(); } From 87d87623445e1f3652c42dc5a424d058097cfc88 Mon Sep 17 00:00:00 2001 From: Gerhard Olsson Date: Tue, 20 Oct 2026 22:22:49 +0200 Subject: [PATCH 4/4] fix: disable animation (#1403) crash reported in Play console --- app/res/layout/start.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/res/layout/start.xml b/app/res/layout/start.xml index cfd99ff48..1694e868e 100644 --- a/app/res/layout/start.xml +++ b/app/res/layout/start.xml @@ -73,7 +73,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" - android:animateLayoutChanges="true" android:background="#424242" android:clickable="true" android:focusable="true"