Created
June 7, 2023 07:29
-
-
Save efstathiosntonas/18f194e182cb5f6d52cca5a78de0c5f0 to your computer and use it in GitHub Desktop.
ExpoGetLocationWithRetry.ts
This file contains 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
const locationOptions: LocationOptions = { | |
accuracy: LocationAccuracy.Balanced, | |
distanceInterval: 250 | |
}; | |
const lastKnownLocationOptions: LocationLastKnownOptions = { | |
maxAge: 60000, | |
requiredAccuracy: 1000 | |
}; | |
const ANDROID_DELAY_IN_MS = 4 * 1000; // 4s | |
const IOS_DELAY_IN_MS = 15 * 1000; // 15s | |
const DELAY_IN_MS = Platform.OS === "ios" ? IOS_DELAY_IN_MS : ANDROID_DELAY_IN_MS; | |
const MAX_TRIES = 3; | |
function delay(timeInMilliseconds: number) { | |
return new Promise<null>((resolve) => { | |
setTimeout(() => resolve(null), timeInMilliseconds); | |
}); | |
} | |
function handleLocationError(locationError: Error | null) { | |
if (!locationError) { | |
throw new Error("com.xxxx.home.permission_timeout"); | |
} | |
if (locationError.message.startsWith("Cannot obtain current location:")) { | |
throw new Error("com.xxxx.home.permission_timeout"); | |
} else if (locationError.message === "Current location not found.") { | |
throw new Error("com.xxxx.home.location_not_found"); | |
} else if (locationError.message === "Location services are disabled") { | |
throw new Error("com.xxxx.home.location_services_disabled"); | |
} else if (locationError.message === "No location provider available") { | |
throw new Error("com.xxxx.home.no_location_provider_available"); | |
} | |
throw new Error(locationError.message); | |
} | |
// using retry logic since get location can silently fail on Android, https://github.com/expo/expo/issues/10756#issuecomment-1483254287 | |
export const getPosition = async () => { | |
console.log("render"); | |
try { | |
const lastKnownLocation = await Location.getLastKnownPositionAsync( | |
lastKnownLocationOptions | |
); | |
if (lastKnownLocation) { | |
const { latitude: lat, longitude: lng } = lastKnownLocation.coords; | |
return { lat: String(lat), lng: String(lng) }; | |
} | |
let tries = 1; | |
let location: LocationObject | null = null; | |
let locationError: Error | null = null; | |
do { | |
tries += 1; | |
try { | |
location = await Promise.race([ | |
delay(DELAY_IN_MS), | |
Location.getCurrentPositionAsync(locationOptions) | |
]); | |
if (!location) { | |
throw new Error("Timeout"); | |
} | |
} catch (err) { | |
locationError = err as Error; | |
} | |
} while (!location && tries <= MAX_TRIES); | |
if (!location) { | |
return handleLocationError(locationError); | |
} | |
const { latitude: lat, longitude: lng } = location.coords; | |
return { lat: String(lat), lng: String(lng) }; | |
} catch (error: any) { | |
notify(error, "warning", "cannot fetch location", { user_id: currentUser().uid }); | |
switch (error.code) { | |
case PermissionStatus.DENIED: | |
throw new Error("com.xxxx.home.permission_denied"); | |
default: | |
throw error; | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment