forked from upstream-mirrors/OpenTracks
@@ -117,7 +117,19 @@ OpenTracks can be used with [Gadgetbridge](https://www.gadgetbridge.org/):
|
||||
__Only required permission:__
|
||||
* _ACCESS_FINE_LOCATION_: required to use the GPS.
|
||||
|
||||
An overview of Bluetooth LE sensors that are known to work with OpenTracks is in [README_TESTED_SENSORS.md](README_TESTED_SENSORS.md).
|
||||
### API
|
||||
The following functionalities by sending from an external 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 Intent to start an activity.
|
||||
Package (depends on the variant installed):
|
||||
* F-Droid: `de.dennisguse.opentracks`
|
||||
* GooglePlay: `de.dennisguse.opentracks.playStore`
|
||||
* Debug: `de.dennisguse.opentracks.debug`
|
||||
* Nightly: `de.dennisguse.opentracks.nightly`
|
||||
|
||||
Activity:
|
||||
* **Start a recording:** `de.dennisguse.opentracks.publicapi.StartRecording`
|
||||
|
||||
* For testing via adb: `adb shell am start -n "package/activity"`
|
||||
|
||||
## Custom Dashboards (incl. map)
|
||||
As of v3.3.1, OpenTracks supports custom dashboards.
|
||||
|
||||
@@ -69,6 +69,23 @@ limitations under the License.
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/ThemeCustom">
|
||||
|
||||
<activity
|
||||
android:name=".publicapi.StartRecording"
|
||||
android:exported="true"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- <activity-->
|
||||
<!-- android:name=".publicapi.StopRecording"-->
|
||||
<!-- android:exported="true"-->
|
||||
<!-- android:theme="@style/SplashTheme">-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <category android:name="android.intent.category.DEFAULT" />-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- </activity>-->
|
||||
|
||||
<activity android:name=".AboutActivity" />
|
||||
|
||||
<activity
|
||||
@@ -308,7 +325,9 @@ limitations under the License.
|
||||
|
||||
<activity android:name=".TrackRecordedActivity" />
|
||||
|
||||
<activity android:name=".TrackRecordingActivity" android:parentActivityName=".TrackListActivity">
|
||||
<activity
|
||||
android:name=".TrackRecordingActivity"
|
||||
android:parentActivityName=".TrackListActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".TrackListActivity" />
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package de.dennisguse.opentracks.publicapi;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
public abstract class AbstractAPIActivity extends AppCompatActivity {
|
||||
|
||||
private final String TAG = AbstractAPIActivity.class.getSimpleName();
|
||||
|
||||
private final TrackRecordingServiceConnection.Callback serviceConnectedCallback = service -> {
|
||||
if (!isFinishing() && !isDestroyed()) {
|
||||
execute(service);
|
||||
}
|
||||
if (isPostExecuteStopService()) {
|
||||
AbstractAPIActivity.this.trackRecordingServiceConnection.unbindAndStop(AbstractAPIActivity.this);
|
||||
} else {
|
||||
AbstractAPIActivity.this.trackRecordingServiceConnection.unbind(AbstractAPIActivity.this);
|
||||
}
|
||||
finish();
|
||||
};
|
||||
|
||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (PreferencesUtils.isPublicAPIenabled()) {
|
||||
Log.i(TAG, "Received and trying to execute requested action.");
|
||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(serviceConnectedCallback);
|
||||
trackRecordingServiceConnection.startAndBind(this);
|
||||
} else {
|
||||
Toast.makeText(this, getString(R.string.settings_public_api_disabled_toast), Toast.LENGTH_LONG).show();
|
||||
Log.w(TAG, "Public API is disabled; ignoring request.");
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
trackRecordingServiceConnection = null;
|
||||
}
|
||||
|
||||
protected abstract void execute(TrackRecordingService service);
|
||||
|
||||
protected abstract boolean isPostExecuteStopService();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.dennisguse.opentracks.publicapi;
|
||||
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
|
||||
public class StartRecording extends AbstractAPIActivity {
|
||||
|
||||
protected void execute(TrackRecordingService service) {
|
||||
service.startNewTrack();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPostExecuteStopService() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package de.dennisguse.opentracks.publicapi;
|
||||
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
|
||||
public class StopRecording extends AbstractAPIActivity {
|
||||
|
||||
protected void execute(TrackRecordingService service) {
|
||||
service.endCurrentTrack();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPostExecuteStopService() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -282,7 +282,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
showNotification(true);
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public void endCurrentTrack() {
|
||||
if (!isRecording()) {
|
||||
Log.w(TAG, "Ignore endCurrentTrack. Not recording.");
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -179,6 +178,10 @@ public class PreferencesUtils {
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public static boolean isPublicAPIenabled() {
|
||||
return getBoolean(R.string.publicapi_enabled_key, resources.getBoolean(R.bool.publicapi_enabled_default));
|
||||
}
|
||||
|
||||
public static boolean isMetricUnits() {
|
||||
final String STATS_UNIT = resources.getString(R.string.stats_units_default);
|
||||
return STATS_UNIT.equals(getString(R.string.stats_units_key, STATS_UNIT));
|
||||
|
||||
@@ -291,6 +291,9 @@
|
||||
<string name="import_prevent_reimport_key" translatable="false">preventReimportTrackKey</string>
|
||||
<bool name="import_prevent_reimport_default">true</bool>
|
||||
|
||||
<string name="publicapi_enabled_key" translatable="false">apiEnabledKey</string>
|
||||
<bool name="publicapi_enabled_default">false</bool>
|
||||
|
||||
<integer name="buttonDelayMillis">1500</integer>
|
||||
|
||||
<!-- androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode() -->
|
||||
|
||||
@@ -445,6 +445,12 @@ limitations under the License.
|
||||
<string name="settings_stats_units_metric">Metric (km, m)</string>
|
||||
<string name="settings_stats_units_title">Preferred units</string>
|
||||
|
||||
<!-- Settings public api -->
|
||||
<string name="settings_public_api_enabled_title">Public API</string>
|
||||
<string name="settings_public_api_enabled_summary_on">Other installed applications can start or stop recordings.</string>
|
||||
<string name="settings_public_api_enabled_summary_off">Only OpenTracks can start and stop recordings.</string>
|
||||
<string name="settings_public_api_disabled_toast">OpenTracks Public API is disabled: it can be enabled in the settings.</string>
|
||||
|
||||
<!-- Settings import/export -->
|
||||
<string name="settings_import_section">Import</string>
|
||||
<string name="settings_export_section">Export</string>
|
||||
|
||||
@@ -4,56 +4,63 @@
|
||||
android:title="@string/menu_settings">
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_units"
|
||||
android:key="@string/settings_defaults_key"
|
||||
android:title="@string/settings_defaults_title"
|
||||
android:summary="@string/settings_defaults_summary"
|
||||
android:icon="@drawable/ic_units" />
|
||||
android:title="@string/settings_defaults_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_ui"
|
||||
android:key="@string/settings_ui_key"
|
||||
android:title="@string/settings_ui_title"
|
||||
android:summary="@string/settings_ui_summary"
|
||||
android:icon="@drawable/ic_ui" />
|
||||
android:title="@string/settings_ui_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_satellite_alt_24"
|
||||
android:key="@string/settings_gps_key"
|
||||
android:title="@string/settings_gps_title"
|
||||
android:summary="@string/settings_gps_summary"
|
||||
android:icon="@drawable/ic_baseline_satellite_alt_24" />
|
||||
android:title="@string/settings_gps_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_sensors_24"
|
||||
android:key="@string/settings_sensors_key"
|
||||
android:title="@string/settings_sensors_title"
|
||||
android:summary="@string/settings_sensors_summary"
|
||||
android:icon="@drawable/ic_baseline_sensors_24" />
|
||||
android:title="@string/settings_sensors_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_volume_up_24"
|
||||
android:key="@string/settings_announcements_key"
|
||||
android:title="@string/settings_announcements_title"
|
||||
android:summary="@string/settings_announcements_summary"
|
||||
android:icon="@drawable/ic_baseline_volume_up_24" />
|
||||
android:title="@string/settings_announcements_title" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_import_export_24"
|
||||
android:key="@string/settings_import_export_key"
|
||||
android:title="@string/settings_import_export_title"
|
||||
android:summary="@string/settings_import_export_summary"
|
||||
android:icon="@drawable/ic_baseline_import_export_24" />
|
||||
android:title="@string/settings_import_export_title" />
|
||||
|
||||
<de.dennisguse.opentracks.settings.ResetDialogPreference
|
||||
android:dialogMessage="@string/settings_reset_confirm_message"
|
||||
android:dialogTitle="@string/settings_reset_confirm_title"
|
||||
android:icon="@drawable/ic_baseline_autorenew_24"
|
||||
android:key="@string/settings_reset_key"
|
||||
android:negativeButtonText="@android:string/cancel"
|
||||
android:persistent="false"
|
||||
android:positiveButtonText="@android:string/ok"
|
||||
android:title="@string/settings_all_reset"
|
||||
android:summary="@string/settings_reset_summary"
|
||||
android:icon="@drawable/ic_baseline_autorenew_24"/>
|
||||
android:title="@string/settings_all_reset" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:title="@string/settings_public_api_enabled_title"
|
||||
android:summaryOn="@string/settings_public_api_enabled_summary_on"
|
||||
android:summaryOff="@string/settings_public_api_enabled_summary_off"
|
||||
android:defaultValue="@bool/publicapi_enabled_default"
|
||||
android:key="@string/publicapi_enabled_key" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_baseline_info_24"
|
||||
android:key="@string/settings_open_tracks_key"
|
||||
android:title="@string/settings_open_tracks_title"
|
||||
android:summary="@string/settings_open_tracks_summary"
|
||||
android:icon="@drawable/ic_baseline_info_24" />
|
||||
android:title="@string/settings_open_tracks_title" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
Reference in New Issue
Block a user