Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ local.properties
app/release/
app/debug/
app/build/
.sdd/
build/
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ An Android app that generates GPX files with points of interest around given coo
| **iNaturalist** | Species not yet observed by the user within ±15 days of today | Not required |
| **Need a photo** | Wikidata objects without photos, useful for photo-mapping routes | Not required |

### Track Corridor (OsmAnd integration)

Discover POIs along a section of a GPX track loaded in OsmAnd. The app connects to OsmAnd via AIDL, lets you pick an active track, define a start/end distance (km) and corridor width (m), then runs existing POI sources inside that corridor. The resulting GPX can be sent back to OsmAnd or shared.

**Requirements**: OsmAnd or OsmAnd+ installed on the device.

## Requirements

- Android 9 (API 28) or higher
Expand Down Expand Up @@ -51,20 +57,29 @@ Default exclusions for **Need a photo**:

## Usage

### POI generation by coordinates

1. Enter coordinates in the `lat,lng` field, tap **Current**, or pick a point on the map.
2. Select one or more data sources.
3. Optionally tap the **color dot** next to any source to change its color in the palette — the chosen color is saved and applied to all waypoints from that source in the output file.
4. After generation the app will prompt you to open the file in an external app (e.g. OsmAnd, Locus Map).

### Track Corridor (OsmAnd)

1. Tap the **route icon** (↗) in the toolbar to open the Track Corridor screen.
2. Tap **Get Tracks from OsmAnd** — the app connects to OsmAnd and lists active/imported tracks.
3. Select a track. If it's the first time, you'll be asked to pick the corresponding GPX file from device storage (the mapping is cached for next time).
4. Enter **Start distance** (km), **End distance** (km), and **Corridor width** (m).
5. Tap **Generate** — the app extracts the track segment, computes a bounding box expanded by the corridor width, and runs POI discovery using your enabled sources.
6. After generation, tap **Send to OsmAnd** to import the result GPX directly, or **Share** to send it via the standard Android chooser.

Generated files are saved to `Android/data/com.example.googleAttractionsGpx/files/`.

## Architecture

```
presentation/ — Compose UI (MainActivity, SettingsScreen)
domain/ — models (PointData, Coordinates) and interfaces (IGpxGenerator, SettingsRepository)
data/repository — generator implementations and SettingsRepositoryImpl
```
See [docs/architecture.md](docs/architecture.md) for the full project structure.

See [docs/track-corridor-workflow.md](docs/track-corridor-workflow.md) for the Track Corridor workflow diagram.

## Build

Expand Down
5 changes: 3 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ android {
applicationId = "com.example.googleAttractionsGpx"
minSdk = 28
targetSdk = 35
versionCode = 1
versionName = project.findProperty("versionName")?.toString() ?: "1.0.0"
versionCode = 5
versionName = project.findProperty("versionName")?.toString() ?: "1.4.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -46,6 +46,7 @@ android {
}
buildFeatures {
compose = true
aidl = true
}
}

Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@
</provider>
</application>

<queries>
<package android:name="net.osmand" />
<package android:name="net.osmand.plus" />
</queries>

</manifest>
204 changes: 204 additions & 0 deletions app/src/main/aidl/net/osmand/aidlapi/IOsmAndAidlInterface.aidl
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package net.osmand.aidlapi;

import android.os.Bundle;
import android.os.IBinder;
import net.osmand.aidlapi.gpx.ASelectedGpxFile;
import net.osmand.aidlapi.gpx.AGpxFile;
import net.osmand.aidlapi.gpx.ImportGpxParams;

interface IOsmAndAidlInterface {
// 1
boolean addMapMarker(in Bundle params);
// 2
boolean removeMapMarker(in Bundle params);
// 3
Comment thread
adbuker marked this conversation as resolved.
boolean updateMapMarker(in Bundle params);
// 4
boolean addMapWidget(in Bundle params);
// 5
boolean removeMapWidget(in Bundle params);
// 6
boolean updateMapWidget(in Bundle params);
// 7
boolean addMapPoint(in Bundle params);
// 8
boolean removeMapPoint(in Bundle params);
// 9
boolean updateMapPoint(in Bundle params);
// 10
boolean addMapLayer(in Bundle params);
// 11
boolean removeMapLayer(in Bundle params);
// 12
boolean updateMapLayer(in Bundle params);
// 13
boolean importGpx(in ImportGpxParams params);
// 14
boolean showGpx(in Bundle params);
// 15
boolean hideGpx(in Bundle params);
// 16
boolean getActiveGpx(out List<ASelectedGpxFile> files);
// 17
boolean setMapLocation(in Bundle params);
// 18
boolean calculateRoute(in Bundle params);
// 19
boolean refreshMap();
// 20
boolean addFavoriteGroup(in Bundle params);
// 21
boolean removeFavoriteGroup(in Bundle params);
// 22
boolean updateFavoriteGroup(in Bundle params);
// 23
boolean addFavorite(in Bundle params);
// 24
boolean removeFavorite(in Bundle params);
// 25
boolean updateFavorite(in Bundle params);
// 26
boolean startGpxRecording(in Bundle params);
// 27
boolean stopGpxRecording(in Bundle params);
// 28
boolean takePhotoNote(in Bundle params);
// 29
boolean startVideoRecording(in Bundle params);
// 30
boolean startAudioRecording(in Bundle params);
// 31
boolean stopRecording(in Bundle params);
// 32
boolean navigate(in Bundle params);
// 33
boolean navigateGpx(inout Bundle params);
// 34
boolean removeGpx(in Bundle params);
// 35
boolean showMapPoint(in Bundle params);
// 36
boolean setNavDrawerItems(in Bundle params);
// 37
boolean pauseNavigation(in Bundle params);
// 38
boolean resumeNavigation(in Bundle params);
// 39
boolean stopNavigation(in Bundle params);
// 40
boolean muteNavigation(in Bundle params);
// 41
boolean unmuteNavigation(in Bundle params);
// 42
boolean search(in Bundle params, IBinder callback);
// 43
boolean navigateSearch(in Bundle params);
// 44
long registerForUpdates(in long updateTimeMS, IBinder callback);
// 45
boolean unregisterFromUpdates(in long callbackId);
// 46
boolean setNavDrawerLogo(in String imageUri);
// 47
boolean setEnabledIds(in List<String> ids);
// 48
boolean setDisabledIds(in List<String> ids);
// 49
boolean setEnabledPatterns(in List<String> patterns);
// 50
boolean setDisabledPatterns(in List<String> patterns);
// 51
boolean regWidgetVisibility(in Bundle params);
// 52
boolean regWidgetAvailability(in Bundle params);
// 53
boolean customizeOsmandSettings(in Bundle params);
// 54
boolean getImportedGpx(out List<AGpxFile> files);
// 55
boolean getSqliteDbFiles(out List<Bundle> files);
// 56
boolean getActiveSqliteDbFiles(out List<Bundle> files);
// 57
boolean showSqliteDbFile(String fileName);
// 58
boolean hideSqliteDbFile(String fileName);
// 59
boolean setNavDrawerLogoWithParams(in Bundle params);
// 60
boolean setNavDrawerFooterWithParams(in Bundle params);
// 61
boolean restoreOsmand();
// 62
boolean changePluginState(in Bundle params);
// 63
boolean registerForOsmandInitListener(IBinder callback);
// 64
boolean getBitmapForGpx(in Bundle file, IBinder callback);
// 65
int copyFile(in Bundle filePart);
// 66
long registerForNavigationUpdates(in Bundle params, IBinder callback);
// 67
long addContextMenuButtons(in Bundle params, IBinder callback);
// 68
boolean removeContextMenuButtons(in Bundle params);
// 69
boolean updateContextMenuButtons(in Bundle params);
// 70
boolean areOsmandSettingsCustomized(in Bundle params);
// 71
boolean setCustomization(in Bundle params);
// 72
long registerForVoiceRouterMessages(in Bundle params, IBinder callback);
// 73
boolean removeAllActiveMapMarkers(in Bundle params);
// 74
boolean importProfile(in Bundle params);
// 75
boolean executeQuickAction(in Bundle params);
// 76
boolean getQuickActionsInfo(out List<Bundle> quickActions);
// 77
boolean setLockState(in Bundle params);
// 78
long registerForKeyEvents(in Bundle params, IBinder callback);
// 79
Bundle getAppInfo();
// 80
boolean setMapMargins(in Bundle params);
// 81
boolean exportProfile(in Bundle params);
// 82
boolean isFragmentOpen();
// 83
boolean isMenuOpen();
// 84
int getPluginVersion(in Bundle params);
// 85
boolean selectProfile(in Bundle params);
// 86
boolean getProfiles(out List<Bundle> profiles);
// 87
boolean getBlockedRoads(out List<Bundle> blockedRoads);
// 88
boolean addRoadBlock(in Bundle params);
// 89
boolean removeRoadBlock(in Bundle params);
// 90
boolean setLocation(in Bundle params);
// 91
boolean exitApp(in Bundle params);
// 92
boolean getText(inout Bundle params);
// 93
boolean reloadIndexes();
// 94
boolean setPreference(in Bundle params);
// 95
boolean getPreference(inout Bundle params);
// 96
long registerForLogcatMessages(in Bundle params, IBinder callback);
// 97
boolean setZoomLimits(in Bundle params);
}
3 changes: 3 additions & 0 deletions app/src/main/aidl/net/osmand/aidlapi/gpx/AGpxFile.aidl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.osmand.aidlapi.gpx;

parcelable AGpxFile;
3 changes: 3 additions & 0 deletions app/src/main/aidl/net/osmand/aidlapi/gpx/AGpxFileDetails.aidl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.osmand.aidlapi.gpx;

parcelable AGpxFileDetails;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.osmand.aidlapi.gpx;

parcelable ASelectedGpxFile;
3 changes: 3 additions & 0 deletions app/src/main/aidl/net/osmand/aidlapi/gpx/ImportGpxParams.aidl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.osmand.aidlapi.gpx;

parcelable ImportGpxParams;
Loading