Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3f0c7e7
Create FUNDING.yml
jamescr Jan 26, 2026
7aa42fe
Feature(CI): Add Signing to nightly APK
jamescr Jan 25, 2026
0c32781
Merge branch 'develop' into 2026.02
jamescr Feb 12, 2026
f2444e6
Possibility to show track of an older hike along with current track.
Mar 1, 2026
10a2df9
1
Mar 1, 2026
214688a
The issue seems to be with the emulator on GitHub?
Mar 1, 2026
51fd8ef
Re-enable first 2 tests
Mar 1, 2026
9a4b062
Re-enable some more tests
Mar 1, 2026
dd37d8b
Re-enable first test of preferences
Mar 1, 2026
967a2f6
first preference test fails, enable second one instead
Mar 1, 2026
6a81698
Check whether we'll see anything in the logs...
Mar 1, 2026
0989cf0
make indentation like it was before
Mar 1, 2026
1f96039
mere presence of logs seems to fix this. Could it be a timing issue?
Mar 1, 2026
172853e
Make file as it was before
Mar 1, 2026
25c41f8
Yes, that log statement is needed
Mar 1, 2026
009e385
Don't need this any longer
Mar 1, 2026
7ec2c5e
Name of intent key for OVERLAID_TRACK_ID more in line with the others
May 16, 2026
982dedf
Merge branch 'labexp:master' into overlay-other
AlainKnaff Aug 9, 2026
e8bd4da
Merge branch 'develop' into overlay-other
AlainKnaff Aug 9, 2026
938c65f
Disable tests to find broken ones
Aug 9, 2026
5b6141c
Make sure overlay table is created on first install
Aug 9, 2026
b8617a4
Disable more tests to find broken ones
Aug 9, 2026
29f9a5e
Re-enable some tests
Aug 9, 2026
9b31231
Disable tests again
Aug 9, 2026
252c396
Re-enable some more tests
Aug 9, 2026
e212f89
Some more tests re-enabled.
Aug 9, 2026
bc625b7
Re-enable some more tests
Aug 9, 2026
144fabe
Re-enable the remaining tests
Aug 9, 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 .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# These are supported funding model platforms
# github: [labexp]
liberapay: OSMTracker
24 changes: 23 additions & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,34 @@ jobs:
distribution: 'temurin'
java-version: '17'

- name: Setup Signing Keystore
run: |
# 1. Decode nightly keystore secret
echo "${{ secrets.NIGHTLY_KEYSTORE }}" | base64 -d > /tmp/nightly-keystore.jks
echo "Keystore created in /tmp/nightly-keystore.jks"

# Verify
echo "βœ… Keystore created in: /tmp/nightly-keystore.jks"
ls -la /tmp/nightly-keystore.jks
echo "ks_path=/tmp/nightly-keystore.jks" >> $GITHUB_OUTPUT


- name: Setup Android SDK
uses: android-actions/setup-android@v2

- name: Build with Gradle
run: ./gradlew assembleDebug --stacktrace
run: |
./gradlew assembleDebug --stacktrace \
-Pandroid.injected.signing.store.file="/tmp/nightly-keystore.jks" \
-Pandroid.injected.signing.store.password="${{ secrets.KEYSTORE_PASSWORD }}" \
-Pandroid.injected.signing.key.alias="${{ secrets.KEY_ALIAS }}" \
-Pandroid.injected.signing.key.password="${{ secrets.KEY_PASSWORD }}"

- name: Cleanup Keystore
run: |
echo "Cleaning keystore..."
rm -f app/nightly-keystore.jks
echo "βœ… Keystore removed"

- name: Rename output APK
run: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.stringContainsInOrder;

import android.util.Log;

import android.content.Context;
import android.content.SharedPreferences;

Expand Down Expand Up @@ -62,6 +64,7 @@ public void tearDown() {
*/
@Test
public void testStorageDirectoryValidatesNonEmpty() {
Log.i("More", "magic");
String keyTitle = context.getString(R.string.prefs_storage_dir);
String defaultValue = OSMTracker.Preferences.VAL_STORAGE_DIR;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,4 @@ private void clickButtonsToDownloadLayout(String layoutName) {

TestUtils.checkToastIsShownWith(TestUtils.getStringResource(R.string.available_layouts_successful_download));
}
}
}
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.TrackPicker"
android:theme="@style/AppTheme"
android:exported="true">
</activity>
<activity
android:name=".activity.TrackLogger"
android:label="@string/tracklogger"
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/java/net/osmtracker/OSMTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,12 @@ public static final class Preferences {
* Key for extra data "uuid" in Intent
*/
public final static String INTENT_KEY_UUID = "uuid";


/**
* Key for extra data "overlaidTrackId" in Intent
*/
public final static String INTENT_KEY_OVERLAID_TRACK_ID = "overlaidTrackId";

/**
* Approximation factor for calculating Horizontal Dilution of Precision
* from location.getAccuracy(). location.getAccuracy() returns an accuracy measured
Expand All @@ -187,4 +192,4 @@ public static final class Preferences {
public static final class Devices {
public static final String NEXUS_S = "Nexus S";
}
}
}
77 changes: 66 additions & 11 deletions app/src/main/java/net/osmtracker/activity/DisplayTrackMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import net.osmtracker.OSMTracker;
import net.osmtracker.R;
import net.osmtracker.db.TrackContentProvider;
import net.osmtracker.db.DataHelper;
import net.osmtracker.overlay.WayPointsOverlay;
import net.osmtracker.overlay.Polylines;

Expand Down Expand Up @@ -100,6 +101,11 @@ public class DisplayTrackMap extends Activity {
*/
private static final long ANIMATION_DURATION_MS = 1000;

/**
* Request Code for picking overlaid track
*/
public final static int RC_PICK_OVERLAID = 1;

/**
* Main OSM view
*/
Expand All @@ -120,6 +126,11 @@ public class DisplayTrackMap extends Activity {
*/
private Polylines polylines;

/**
* OSM view overlay that displays path of other track for comparison
*/
private Polylines polylinesOverlaid;

/**
* OSM view overlay that displays waypoints
*/
Expand All @@ -135,6 +146,11 @@ public class DisplayTrackMap extends Activity {
*/
private long currentTrackId;

/**
* Current overlaid track id
*/
private long overlaidTrackId=0;

/**
* whether the map display should be centered to the gps location
*/
Expand Down Expand Up @@ -185,6 +201,10 @@ public void onCreate(Bundle savedInstanceState) {
currentTrackId = getIntent().getExtras().getLong(TrackContentProvider.Schema.COL_TRACK_ID);
setTitle(getTitle() + ": #" + currentTrackId);

final DataHelper dataHelper = new DataHelper(this);
overlaidTrackId = dataHelper.queryOverlay(currentTrackId,
getContentResolver());

// Initialize OSM view
Configuration.getInstance().load(this, prefs);

Expand Down Expand Up @@ -219,7 +239,7 @@ public void onCreate(Bundle savedInstanceState) {
trackpointContentObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
pathChanged();
pathChanged(polylines, currentTrackId);
}
};

Expand Down Expand Up @@ -299,19 +319,31 @@ private void resumeActivity() {
// setKeepScreenOn depending on user's preferences
osmView.setKeepScreenOn(prefs.getBoolean(OSMTracker.Preferences.KEY_UI_DISPLAY_KEEP_ON, OSMTracker.Preferences.VAL_UI_DISPLAY_KEEP_ON));

// Register content observer for any track point changes
getContentResolver().registerContentObserver(
TrackContentProvider.trackPointsUri(currentTrackId),
true, trackpointContentObserver);
// display "other" track
if(overlaidTrackId != 0) {
// from the database to populate the path layout
lastTrackPointIdProcessed = null;
prevSegmentId = -1;

// Reload path
pathChanged(polylinesOverlaid, overlaidTrackId);
}

// Forget the last waypoint read from the DB
// This ensures that all waypoints for the track will be reloaded
// from the database to populate the path layout
lastTrackPointIdProcessed = null;
prevSegmentId = -1;

// Reload path
pathChanged();
// Register content observer for any track point changes
getContentResolver().registerContentObserver(
TrackContentProvider.trackPointsUri(currentTrackId),
true, trackpointContentObserver);

// Reload path a first time after resume. If
// trackpointObserver was already invoked just now, this becomes
// a no-op
pathChanged(polylines, currentTrackId);

selectTileSource();

Expand All @@ -328,6 +360,7 @@ protected void onPause() {

// Clear the points list.
polylines.clear();
polylinesOverlaid.clear();

super.onPause();
}
Expand Down Expand Up @@ -366,6 +399,13 @@ public boolean onOptionsItemSelected(MenuItem item) {
osmViewController.animateTo(currentPosition);
}
break;
case R.id.displaytrackmap_menu_overlay_other:
// Start track picker activity
Intent i = new Intent(this, TrackPicker.class);
i.putExtra(TrackContentProvider.Schema.COL_TRACK_ID, currentTrackId);
i.putExtra(OSMTracker.INTENT_KEY_OVERLAID_TRACK_ID, overlaidTrackId);
startActivityForResult(i, RC_PICK_OVERLAID);
break;
case R.id.displaytrackmap_menu_settings:
// Start settings activity
startActivity(new Intent(this, Preferences.class));
Expand All @@ -374,6 +414,17 @@ public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}

@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if(requestCode == RC_PICK_OVERLAID &&
resultCode == RESULT_OK) {
overlaidTrackId = data.getLongExtra(OSMTracker.INTENT_KEY_OVERLAID_TRACK_ID,0);
final DataHelper dataHelper = new DataHelper(this);
dataHelper.updateOverlay(currentTrackId,overlaidTrackId);
}
}

@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
Expand All @@ -394,6 +445,7 @@ private void createOverlays() {

// set with to hopefully DPI independent 0.5mm
polylines = new Polylines(Color.BLUE, (float)(metrics.densityDpi / 25.4 / 2), osmView);
polylinesOverlaid = new Polylines(Color.RED, (float)(metrics.densityDpi / 25.4 / 2), osmView);

myLocationOverlay = new SimpleLocationOverlay(this);
osmView.getOverlays().add(myLocationOverlay);
Expand All @@ -411,8 +463,10 @@ private void createOverlays() {
* from {@link #onResume()}, and not the periodic call from
* {@link ContentObserver#onChange(boolean) trackpointContentObserver.onChange(boolean)}
* while recording.
* @param polylines lineset to update
* @param trackId trackid from which to draw lineset
*/
private void pathChanged() {
private synchronized void pathChanged(Polylines polylines, long trackId) {
if (isFinishing()) {
return;
}
Expand All @@ -424,10 +478,11 @@ private void pathChanged() {
boolean doInitialBoundsCalc = false;
double minLat = 91.0, minLon = 181.0;
double maxLat = -91.0, maxLon = -181.0;
if ((!zoomedToTrackAlready) && (lastTrackPointIdProcessed == null)) {
if (trackId == currentTrackId &&
(!zoomedToTrackAlready) && (lastTrackPointIdProcessed == null)) {
final String[] proj_active = {TrackContentProvider.Schema.COL_ACTIVE};
Cursor cursor = getContentResolver().query(
ContentUris.withAppendedId(TrackContentProvider.CONTENT_URI_TRACK, currentTrackId),
ContentUris.withAppendedId(TrackContentProvider.CONTENT_URI_TRACK, trackId),
proj_active, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int colIndex = cursor.getColumnIndex(TrackContentProvider.Schema.COL_ACTIVE);
Expand Down Expand Up @@ -460,7 +515,7 @@ private void pathChanged() {

// Retrieve any points we have not yet seen
Cursor c = getContentResolver().query(
TrackContentProvider.trackPointsUri(currentTrackId),
TrackContentProvider.trackPointsUri(trackId),
projection, selection, selectionArgs, TrackContentProvider.Schema.COL_ID + " asc");

if (c != null) {
Expand Down
33 changes: 29 additions & 4 deletions app/src/main/java/net/osmtracker/activity/TrackListRVAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.graphics.Color;
import android.util.TypedValue;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import net.osmtracker.R;
import net.osmtracker.db.TracklistAdapter;
import net.osmtracker.db.TrackContentProvider;

public class TrackListRVAdapter extends RecyclerView.Adapter<TrackListRVAdapter.TrackItemVH> {

Expand All @@ -36,10 +39,15 @@ public TracklistAdapter getCursorAdapter() {
}

public interface TrackListRecyclerViewAdapterListener {
void onClick(long trackId);
default void onClick(long trackId) {};

void onCreateContextMenu(ContextMenu contextMenu, View view,
ContextMenu.ContextMenuInfo contextMenuInfo, long trackId);
default void onClick(TrackItemVH item, long trackId) {
onClick(trackId);
}
default void initializeItem(TrackItemVH item, long trackId) {
}
}

/**
Expand Down Expand Up @@ -104,9 +112,23 @@ public ImageView getvUploadStatus() {
@Override
public void onClick(View v) {
long trackId = Long.parseLong(getvId().getText().toString());
mHandler.onClick(trackId);
mHandler.onClick(this, trackId);
}

public void activate(boolean state) {
if(state)
itemView.setBackgroundColor(Color.RED);
else {
TypedValue outValue = new TypedValue();
itemView
.getContext()
.getTheme()
.resolveAttribute(android.R.attr.selectableItemBackground,
outValue, true);
itemView.setBackgroundResource(outValue.resourceId);
}
}

@Override
public void onCreateContextMenu(ContextMenu contextMenu, View view, ContextMenu.ContextMenuInfo contextMenuInfo) {
long trackId = Long.parseLong(getvId().getText().toString());
Expand All @@ -130,8 +152,11 @@ public void onBindViewHolder(@NonNull TrackItemVH holder, int position) {
// contents of the view with that element

// Passing the binding operation to cursor loader
cursorAdapter.getCursor().moveToPosition(position);
cursorAdapter.bindView(holder.itemView, context, cursorAdapter.getCursor());
Cursor cursor = cursorAdapter.getCursor();
cursor.moveToPosition(position);
cursorAdapter.bindView(holder.itemView, context, cursor);
mHandler.initializeItem(holder,
cursor.getLong(cursor.getColumnIndex(TrackContentProvider.Schema.COL_ID)));
}

@Override
Expand Down
Loading
Loading