diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/AutoGpxExporter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/AutoGpxExporter.java index 0cb9e51cac..ac82146e93 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/AutoGpxExporter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/AutoGpxExporter.java @@ -1,8 +1,25 @@ +/* Copyright (C) 2026 José Rebelo, Thomas Kuehne + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.export; import android.content.Context; import android.net.Uri; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.documentfile.provider.DocumentFile; @@ -30,21 +47,41 @@ import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; public class AutoGpxExporter { private static final Logger LOG = LoggerFactory.getLogger(AutoGpxExporter.class); - public static void doExport(final Context context, - final GBDevice gbDevice, - @Nullable final BaseActivitySummary summary, - final ActivityTrack activityTrack) { + public static boolean isExportEnabled(@NonNull final GBDevice gbDevice) { + return getExportDirectory(gbDevice) != null; + } + + @Nullable + public static String getExportDirectory(@NonNull final GBDevice gbDevice) { final GBPrefs prefs = GBApplication.getPrefs(); final boolean enabled = prefs.getBoolean(GBPrefs.AUTO_EXPORT_GPX_ENABLED, false); if (!enabled) { LOG.debug("Auto gpx export is disabled"); - return; + return null; } final Set selectedDevices = prefs.getStringSet(GBPrefs.AUTO_EXPORT_GPX_SELECTED_DEVICES, Collections.emptySet()); final boolean allDevices = prefs.getBoolean(GBPrefs.AUTO_EXPORT_GPX_ALL_DEVICES, true); if (!allDevices && !selectedDevices.contains(gbDevice.getAddress())) { - LOG.debug("Skipping auto gpx export - not enabled for {}", gbDevice); + LOG.debug("Auto gpx export is not enabled for {}", gbDevice); + return null; + } + + final String directory = prefs.getString(GBPrefs.AUTO_EXPORT_GPX_DIRECTORY, ""); + if (directory.isBlank()) { + LOG.warn("No auto gpx export directory specified"); + return null; + } + + return directory; + } + + public static void doExport(final Context context, + final GBDevice gbDevice, + @Nullable final BaseActivitySummary summary, + final ActivityTrack activityTrack) { + final String directory = getExportDirectory(gbDevice); + if (directory == null) { return; } @@ -55,12 +92,6 @@ public class AutoGpxExporter { return; } - final String directory = prefs.getString(GBPrefs.AUTO_EXPORT_GPX_DIRECTORY, ""); - if (directory.isBlank()) { - LOG.warn("Not auto-exporting gpx, no directory specified"); - return; - } - final String trackType; if (summary != null) { trackType = context.getString(ActivityKind.fromCode(summary.getActivityKind()).getLabel()).toLowerCase(Locale.ROOT); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/FitActivityTrackProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/FitActivityTrackProvider.java index 4fbc54a1e6..19a0664d2e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/FitActivityTrackProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/FitActivityTrackProvider.java @@ -58,7 +58,11 @@ public class FitActivityTrackProvider implements ActivityTrackProvider { LOG.error("Failed to parse fit file", e); return null; } + return getActivityTrack(summary, fitFile); + } + @Nullable + public ActivityTrack getActivityTrack(@NonNull final BaseActivitySummary summary, @NonNull final FitFile fitFile) { final ActivityTrack activityTrack = new ActivityTrack(); activityTrack.setName(summary.getName()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitAsyncProcessor.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitAsyncProcessor.java index 2d3665f9f3..6582dfd045 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitAsyncProcessor.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitAsyncProcessor.java @@ -38,6 +38,7 @@ public class FitAsyncProcessor { new Thread(() -> { try { + FitImporter fitImporter = null; int i = 0; for (final File file : files) { i++; @@ -47,10 +48,13 @@ public class FitAsyncProcessor { FitAsyncProcessor.this.handler.post(() -> callback.onProgress(finalI)); try { - final FitImporter fitImporter = new FitImporter(context, gbDevice); + if (fitImporter == null) { + fitImporter = new FitImporter(context, gbDevice); + } fitImporter.importFile(file, isReprocessing); } catch (final Exception ex) { LOG.error("Exception while importing {}", file, ex); + fitImporter = null; continue; // do not remove from pending files } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitImporter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitImporter.java index 882e4daefa..4d712e679b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitImporter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FitImporter.java @@ -566,7 +566,7 @@ public class FitImporter { switch (fileId.getType()) { case ACTIVITY: - persistWorkout(finalExportFile, session, isReprocessing); + persistWorkout(finalExportFile, session, isReprocessing, fitFile); break; case MONITOR: persistActivitySamples(session); @@ -644,7 +644,7 @@ public class FitImporter { } } - private void persistWorkout(final File file, final DaoSession session, boolean isReprocessing) { + private void persistWorkout(final File file, final DaoSession session, boolean isReprocessing, FitFile fitFile) { LOG.debug("Persisting workout for {}", fileId); Long sessionStart = workoutParser.getSessionStartTime(); @@ -701,10 +701,12 @@ public class FitImporter { } // Export to gpx - final FitActivityTrackProvider activityTrackProvider = new FitActivityTrackProvider(); - final ActivityTrack activityTrack = activityTrackProvider.getActivityTrack(summary); - if (activityTrack != null) { - AutoGpxExporter.doExport(context, gbDevice, summary, activityTrack); + if (AutoGpxExporter.isExportEnabled(gbDevice)) { + final FitActivityTrackProvider activityTrackProvider = new FitActivityTrackProvider(); + final ActivityTrack activityTrack = activityTrackProvider.getActivityTrack(summary, fitFile); + if (activityTrack != null) { + AutoGpxExporter.doExport(context, gbDevice, summary, activityTrack); + } } }