fix: report null instead of fabricated zeros for unavailable location fields - #1104
Open
Lyokone wants to merge 2 commits into
Open
fix: report null instead of fabricated zeros for unavailable location fields#1104Lyokone wants to merge 2 commits into
Lyokone wants to merge 2 commits into
Conversation
Every platform had at least one field where "this fix does not carry that measurement" was indistinguishable from a real reading of zero, due north, stationary, or perfectly accurate. - Android: gate each field on its Location.hasX() companion. - iOS/macOS: map Core Location's negative sentinel to nil for every scalar, not just speed (#741); altitude follows verticalAccuracy, which is what marks it invalid. Skip fixes whose horizontalAccuracy is negative, since that means the coordinate itself is invalid and lat/long are non-nullable. - Windows: omit heading/speed when their IReference is null, and gate altitude on AltitudeAccuracy -- BasicGeoposition.Altitude is a plain double that cannot express "unknown", so Wi-Fi/IP fixes reported sea level. Also forward verticalAccuracy. - Linux: recognise GeoClue2's sentinels (-1 for Speed/Heading/Accuracy, -G_MAXDOUBLE for Altitude) instead of forwarding them, and populate time from the Timestamp property. - Web: normalise non-finite readings to null. The Geolocation spec makes heading NaN, not null, when stationary, and NaN made two identical LocationData compare unequal with unstable hashCodes. Also: isMock/isProducedByAccessory stay null when the platform exposes no such flag rather than defaulting to false, and Android no longer applies a stale NMEA mean-sea-level altitude to a fix that carries none of its own.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every platform had at least one field where "this fix does not carry that measurement" was indistinguishable from a real reading — of zero, due north, stationary, or perfectly accurate.
LocationDatahas always documented these fields asdouble?/ "will be null if not available"; this makes the native side actually honour that.The iOS
speedsentinel fix (#741) covered one field on one platform. This extends the same treatment to every scalar on every platform.Before → after, per platform
0.0fromgetSpeed()/getBearing()/getAccuracy()/… on a fix that carries no such fieldLocation.hasX()horizontalAccuracy,verticalAccuracy,speedAccuracy,course;altitudealways sentnil;altitudefollowsverticalAccuracy, which is what Core Location documents as marking it invalidheading/speedforced to0.0;altitudealways sentIReference<double>is null;altitudegated onAltitudeAccuracy,verticalAccuracynow forwarded-1speed/heading, altitude of-1.797e308timenow populated fromTimestampheadingasNaNwhen stationarynullWindows and Linux matter most in practice: without a GPS radio both position by Wi-Fi/IP, so every fix hit the bad path — Windows reported sea level, Linux reported an altitude 1.8e308 metres below the ellipsoid.
The web case is subtler than a fake zero. The Geolocation spec specifies
headingas NaN, not null, when the device is stationary; sinceNaN != NaN, that made two otherwise identicalLocationDatacompare unequal with unstablehashCodes.Also included
horizontalAccuracyis negative is skipped rather than delivered — Core Location documents that as meaning the coordinate itself is invalid, andlatitude/longitudeare non-nullable, so it cannot be passed on without inventing one.didUpdateLocationstakes the last valid fix in a batch, so this cannot drop an update that had a good fix available.Behaviour change to be aware of
isMockandisProducedByAccessoryare nownullwhen the platform exposes no such flag, instead of defaulting tofalse— "nothing checked" and "checked, and it was not mocked" are different claims. Android now always reportsisMock; Apple reports both on iOS 15.0+/macOS 12.0+; Windows/Linux/web reportnull.Nothing stops compiling — the affected fields were already nullable — but an app that force-unwraps (
data.speed!,data.isMock!) or that treated the old0as a real reading will now see a null. Documented under## Unreleasedin all three changelogs; version bumps left as a separate commit per the usual flow.Verification
compileDebugKotlin+lintDebugNewApi)swiftc -typecheckagainst the engine frameworklocation desktopCIlocation desktopCIflutter analyze, 50 tests,dart formatNew tests cover the sparse-map path (all optionals null) and reported-
0vs absent flags, in both thedoubleshape Android sends and theintshape Apple sends. One existing test asserted the oldisProducedByAccessorydefault offalseand was updated.Not runtime-verified: GeoClue2's sentinel values and the
AltitudeAccuracy-is-null-when-no-altitude behaviour are from the respective platform docs. Both compile, but the desktop workflow only builds — confirming them behaviourally needs a real Linux desktop and a Windows machine without GPS.