Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
819effb
Add HTTP upload sender and worker
ardenn Mar 17, 2026
14531f1
Add HTTP upload settings and preferences UI
ardenn Mar 17, 2026
d8ca19f
Wire HTTP upload into main navigation and actions
ardenn Mar 17, 2026
78074b2
Add HTTP upload manager unit tests
ardenn Mar 17, 2026
6f3fae1
Restore SO link
ardenn Mar 17, 2026
d8ad089
Test that two trkseg elements are written in the GPX file
mendhak Mar 31, 2026
e453209
v136-rc1
mendhak Mar 31, 2026
9b6bb9a
Translated using Weblate (Galician)
mbouzada Dec 6, 2025
9e8c3cb
Translated using Weblate (Japanese)
LinerSeven Dec 6, 2025
c7ae2ea
Translated using Weblate (Hungarian)
BLaszlo001 Dec 6, 2025
e21511a
Translated using Weblate (Slovak)
Marian-SK Dec 6, 2025
db89c32
Translated using Weblate (Hungarian)
BLaszlo001 Dec 11, 2025
26d8bff
Translated using Weblate (Catalan)
Dec 15, 2025
641132c
Translated using Weblate (German)
Mr-Update Dec 27, 2025
3fd802d
Translated using Weblate (German)
Mr-Update Dec 27, 2025
34b9515
Translated using Weblate (German)
Mr-Update Dec 27, 2025
41e3a85
Translated using Weblate (German)
Mr-Update Dec 27, 2025
843e9c7
Translated using Weblate (German)
Mr-Update Dec 27, 2025
593708b
Translated using Weblate (German)
Mr-Update Dec 28, 2025
6394340
Translated using Weblate (German)
Mr-Update Jan 12, 2026
8ad6c64
Translated using Weblate (Japanese)
LinerSeven Jan 25, 2026
598f820
Translated using Weblate (Slovak)
Marian-SK Jan 25, 2026
2741490
Translated using Weblate (Japanese)
LinerSeven Jan 27, 2026
05176d7
Translated using Weblate (Slovak)
Marian-SK Jan 31, 2026
c398704
Translated using Weblate (Hungarian)
BLaszlo001 Feb 10, 2026
bc6d70c
Translated using Weblate (Spanish (Colombia))
SGalvisD Feb 17, 2026
6e35bec
Translated using Weblate (Portuguese (Brazil))
caduaraxa Feb 19, 2026
b075fef
Translated using Weblate (Portuguese (Brazil))
caduaraxa Feb 19, 2026
a1e76d6
Translated using Weblate (German)
Mr-Update Feb 27, 2026
004c070
Translated using Weblate (Korean)
Mar 14, 2026
ed07035
Translated using Weblate (Tamil)
TamilNeram Mar 15, 2026
ab9ba0a
Translated using Weblate (Tamil)
TamilNeram Mar 15, 2026
b2ae8de
Add UI and strings for significant motion bypass interval
ardenn Mar 19, 2026
ef4ab69
Add significant motion bypass interval to preferences logic
ardenn Mar 19, 2026
3369c58
Implement settings fragment for significant motion bypass interval
ardenn Mar 19, 2026
712022c
Add logic to occasionally bypass significant motion check
ardenn Mar 19, 2026
340f36c
Fix formatting
ardenn Mar 19, 2026
9523afe
Logging that the bypass interval has passed in debug level
mendhak Apr 1, 2026
c43242d
Disable the bypass preference if the significant motion sensor doesn'…
mendhak Apr 1, 2026
6afe1a0
Merge remote-tracking branch 'origin/master' into milestone136
mendhak Apr 1, 2026
37fc9c8
Rename HTTP Upload to HTTP File Upload
ardenn Apr 1, 2026
acef804
Fix mock
ardenn Apr 1, 2026
b199eb2
More renames
ardenn Apr 1, 2026
6596287
Add HTTP headers example
ardenn Apr 1, 2026
e25d682
Merge remote-tracking branch 'origin/milestone136' into ardenn-http-f…
mendhak Apr 2, 2026
0b745d1
Merge pull request #1280 from ardenn/ardenn/http-upload-sender
mendhak Apr 2, 2026
33b49f8
Changelog for v136
mendhak Apr 2, 2026
450085a
trkseg bugfix
mendhak Apr 2, 2026
ee995d4
Bugfix: For the on-every-start filename, don't create a new filename …
mendhak Apr 12, 2026
deba137
Merge remote-tracking branch 'origin/master' into milestone136
mendhak Apr 20, 2026
107b33f
OwnCloud validation improvement check. Issue #1263
mendhak Apr 20, 2026
36ae7b2
Better check for whether auto senders are available or not. Issue #1263
mendhak Apr 20, 2026
6ba7de6
If no loggers are enabled, show an error dialog.
mendhak Apr 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/136.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* HTTP File Upload Target (separate from normal Custom URL logger).
* Significant motion heartbeat interval setting for long durations.
* Fixed bug where GPX track segments were not being created correctly.
4 changes: 2 additions & 2 deletions gpslogger/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ android {

targetSdkVersion 35
compileSdk 35
versionCode 135
versionName "135"
versionCode 136
versionName "136-rc1"

// Used by AppAuth-Android
manifestPlaceholders = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ private void handleIntent(Intent intent) {
preferenceHelper.setPassiveFilterInterval(passiveFilterInterval);
needToStartGpsManager = true;
}

if(bundle.get(IntentConstants.LOG_ONCE) != null){
boolean logOnceIntent = bundle.getBoolean(IntentConstants.LOG_ONCE);
LOG.debug("Intent received - Log Once: " + String.valueOf(logOnceIntent));
Expand Down Expand Up @@ -435,7 +435,9 @@ protected void startLogging() {
showNotification();
setupAutoSendTimers();
setupSignificantMotionSensor();
resetCurrentFileName(true);

resetCurrentFileName(Strings.isNullOrEmpty(session.getCurrentFormattedFileName()));

notifyClientsStarted(true);
startPassiveManager();
startGpsManager();
Expand Down Expand Up @@ -806,8 +808,19 @@ private boolean userHasBeenStillForTooLong() {
if(!preferenceHelper.shouldLogOnlyIfSignificantMotion()){
return false;
}
return !session.hasDescription() && !session.isSinglePointMode() &&

boolean hasBeenStill = !session.hasDescription() && !session.isSinglePointMode() &&
(session.getUserStillSinceTimeStamp() > 0 && (System.currentTimeMillis() - session.getUserStillSinceTimeStamp()) > (preferenceHelper.getMinimumLoggingInterval() * 1000));

if (hasBeenStill && preferenceHelper.getSignificantMotionBypassInterval() >= 1) {
long bypassIntervalInMillis = preferenceHelper.getSignificantMotionBypassInterval() * 60 * 1000L;
if (System.currentTimeMillis() - session.getLatestTimeStamp() >= bypassIntervalInMillis) {
LOG.debug("Significant motion bypass interval passed, so let's allow a point to be logged.");
return false;
}
}

return hasBeenStill;
}

private void startAbsoluteTimer() {
Expand Down Expand Up @@ -1243,7 +1256,13 @@ private void setAlarmForNextPoint() {
* @param loc Location object
*/
private void writeToFile(Location loc) {
session.setAddNewTrackSegment(false);
//session.setAddNewTrackSegment(false);

if(FileLoggerFactory.getFileLoggers(getApplicationContext()).isEmpty()){
Systems.showErrorNotification(getApplicationContext(),
String.format("%s %s", getString(R.string.summary_loggingto), getString(R.string.summary_loggingto_screen)));
return;
}

try {
LOG.debug("Calling file writers");
Expand All @@ -1259,6 +1278,7 @@ private void writeToFile(Location loc) {
Systems.showErrorNotification(this, getString(R.string.could_not_write_to_file));
}

session.setAddNewTrackSegment(false);
session.clearDescription();
EventBus.getDefault().post(new ServiceEvents.AnnotationStatus(true));
}
Expand Down
42 changes: 40 additions & 2 deletions gpslogger/src/main/java/com/mendhak/gpslogger/GpsMainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,7 @@ public boolean onProfileLongClick(View view, final IProfile iProfile, boolean b)

materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.pref_autosend_title, R.string.pref_autosend_summary, R.drawable.autosend, 1003));
materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.log_customurl_setup_title, null, R.drawable.customurlsender, 1020));
materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.http_file_upload_setup_title, null, R.drawable.customurlsender, 1021));
materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.dropbox_setup_title, null, R.drawable.dropbox, 1005));
materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.google_drive_setup_title, null, R.drawable.googledrive, 1011));
materialDrawer.addItem(GpsLoggerDrawerItem.newPrimary(R.string.sftp_setup_title, null, R.drawable.sftp, 1015));
Expand Down Expand Up @@ -905,6 +906,9 @@ public boolean onItemClick(View view, int i, IDrawerItem iDrawerItem) {
case 1020:
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.CUSTOMURL);
break;
case 1021:
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.HTTPFILEUPLOAD);
break;
case 9000:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://gpslogger.app")));
break;
Expand Down Expand Up @@ -1231,6 +1235,7 @@ public boolean onMenuItemClick(MenuItem item) {
return true;
case R.id.mnuAutoSendNow:
forceAutoSendNow();
return true;
case R.id.mnuOwnCloud:
uploadToOwnCloud();
return true;
Expand All @@ -1240,6 +1245,9 @@ public boolean onMenuItemClick(MenuItem item) {
case R.id.mnuCustomUrl:
uploadToCustomURL();
return true;
case R.id.mnuHttpFileUpload:
uploadToHttpFileUpload();
return true;
default:
return true;
}
Expand All @@ -1250,8 +1258,12 @@ private void forceAutoSendNow() {
LOG.debug("User forced an auto send");

if (preferenceHelper.isAutoSendEnabled()) {
Dialogs.progress(this, getString(R.string.autosend_sending));
EventBus.getDefault().post(new CommandEvents.AutoSend(null));
if (FileSenderFactory.getAvailableFileAutoSenders().isEmpty()) {
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.UPLOAD);
} else {
Dialogs.progress(this, getString(R.string.autosend_sending));
EventBus.getDefault().post(new CommandEvents.AutoSend(null));
}

} else {
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.UPLOAD);
Expand Down Expand Up @@ -1321,6 +1333,15 @@ private void uploadToCustomURL(){
showFileListDialog(FileSenderFactory.getCustomUrlSender());
}

private void uploadToHttpFileUpload(){
if(!FileSenderFactory.getHttpFileUploadSender().isAvailable()){
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.HTTPFILEUPLOAD);
return;
}

showFileListDialog(FileSenderFactory.getHttpFileUploadSender());
}

private void uploadToSFTP(){
if(!FileSenderFactory.getSFTPSender().isAvailable()){
launchPreferenceScreen(MainPreferenceActivity.PREFERENCE_FRAGMENTS.SFTP);
Expand Down Expand Up @@ -1610,6 +1631,23 @@ public void onEventMainThread(UploadEvents.CustomUrl upload){
}
}

@EventBusHook
public void onEventMainThread(UploadEvents.HttpFileUpload upload){
LOG.debug("HTTP File Upload Event completed, success: " + upload.success);
Dialogs.hideProgress();

if(!upload.success){
LOG.error(getString(R.string.http_file_upload_setup_title)
+ "-"
+ getString(R.string.upload_failure));

if(userInvokedUpload){
Dialogs.showError(getString(R.string.sorry), getString(R.string.upload_failure), upload.message, upload.throwable, this);
userInvokedUpload = false;
}
}
}

@EventBusHook
public void onEventMainThread(UploadEvents.AutoEmail upload){
LOG.debug("Auto Email Event completed, success: " + upload.success);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ protected void onCreate(Bundle savedInstanceState) {
setTitle(R.string.sftp_setup_title);
preferenceFragmentCompat = new SFTPSettingsFragment();
break;
case PREFERENCE_FRAGMENTS.HTTPFILEUPLOAD:
setTitle(R.string.http_file_upload_setup_title);
preferenceFragmentCompat = new HttpFileUploadSettingsFragment();
break;
}

getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, preferenceFragmentCompat).commit();
Expand Down Expand Up @@ -190,6 +194,7 @@ public static class PREFERENCE_FRAGMENTS {
public static final String OWNCLOUD = "OwnCloudAuthorizationFragment";
public static final String OSM = "OSMAuthorizationFragment";
public static final String SFTP = "SFTPSettingsFragment";
public static final String HTTPFILEUPLOAD = "HttpFileUploadSettingsFragment";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ public int getAbsoluteTimeoutForAcquiringPosition() {
public void setAbsoluteTimeoutForAcquiringPosition(int absoluteTimeout) {
prefs.edit().putString(PreferenceNames.ABSOLUTE_TIMEOUT, String.valueOf(absoluteTimeout)).apply();
}

/**
* Reduce redundant passive location updates by adjusting the minimum collection interval (in seconds).
*/
Expand Down Expand Up @@ -720,6 +720,64 @@ public boolean shouldLogToOpenGTS() {
}


@ProfilePreference(name=PreferenceNames.AUTOSEND_HTTPFILEUPLOAD_ENABLED)
public boolean isHttpFileUploadAutoSendEnabled() {
return prefs.getBoolean(PreferenceNames.AUTOSEND_HTTPFILEUPLOAD_ENABLED, false);
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_URL)
public String getHttpFileUploadUrl() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_URL, "");
}

public void setHttpFileUploadUrl(String url) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_URL, url).apply();
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_METHOD)
public String getHttpFileUploadMethod() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_METHOD, "POST");
}

public void setHttpFileUploadMethod(String method) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_METHOD, method).apply();
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_HEADERS)
public String getHttpFileUploadHeaders() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_HEADERS, "");
}

public void setHttpFileUploadHeaders(String headers) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_HEADERS, headers).apply();
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_USERNAME)
public String getHttpFileUploadUsername() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_USERNAME, "");
}

public void setHttpFileUploadUsername(String username) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_USERNAME, username).apply();
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_PASSWORD)
public String getHttpFileUploadPassword() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_PASSWORD, "");
}

public void setHttpFileUploadPassword(String password) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_BASICAUTH_PASSWORD, password).apply();
}

@ProfilePreference(name=PreferenceNames.HTTPFILEUPLOAD_BODY_TYPE)
public String getHttpFileUploadBodyType() {
return prefs.getString(PreferenceNames.HTTPFILEUPLOAD_BODY_TYPE, "form-data");
}

public void setHttpFileUploadBodyType(String bodyType) {
prefs.edit().putString(PreferenceNames.HTTPFILEUPLOAD_BODY_TYPE, bodyType).apply();
}


@ProfilePreference(name=PreferenceNames.LOG_PASSIVE_LOCATIONS)
Expand Down Expand Up @@ -1246,6 +1304,20 @@ public void setShouldLogOnlyIfSignificantMotion(boolean value){
prefs.edit().putBoolean(PreferenceNames.ONLY_LOG_IF_SIGNIFICANT_MOTION, value).apply();
}

@ProfilePreference(name= PreferenceNames.SIGNIFICANT_MOTION_BYPASS_INTERVAL)
public int getSignificantMotionBypassInterval() {
try{
return Integer.parseInt(prefs.getString(PreferenceNames.SIGNIFICANT_MOTION_BYPASS_INTERVAL, "0"));
}
catch(Exception e){
return 0;
}
}

public void setSignificantMotionBypassInterval(int value){
prefs.edit().putString(PreferenceNames.SIGNIFICANT_MOTION_BYPASS_INTERVAL, String.valueOf(value)).apply();
}

@SuppressWarnings("unchecked")
public void savePropertiesFromPreferences(File f) throws IOException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ public class PreferenceNames {
public static final String LOG_TO_URL_BASICAUTH_PASSWORD = "log_customurl_basicauth_password";
public static final String LOG_TO_URL_DISCARD_OFFLINE_LOCATIONS_ENABLED = "log_customurl_discard_offline_locations_enabled";
public static final String AUTOSEND_CUSTOMURL_ENABLED = "autocustomurl_enabled";

public static final String AUTOSEND_HTTPFILEUPLOAD_ENABLED = "autohttpfileupload_enabled";
public static final String HTTPFILEUPLOAD_URL = "httpfileupload_url";
public static final String HTTPFILEUPLOAD_METHOD = "httpfileupload_method";
public static final String HTTPFILEUPLOAD_HEADERS = "httpfileupload_headers";
public static final String HTTPFILEUPLOAD_BASICAUTH_USERNAME = "httpfileupload_basicauth_username";
public static final String HTTPFILEUPLOAD_BASICAUTH_PASSWORD = "httpfileupload_basicauth_password";
public static final String HTTPFILEUPLOAD_BODY_TYPE = "httpfileupload_body_type";

public static final String LOG_TO_OPENGTS = "log_opengts";
public static final String LOG_PASSIVE_LOCATIONS="log_passive_locations";
public static final String LOG_SATELLITE_LOCATIONS = "log_satellite_locations";
Expand Down Expand Up @@ -148,5 +157,6 @@ public static enum DegreesDisplayFormat {
public static final String ANNOTATIONS_BUTTON_SETTINGS = "annotations_buttons";

public static final String ONLY_LOG_IF_SIGNIFICANT_MOTION = "only_log_if_significant_motion";
public static final String SIGNIFICANT_MOTION_BYPASS_INTERVAL = "significant_motion_bypass_interval";

}
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,6 @@ public static class SFTP extends BaseUploadEvent {
public String fingerprint;
public String hostKey;
}

public static class HttpFileUpload extends BaseUploadEvent {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public static class SenderNames {
public static final String SFTP = "SFTP_SENDER";
public static final String OPENSTREETMAP = "OSM_SENDER";
public static final String CUSTOMURL = "CUSTOM_URL_SENDER";
public static final String HTTPFILEUPLOAD = "HTTP_FILE_UPLOAD_SENDER";
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.mendhak.gpslogger.senders.email.AutoEmailManager;
import com.mendhak.gpslogger.senders.ftp.FtpManager;
import com.mendhak.gpslogger.senders.googledrive.GoogleDriveManager;
import com.mendhak.gpslogger.senders.http.HttpFileUploadManager;
import com.mendhak.gpslogger.senders.opengts.OpenGTSManager;
import com.mendhak.gpslogger.senders.osm.OpenStreetMapManager;
import com.mendhak.gpslogger.senders.owncloud.OwnCloudManager;
Expand Down Expand Up @@ -80,6 +81,10 @@ public static FileSender getCustomUrlSender(){
return new CustomUrlManager(PreferenceHelper.getInstance());
}

public static FileSender getHttpFileUploadSender() {
return new HttpFileUploadManager(PreferenceHelper.getInstance());
}

public static void autoSendFiles(final String fileToSend) {

PreferenceHelper preferenceHelper = PreferenceHelper.getInstance();
Expand Down Expand Up @@ -164,6 +169,8 @@ public static FileSender getSenderByName(String senderName) {
return getSFTPSender();
case FileSender.SenderNames.CUSTOMURL:
return getCustomUrlSender();
case FileSender.SenderNames.HTTPFILEUPLOAD:
return getHttpFileUploadSender();
default:
return null;

Expand All @@ -181,10 +188,11 @@ private static List<FileSender> getAllFileSenders(){
senders.add(getOwnCloudSender());
senders.add(getSFTPSender());
senders.add(getCustomUrlSender());
senders.add(getHttpFileUploadSender());
return senders;
}

private static List<FileSender> getAvailableFileAutoSenders() {
public static List<FileSender> getAvailableFileAutoSenders() {

List<FileSender> senders = new ArrayList<>();

Expand Down Expand Up @@ -224,6 +232,10 @@ private static List<FileSender> getAvailableFileAutoSenders() {
senders.add(getCustomUrlSender());
}

if(getHttpFileUploadSender().isAutoSendAvailable()){
senders.add(getHttpFileUploadSender());
}

return senders;

}
Expand Down
Loading
Loading