1import { PermissionStatus, createPermissionHook, Platform, } from 'expo-modules-core';
2import ExpoLocation from './ExpoLocation';
3import { LocationAccuracy, LocationActivityType, LocationGeofencingEventType, LocationGeofencingRegionState, } from './Location.types';
4import { LocationEventEmitter } from './LocationEventEmitter';
5import { LocationSubscriber, HeadingSubscriber, _getCurrentWatchId } from './LocationSubscribers';
6// @needsAudit
7/**
8 * @deprecated The Geocoding web api is no longer available from SDK 49 onwards. Use [Place Autocomplete](https://developers.google.com/maps/documentation/places/web-service/autocomplete) instead.
9 * @param apiKey Google API key obtained from Google API Console. This API key must have `Geocoding API`
10 * enabled, otherwise your geocoding requests will be denied.
11 */
12function setGoogleApiKey(_apiKey) { }
13// @needsAudit
14/**
15 * Check status of location providers.
16 * @return A promise which fulfills with an object of type [LocationProviderStatus](#locationproviderstatus).
17 */
18export async function getProviderStatusAsync() {
19    return ExpoLocation.getProviderStatusAsync();
20}
21// @needsAudit
22/**
23 * Asks the user to turn on high accuracy location mode which enables network provider that uses
24 * Google Play services to improve location accuracy and location-based services.
25 * @return A promise resolving as soon as the user accepts the dialog. Rejects if denied.
26 */
27export async function enableNetworkProviderAsync() {
28    // If network provider is disabled (user's location mode is set to "Device only"),
29    // Android's location provider may not give you any results. Use this method in order to ask the user
30    // to change the location mode to "High accuracy" which uses Google Play services and enables network provider.
31    // `getCurrentPositionAsync` and `watchPositionAsync` are doing it automatically anyway.
32    if (Platform.OS === 'android') {
33        return ExpoLocation.enableNetworkProviderAsync();
34    }
35}
36// @needsAudit
37/**
38 * Requests for one-time delivery of the user's current location.
39 * Depending on given `accuracy` option it may take some time to resolve,
40 * especially when you're inside a building.
41 * > __Note:__ Calling it causes the location manager to obtain a location fix which may take several
42 * > seconds. Consider using [`Location.getLastKnownPositionAsync`](#locationgetlastknownpositionasyncoptions)
43 * > if you expect to get a quick response and high accuracy is not required.
44 * @param options
45 * @return A promise which fulfills with an object of type [`LocationObject`](#locationobject).
46 */
47export async function getCurrentPositionAsync(options = {}) {
48    return ExpoLocation.getCurrentPositionAsync(options);
49}
50// @needsAudit
51/**
52 * Gets the last known position of the device or `null` if it's not available or doesn't match given
53 * requirements such as maximum age or required accuracy.
54 * It's considered to be faster than `getCurrentPositionAsync` as it doesn't request for the current
55 * location, but keep in mind the returned location may not be up-to-date.
56 * @param options
57 * @return A promise which fulfills with an object of type [LocationObject](#locationobject) or
58 * `null` if it's not available or doesn't match given requirements such as maximum age or required
59 * accuracy.
60 */
61export async function getLastKnownPositionAsync(options = {}) {
62    return ExpoLocation.getLastKnownPositionAsync(options);
63}
64// @needsAudit
65/**
66 * Subscribe to location updates from the device. Please note that updates will only occur while the
67 * application is in the foreground. To get location updates while in background you'll need to use
68 * [Location.startLocationUpdatesAsync](#locationstartlocationupdatesasynctaskname-options).
69 * @param options
70 * @param callback This function is called on each location update. It receives an object of type
71 * [`LocationObject`](#locationobject) as the first argument.
72 * @return A promise which fulfills with a [`LocationSubscription`](#locationsubscription) object.
73 */
74export async function watchPositionAsync(options, callback) {
75    const watchId = LocationSubscriber.registerCallback(callback);
76    await ExpoLocation.watchPositionImplAsync(watchId, options);
77    return {
78        remove() {
79            LocationSubscriber.unregisterCallback(watchId);
80        },
81    };
82}
83// @needsAudit
84/**
85 * Gets the current heading information from the device. To simplify, it calls `watchHeadingAsync`
86 * and waits for a couple of updates, and then returns the one that is accurate enough.
87 * @return A promise which fulfills with an object of type [LocationHeadingObject](#locationheadingobject).
88 */
89export async function getHeadingAsync() {
90    return new Promise(async (resolve) => {
91        let tries = 0;
92        const subscription = await watchHeadingAsync((heading) => {
93            if (heading.accuracy > 1 || tries > 5) {
94                subscription.remove();
95                resolve(heading);
96            }
97            else {
98                tries += 1;
99            }
100        });
101    });
102}
103// @needsAudit
104/**
105 * Subscribe to compass updates from the device.
106 * @param callback This function is called on each compass update. It receives an object of type
107 * [LocationHeadingObject](#locationheadingobject) as the first argument.
108 * @return A promise which fulfills with a [`LocationSubscription`](#locationsubscription) object.
109 */
110export async function watchHeadingAsync(callback) {
111    const watchId = HeadingSubscriber.registerCallback(callback);
112    await ExpoLocation.watchDeviceHeading(watchId);
113    return {
114        remove() {
115            HeadingSubscriber.unregisterCallback(watchId);
116        },
117    };
118}
119// @needsAudit
120/**
121 * Geocode an address string to latitude-longitude location.
122 * > **Note**: Using the Geocoding web api is no longer supported. Use [Place Autocomplete](https://developers.google.com/maps/documentation/places/web-service/autocomplete) instead.
123 *
124 * > **Note**: Geocoding is resource consuming and has to be used reasonably. Creating too many
125 * > requests at a time can result in an error, so they have to be managed properly.
126 * > It's also discouraged to use geocoding while the app is in the background and its results won't
127 * > be shown to the user immediately.
128 *
129 * > On Android, you must request a location permission (`Permissions.LOCATION`) from the user
130 * > before geocoding can be used.
131 * @param address A string representing address, eg. `"Baker Street London"`.
132 * @param options
133 * @return A promise which fulfills with an array (in most cases its size is 1) of [`LocationGeocodedLocation`](#locationgeocodedlocation) objects.
134 */
135export async function geocodeAsync(address, options) {
136    if (typeof address !== 'string') {
137        throw new TypeError(`Address to geocode must be a string. Got ${address} instead.`);
138    }
139    if (options?.useGoogleMaps || Platform.OS === 'web') {
140        if (__DEV__) {
141            console.warn('The Geocoding API has been removed in SDK 49, use Place Autocomplete service instead' +
142                '(https://developers.google.com/maps/documentation/places/web-service/autocomplete)');
143        }
144        return [];
145    }
146    return await ExpoLocation.geocodeAsync(address);
147}
148// @needsAudit
149/**
150 * Reverse geocode a location to postal address.
151 * > **Note**: Using the Geocoding web api is no longer supported. Use [Place Autocomplete](https://developers.google.com/maps/documentation/places/web-service/autocomplete) instead.
152 *
153 * > **Note**: Geocoding is resource consuming and has to be used reasonably. Creating too many
154 * > requests at a time can result in an error, so they have to be managed properly.
155 * > It's also discouraged to use geocoding while the app is in the background and its results won't
156 * > be shown to the user immediately.
157 *
158 * > On Android, you must request a location permission (`Permissions.LOCATION`) from the user
159 * > before geocoding can be used.
160 * @param location An object representing a location.
161 * @param options
162 * @return A promise which fulfills with an array (in most cases its size is 1) of [`LocationGeocodedAddress`](#locationgeocodedaddress) objects.
163 */
164export async function reverseGeocodeAsync(location, options) {
165    if (typeof location.latitude !== 'number' || typeof location.longitude !== 'number') {
166        throw new TypeError('Location to reverse-geocode must be an object with number properties `latitude` and `longitude`.');
167    }
168    if (options?.useGoogleMaps || Platform.OS === 'web') {
169        if (__DEV__) {
170            console.warn('The Geocoding API has been removed in SDK 49, use Place Autocomplete service instead' +
171                '(https://developers.google.com/maps/documentation/places/web-service/autocomplete)');
172        }
173        return [];
174    }
175    return await ExpoLocation.reverseGeocodeAsync(location);
176}
177// @needsAudit
178/**
179 * Checks user's permissions for accessing location.
180 * @return A promise that fulfills with an object of type [LocationPermissionResponse](#locationpermissionresponse).
181 * @deprecated Use [`getForegroundPermissionsAsync`](#locationgetforegroundpermissionsasync) or [`getBackgroundPermissionsAsync`](#locationgetbackgroundpermissionsasync) instead.
182 */
183export async function getPermissionsAsync() {
184    console.warn(`"getPermissionsAsync()" is now deprecated. Please use "getForegroundPermissionsAsync()" or "getBackgroundPermissionsAsync()" instead.`);
185    return await ExpoLocation.getPermissionsAsync();
186}
187// @needsAudit
188/**
189 * Asks the user to grant permissions for location.
190 * @return A promise that fulfills with an object of type [LocationPermissionResponse](#locationpermissionresponse).
191 * @deprecated Use [`requestForegroundPermissionsAsync`](#locationrequestforegroundpermissionsasync) or [`requestBackgroundPermissionsAsync`](#locationrequestbackgroundpermissionsasync) instead.
192 */
193export async function requestPermissionsAsync() {
194    console.warn(`"requestPermissionsAsync()" is now deprecated. Please use "requestForegroundPermissionsAsync()" or "requestBackgroundPermissionsAsync()" instead.`);
195    return await ExpoLocation.requestPermissionsAsync();
196}
197// @needsAudit
198/**
199 * Checks user's permissions for accessing location while the app is in the foreground.
200 * @return A promise that fulfills with an object of type [PermissionResponse](#permissionresponse).
201 */
202export async function getForegroundPermissionsAsync() {
203    return await ExpoLocation.getForegroundPermissionsAsync();
204}
205// @needsAudit
206/**
207 * Asks the user to grant permissions for location while the app is in the foreground.
208 * @return A promise that fulfills with an object of type [PermissionResponse](#permissionresponse).
209 */
210export async function requestForegroundPermissionsAsync() {
211    return await ExpoLocation.requestForegroundPermissionsAsync();
212}
213// @needsAudit
214/**
215 * Check or request permissions for the foreground location.
216 * This uses both `requestForegroundPermissionsAsync` and `getForegroundPermissionsAsync` to interact with the permissions.
217 *
218 * @example
219 * ```ts
220 * const [status, requestPermission] = Location.useForegroundPermissions();
221 * ```
222 */
223export const useForegroundPermissions = createPermissionHook({
224    getMethod: getForegroundPermissionsAsync,
225    requestMethod: requestForegroundPermissionsAsync,
226});
227// @needsAudit
228/**
229 * Checks user's permissions for accessing location while the app is in the background.
230 * @return A promise that fulfills with an object of type [PermissionResponse](#permissionresponse).
231 */
232export async function getBackgroundPermissionsAsync() {
233    return await ExpoLocation.getBackgroundPermissionsAsync();
234}
235// @needsAudit
236/**
237 * Asks the user to grant permissions for location while the app is in the background.
238 * On __Android 11 or higher__: this method will open the system settings page - before that happens
239 * you should explain to the user why your application needs background location permission.
240 * For example, you can use `Modal` component from `react-native` to do that.
241 * > __Note__: Foreground permissions should be granted before asking for the background permissions
242 * (your app can't obtain background permission without foreground permission).
243 * @return A promise that fulfills with an object of type [PermissionResponse](#permissionresponse).
244 */
245export async function requestBackgroundPermissionsAsync() {
246    return await ExpoLocation.requestBackgroundPermissionsAsync();
247}
248// @needsAudit
249/**
250 * Check or request permissions for the background location.
251 * This uses both `requestBackgroundPermissionsAsync` and `getBackgroundPermissionsAsync` to
252 * interact with the permissions.
253 *
254 * @example
255 * ```ts
256 * const [status, requestPermission] = Location.useBackgroundPermissions();
257 * ```
258 */
259export const useBackgroundPermissions = createPermissionHook({
260    getMethod: getBackgroundPermissionsAsync,
261    requestMethod: requestBackgroundPermissionsAsync,
262});
263// --- Location service
264// @needsAudit
265/**
266 * Checks whether location services are enabled by the user.
267 * @return A promise which fulfills to `true` if location services are enabled on the device,
268 * or `false` if not.
269 */
270export async function hasServicesEnabledAsync() {
271    return await ExpoLocation.hasServicesEnabledAsync();
272}
273// --- Background location updates
274function _validateTaskName(taskName) {
275    if (!taskName || typeof taskName !== 'string') {
276        throw new Error(`\`taskName\` must be a non-empty string. Got ${taskName} instead.`);
277    }
278}
279// @docsMissing
280export async function isBackgroundLocationAvailableAsync() {
281    const providerStatus = await getProviderStatusAsync();
282    return providerStatus.backgroundModeEnabled;
283}
284// @needsAudit
285/**
286 * Registers for receiving location updates that can also come when the app is in the background.
287 *
288 * # Task parameters
289 *
290 * Background location task will be receiving following data:
291 * - `locations` - An array of the new locations.
292 *
293 * ```ts
294 * import * as TaskManager from 'expo-task-manager';
295 *
296 * TaskManager.defineTask(YOUR_TASK_NAME, ({ data: { locations }, error }) => {
297 *  if (error) {
298 *    // check `error.message` for more details.
299 *    return;
300 *  }
301 *  console.log('Received new locations', locations);
302 * });
303 * ```
304 *
305 * @param taskName Name of the task receiving location updates.
306 * @param options An object of options passed to the location manager.
307 *
308 * @return A promise resolving once the task with location updates is registered.
309 */
310export async function startLocationUpdatesAsync(taskName, options = { accuracy: LocationAccuracy.Balanced }) {
311    _validateTaskName(taskName);
312    await ExpoLocation.startLocationUpdatesAsync(taskName, options);
313}
314// @needsAudit
315/**
316 * Stops geofencing for specified task.
317 * @param taskName Name of the background location task to stop.
318 * @return A promise resolving as soon as the task is unregistered.
319 */
320export async function stopLocationUpdatesAsync(taskName) {
321    _validateTaskName(taskName);
322    await ExpoLocation.stopLocationUpdatesAsync(taskName);
323}
324// @needsAudit
325/**
326 * @param taskName Name of the location task to check.
327 * @return A promise which fulfills with boolean value indicating whether the location task is
328 * started or not.
329 */
330export async function hasStartedLocationUpdatesAsync(taskName) {
331    _validateTaskName(taskName);
332    return ExpoLocation.hasStartedLocationUpdatesAsync(taskName);
333}
334// --- Geofencing
335function _validateRegions(regions) {
336    if (!regions || regions.length === 0) {
337        throw new Error('Regions array cannot be empty. Use `stopGeofencingAsync` if you want to stop geofencing all regions');
338    }
339    for (const region of regions) {
340        if (typeof region.latitude !== 'number') {
341            throw new TypeError(`Region's latitude must be a number. Got '${region.latitude}' instead.`);
342        }
343        if (typeof region.longitude !== 'number') {
344            throw new TypeError(`Region's longitude must be a number. Got '${region.longitude}' instead.`);
345        }
346        if (typeof region.radius !== 'number') {
347            throw new TypeError(`Region's radius must be a number. Got '${region.radius}' instead.`);
348        }
349    }
350}
351// @needsAudit
352/**
353 * Starts geofencing for given regions. When the new event comes, the task with specified name will
354 * be called with the region that the device enter to or exit from.
355 * If you want to add or remove regions from already running geofencing task, you can just call
356 * `startGeofencingAsync` again with the new array of regions.
357 *
358 * # Task parameters
359 *
360 * Geofencing task will be receiving following data:
361 *  - `eventType` - Indicates the reason for calling the task, which can be triggered by entering or exiting the region.
362 *    See [GeofencingEventType](#geofencingeventtype).
363 *  - `region` - Object containing details about updated region. See [LocationRegion](#locationregion) for more details.
364 *
365 * @param taskName Name of the task that will be called when the device enters or exits from specified regions.
366 * @param regions Array of region objects to be geofenced.
367 *
368 * @return A promise resolving as soon as the task is registered.
369 *
370 * @example
371 * ```ts
372 * import { GeofencingEventType } from 'expo-location';
373 * import * as TaskManager from 'expo-task-manager';
374 *
375 *  TaskManager.defineTask(YOUR_TASK_NAME, ({ data: { eventType, region }, error }) => {
376 *   if (error) {
377 *     // check `error.message` for more details.
378 *     return;
379 *   }
380 *   if (eventType === GeofencingEventType.Enter) {
381 *     console.log("You've entered region:", region);
382 *   } else if (eventType === GeofencingEventType.Exit) {
383 *     console.log("You've left region:", region);
384 *   }
385 * });
386 * ```
387 */
388export async function startGeofencingAsync(taskName, regions = []) {
389    _validateTaskName(taskName);
390    _validateRegions(regions);
391    await ExpoLocation.startGeofencingAsync(taskName, { regions });
392}
393// @needsAudit
394/**
395 * Stops geofencing for specified task. It unregisters the background task so the app will not be
396 * receiving any updates, especially in the background.
397 * @param taskName Name of the task to unregister.
398 * @return A promise resolving as soon as the task is unregistered.
399 */
400export async function stopGeofencingAsync(taskName) {
401    _validateTaskName(taskName);
402    await ExpoLocation.stopGeofencingAsync(taskName);
403}
404// @needsAudit
405/**
406 * @param taskName Name of the geofencing task to check.
407 * @return A promise which fulfills with boolean value indicating whether the geofencing task is
408 * started or not.
409 */
410export async function hasStartedGeofencingAsync(taskName) {
411    _validateTaskName(taskName);
412    return ExpoLocation.hasStartedGeofencingAsync(taskName);
413}
414export { LocationEventEmitter as EventEmitter, _getCurrentWatchId };
415export { LocationAccuracy as Accuracy, LocationActivityType as ActivityType, LocationGeofencingEventType as GeofencingEventType, LocationGeofencingRegionState as GeofencingRegionState, PermissionStatus, setGoogleApiKey, };
416export { installWebGeolocationPolyfill } from './GeolocationPolyfill';
417export * from './Location.types';
418//# sourceMappingURL=Location.js.map