diff --git a/README.md b/README.md index 29bd51489..0d7849593 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ OpenTracks can be used with [Gadgetbridge](https://www.gadgetbridge.org/): __Only required permission:__ * _ACCESS_FINE_LOCATION_: required to use the GPS. -### API +### Public API OpenTracks includes an API for starting/stopping recording by another installed application (e.g., [Automate](https://llamalab.com/automate/), [Tasker](https://tasker.joaoapps.com), or [Easer](https://github.com/renyuneyun/Easer)). The API can be invoked by sending an explicit Intent to start an activity. @@ -107,20 +107,37 @@ The API can be invoked by sending an explicit Intent to start an activity. * Nightly: `de.dennisguse.opentracks.nightly` `Class`: + * **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording` * **Stop a recording:** `de.dennisguse.opentracks.publicapi.StopRecording` For testing via adb: `adb shell am start -n "package/class"` -The Start/Stop API is disabled by default to protect the user's privacy, but it can easily be enabled in the settings. +`StartRecording` supports the following parameters: -## Custom Dashboards (incl. map) -As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live tracks. +* Set track data: `TRACK_NAME`, `TRACK_CATEGORY`, and `TRACK_DESCRIPTION` +* Send recorded data to another application via _Dashboard API_: `STATS_TARGET_PACKAGE` + and `STATS_TARGET_CLASS` -The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which presents an OpenStreetMap map (showing the current track, incl. updates). The Dashboard API is also used by [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) for displaying live track statistics on supported wearables. +The Public API is disabled by default to protect the user's privacy, but it can easily be enabled in +the settings. -Alternatively, recorded tracks can be shared as KMZ/GPX with installed applications (e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand)). -However, this is rather slow and does not provide updates while recording. +__IMPORTANT__: triggering `StartRecording` does not check if Android permissions (location or +Bluetooth) were granted. If they are not granted` + +## Dashboard API (incl. map) + +As of v3.3.1, OpenTracks supports custom dashboards for displaying previously recorded and live +tracks. + +The reference implementation is [OSMDashboard](https://github.com/OpenTracksApp/OSMDashboard), which +presents an OpenStreetMap map (showing the current track, incl. updates). The Dashboard API is also +used by [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) for displaying live track +statistics on supported wearables. + +Alternatively, recorded tracks can be shared as KMZ/GPX with installed applications ( +e.g., [OsmAnd](https://play.google.com/store/apps/details?id=net.osmand)). However, this is rather +slow and does not provide updates while recording. The developer documentation is in [README_API.md](README_API.md). diff --git a/src/main/java/de/dennisguse/opentracks/publicapi/StartRecording.java b/src/main/java/de/dennisguse/opentracks/publicapi/StartRecording.java index 9a7c7471b..c904e1c5b 100644 --- a/src/main/java/de/dennisguse/opentracks/publicapi/StartRecording.java +++ b/src/main/java/de/dennisguse/opentracks/publicapi/StartRecording.java @@ -2,26 +2,57 @@ package de.dennisguse.opentracks.publicapi; import android.os.Bundle; +import androidx.annotation.NonNull; + +import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.util.IntentDashboardUtils; +import de.dennisguse.opentracks.util.TrackUtils; public class StartRecording extends AbstractAPIActivity { + + public static final String EXTRA_TRACK_NAME = "TRACK_NAME"; + public static final String EXTRA_TRACK_CATEGORY = "TRACK_CATEGORY"; + public static final String EXTRA_TRACK_DESCRIPTION = "TRACK_DESCRIPTION"; + + public static final String EXTRA_STATS_TARGET_PACKAGE = "STATS_TARGET_PACKAGE"; + public static final String EXTRA_STATS_TARGET_CLASS = "STATS_TARGET_CLASS"; + private static final String TAG = StartRecording.class.getSimpleName(); protected void execute(TrackRecordingService service) { Track.Id trackId = service.startNewTrack(); - if ((trackId != null) && (PreferencesUtils.isPublicAPIDashboardEnabled())) { + if (trackId != null) { Bundle bundle = getIntent().getExtras(); if (bundle != null) { - String targetPackage = bundle.getString("STATS_TARGET_PACKAGE", null); - String targetClass = bundle.getString("STATS_TARGET_CLASS", null); - IntentDashboardUtils.startDashboard(this, true, targetPackage, targetClass, trackId); + updateTrackMetadata(trackId, bundle); + + if (PreferencesUtils.isPublicAPIDashboardEnabled()) { + startDashboardAPI(trackId, bundle); + } } } } + private void updateTrackMetadata(@NonNull Track.Id trackId, @NonNull Bundle bundle) { + ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); + Track track = contentProviderUtils.getTrack(trackId); + + TrackUtils.updateTrack(this, track, bundle.getString(EXTRA_TRACK_NAME, null), + bundle.getString(EXTRA_TRACK_CATEGORY, null), bundle.getString(EXTRA_TRACK_DESCRIPTION, null), + contentProviderUtils); + } + + private void startDashboardAPI(@NonNull Track.Id trackId, @NonNull Bundle bundle) { + String targetPackage = bundle.getString(EXTRA_STATS_TARGET_PACKAGE, null); + String targetClass = bundle.getString(EXTRA_STATS_TARGET_CLASS, null); + if (targetClass != null && targetPackage != null) { + IntentDashboardUtils.startDashboard(this, true, targetPackage, targetClass, trackId); + } + } + @Override protected boolean isPostExecuteStopService() { return false; diff --git a/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java b/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java index 7905f8ac0..f5dfdbc9b 100644 --- a/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/IntentDashboardUtils.java @@ -9,6 +9,7 @@ import android.util.Log; import android.util.Pair; import android.widget.Toast; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import java.util.ArrayList; @@ -138,7 +139,7 @@ public class IntentDashboardUtils { * @param targetClass the target class * @param trackIds the track ids */ - public static void startDashboard(Context context, boolean isRecording, String targetPackage, String targetClass, Track.Id... trackIds) { + public static void startDashboard(Context context, boolean isRecording, @Nullable String targetPackage, @Nullable String targetClass, Track.Id... trackIds) { if (trackIds.length == 0) { return; } @@ -168,7 +169,7 @@ public class IntentDashboardUtils { clipData.addItem(new ClipData.Item(uris.get(MARKERS_URI_INDEX))); intent.setClipData(clipData); - if ((targetPackage != null) && (targetClass != null)) { + if (targetPackage != null && targetClass != null) { Log.i(TAG, "Starting dashboard activity with explicit intent (package=" + targetPackage + ", class=" + targetClass + ")"); intent.setClassName(targetPackage, targetClass); } else {