mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 09:33:06 +02:00
Public API: allow setting track properties (name, category, description) on StartRecording.
Fixes #1282.
This commit is contained in:
@@ -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).
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user