I'm implementing a fitness tracker with navigator.geolocation.watchPosition and getCurrentPosition . It works fine on android and on ios emulator, have 5/10m accuracy, but on iphone 5s, I have a terrible accuracy (50/65).
I found out that when I was running an existing fitness tracker at the same time (strava) on ios, suddenly my app was retrieving GPS coordinates with very good accuracy.
So clearly I must be missing some configuration because by default my app does not use high accuracy on iOS. Any idea how to solve that problem?
Code:
const GPS_TIMEOUT_GET = 5000;
const GPS_MAX_AGE = 1000;
const GPS_DISTANCE_FILTER = 5;
const GPS_TIMEOUT_WATCH = 60000;
const GPS_MIN_ACCURACY = 50;
//start the GPS into full time watching. Drains battery but brings best accuracy (required for our needs)
let watchId = navigator.geolocation.watchPosition((position) => {
}
, (error) => {
console.log(error);
}
, {
enableHighAccuracy: true,
timeout: GPS_TIMEOUT_WATCH,
maximumAge: GPS_MAX_AGE,
distanceFilter: GPS_DISTANCE_FILTER
});
//check GPS every X milliseconds)
let intervalId = BackgroundTimer.setInterval(() => {
navigator.geolocation.getCurrentPosition((geoPosition) => {
if (geoPosition.coords.accuracy <= GPS_MIN_ACCURACY) {
let position = createPositionObjectFromGeoPosition(geoPosition);
dispatch({type: GPS_UPDATE_LOC, payload: position})
}
}
, (error) => {
console.log(error);
}
, {
enableHighAccuracy: true,
timeout: GPS_TIMEOUT_GET,
maximumAge: GPS_MAX_AGE
});
}, time);
Info.plist:
<key>NSLocationAlwaysUsageDescription</key>
<string>Your location is used to track your position during a ride and get feedback (distance ridden, duration, speed, etc) in real time and afterwards.</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
<string>location-services</string>
<string>gps</string>
</array>
I used https://github.com/timfpark/react-native-location which uses iOS native location api, and updated my code so that
on android, it stays unchanged and uses the w3c geolocation api which already works
on iOS, I start tracking with the above iOS dedicated api, instead of using w3c geoloc function 'watchPosition'. To retrieve location at regular intervals, getPosition from w3c geoloc still works (as observed when running strava at the same time as my app), so I kept it (might refactor it to remove completely w3c api on iOS later if it's not satisfying).
UPDATE: after many user feedbacks, I'm not satisfied with the accuracy of the JS API watchPosition on Android. My application is a fitness tracker so I need very high accuracy, but it might be different for your needs. I advise to test it carefully, and if unsatisfying use a native android API instead.