Skip to content

feat: Added Notifications to app - #183

Draft
JKFerland wants to merge 1 commit into
FoggedLens:mainfrom
JKFerland:add-notifications
Draft

feat: Added Notifications to app#183
JKFerland wants to merge 1 commit into
FoggedLens:mainfrom
JKFerland:add-notifications

Conversation

@JKFerland

Copy link
Copy Markdown

Proximity alerts: fire while the app is backgrounded

Brought to you by Claude ™️

Proximity alerts previously only worked with the app open on screen, and on iOS
they never fired at all. This fixes both.

New permissions / entitlements

This PR declares new platform capabilities. Both are worth a look during review.

iOS (ios/Runner/Info.plist)

  • UIBackgroundModeslocation — new key. Without it iOS suspends the app the moment it leaves the screen, which stops the CoreLocation stream and makes a backgrounded alert impossible. This is the
    entitlement that triggers App Store review scrutiny on background location, so expect to justify it.
  • NSLocationAlwaysUsageDescription — new usage string covering the background case. NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription were already present and
    are unchanged.
  • No new runtime authorization is requested — the app still asks for When In Use, which combined with the background mode is enough to keep receiving updates while backgrounded.

Android (android/app/src/main/AndroidManifest.xml)

  • FOREGROUND_SERVICE — required to run geolocator's GeolocatorLocationService, which is what keeps location flowing while backgrounded.
  • FOREGROUND_SERVICE_LOCATION — required from Android 14 onward for a foreground service of type location.
  • WAKE_LOCK — without it the system sleeps and delivers queued positions in one burst on wake, far too late to warn anyone about a device they already drove past.
  • ACCESS_BACKGROUND_LOCATION is deliberately not declared — see the Android section below for why.
  • ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, POST_NOTIFICATIONS and INTERNET were already declared and are unchanged.

Changes

Background operation

  • Added the location background mode to Info.plist. Without it iOS suspends the app the moment it leaves the screen, which stops the CoreLocation stream and makes a backgrounded alert
    impossible.
  • Switched the iOS position stream to AppleSettings with allowBackgroundLocationUpdates. It's armed only while the user has proximity alerts switched on, so everyone else keeps the old
    foreground-only behavior and no blue status bar pill.
  • Set pauseLocationUpdatesAutomatically: false. iOS otherwise pauses updates once it decides you've stopped moving and never reliably resumes them, silently killing alerts mid-trip.
  • Nearby-node lookup now boxes around the live GPS position instead of the map camera's visibleBounds. The camera is frozen wherever you left it while backgrounded, so a viewport lookup returned
    nodes from wherever you were miles ago — this also fixes missed alerts in the foreground when the map is panned away from you.
  • Pull a fresh fix on app resume. The position stream can stay silent across suspension, leaving the app evaluating alerts against a stale location.

iOS notifications (previously fully broken)

  • Registered UNUserNotificationCenter.delegate in AppDelegate. flutter_local_notifications implements willPresent but never registers itself, so iOS was silently suppressing every foreground
    notification.
  • Stopped gating notifications on initialize()'s return value. On iOS that reports the outcome of the permission request — which we intentionally disable — so it returned false even on success
    and left every notification path dead.
  • Added presentBanner/presentList to the Darwin notification details. presentAlert alone is dead on iOS 14+, where the plugin only consults the other two, so no banner ever appeared.
  • Fold node IDs into a signed 32-bit range for notification IDs. OSM node IDs are past 12 billion, and passing one through threw ArgumentError and dropped the notification entirely.
  • areNotificationsEnabled() now actually asks iOS instead of returning a blind true. The settings UI previously couldn't tell whether notifications were authorized.
  • Added an "Open Settings" fallback dialog when permission is refused. iOS shows its permission prompt exactly once ever, so re-requesting is a no-op and the system settings app is the only
    remaining path. Localized across all 11 locales.

Tests

  • Added test/services/geo_bounds_test.dart. Covers the location-boxing math in real meters, including the cos(latitude) longitude widening and clamping at the poles and antimeridian.
  • Added test/services/notification_id_test.dart. Pins the 32-bit contract against real OSM node IDs, negative (not-yet-uploaded) IDs, and determinism so a repeat alert replaces rather than stacks.

Video

bob.mov

Platform coverage — iOS only

This was tested on iOS only. The Android path is unverified.

@reb1995 reb1995 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worked on hardware with this change.

Image Image

/// background delivery is armed (or dropped) immediately rather than at the
/// next unrelated stream restart.
void updateProximityAlertsEnabled(bool enabled) {
if (_positionSub == null || _streamIsBackgroundCapable == enabled) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to change this line to the below. Otherwise, the foreground location notification never showed up on a real device.

if (_streamIsBackgroundCapable == enabled) return;

@reb1995

reb1995 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Also, do we want to change the title/description to something specifying that it is constant location access and proximity alerts?

@reb1995

reb1995 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Was able to test in the real world. Found an issue. The proximity alerts only when trigger on known nodes. If you open the and the zoom is tighter than your drive, you will never alert on new nodes. The location tracking logic works, but alerts do not work. Opening the app from the background will correctly display your current location, refresh the data, and then instantly alerts.

We need to refresh node data in the background as well, but at a reasonable rate so we don't DDOS anybody.

@reb1995

reb1995 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Opened up a pull on @JKFerland's feature branch that should solve these issues and make it complete as far as Android is concerned. Basically, 5km of data is downloaded at once. If we come within 1km of that bounding area, we update with another 5km square of data. This is done in the background based on our location.

JKFerland#1

@stopflock

Copy link
Copy Markdown
Collaborator

What's the status on this? Still draft? Ready for review? How much testing has been done?
Would like to get this in for the next release if we can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants