Requesting Location Permission in React Native Applications
Tags: reactnative, mobile
Published: 2023-02-22 00:17:26

by [Noble Okafor](https://blog.openreplay.com/authors/noble-okafor)


Many mobile apps, like maps or social media, use location services to function effectively. As a developer building such mobile apps, you'll need to add location access to your app for better functionality.

Before reading a user's location information with a mobile app, they must first grant the location API permission to track their device. This convention respects a user's privacy and gives the app full coverage of the user's location.

In this article, you'll learn how to request permission to access a user's location information in foreground and background mode and track their device in a React Native app. 

## Step 1: Installing the Expo Location API

The [Expo SDK](https://docs.expo.dev/workflow/using-libraries/#using-expo-sdk-libraries) provides functionality for gaining access to a location API. This location API ([expo-location](https://docs.expo.dev/versions/latest/sdk/location/)) is responsible for reading geolocation information from a user's device. To do this, you must first install expo-location in your app.

Run this command to install expo-location in an [expo-managed](https://docs.expo.dev/introduction/managed-vs-bare/#managed-workflow) app:

```bash
expo install expo-location 
```

Follow these [instructions to install and configure expo modules in a bare React Native app](https://docs.expo.dev/bare/installing-expo-modules/).

Now, install and configure `expo-location` for iOS and Android. How to achieve this is documented in the [expo-location GitHub repository](https://github.com/expo/expo/tree/sdk-46/packages/expo-location#installation-in-bare-react-native-projects).

## Step 2: Requesting Foreground Permission

You can track a user's location in two modes: when the app is open (Foreground) or closed but running in the background (Background). Making requests to track both Foreground and Background locations must be made independently.

Proceed to import expo-location into your project:

```javascript
import * as Location from 'expo-location';
```

Expo-location provides methods that trigger events or read data from the user's device. The [**requestForegroundPermissionsAsync()**](https://docs.expo.dev/versions/latest/sdk/location/#locationrequestforegroundpermissionsasync) method requests permission to track a device's location in foreground mode and returns an object with property `status`. 

`status` reports the status of the request to access the location. This object returns `"granted```, `"denied```, or `"undetermined``` if the user accepted, rejected, or failed to accept or reject the permission request, respectively.

To determine the result of the `status` property [destructure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) the object from calling the **`requestForegroundPermissionsAsync()`** method:

```javascript
let { status } = await Location.requestForegroundPermissionsAsync();
console.log(status)
```

Requesting location permission will display a permission modal for the user to select between the options, as shown in the images below.



![-](https://blog.openreplay.com/images/requesting-location-permission-in-react-native-apps/images/j1CxgLD.png)

iOS permission modal



![-](https://blog.openreplay.com/images/requesting-location-permission-in-react-native-apps/images/zaS9X2d.png)


Android permission modal

Once a user accepts or rejects the location permission, it is automatically accepted or rejected subsequently based on the previously set option. 

 

The table below shows how to reset the location permission `status` on an [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/), [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/), and a physical device running the [Expo Go app](https://docs.expo.dev/workflow/expo-go/).

| Platform | Steps to Reset Location Permission |
| --- | --- |
| iOS Simulator | Settings > General > Reset > Reset Location and Privacy |
| iOS Device running Expo Go | Settings > Expo Go > Toggle Location Permission |
| Android Emulator | Run "adb shell pm reset-permissions" inside your project directory in your terminal  |
| Android Device running Expo Go | (Android 11) Settings > Location > Expo Go > Permissions > Location > Toggle Location Permission |

## Step 3: Requesting Background Permission.

A user must first grant foreground location permission to request background location permission. 

The code below will request foreground and background location permission on the user's device: 

```javascript
const startBackgroundTracking = async () => {
  const { status } = await Location.requestForegroundPermissionsAsync();
  if (status == "granted") {
    await Location.requestBackgroundPermissionsAsync();
  }
};
```

Next, set configurations for your `ios` and `android` builds to allow background location tracking. 

For `ios`, declare an [**NSLocationAlwaysAndWhenInUseUsageDescription**](https://developer.apple.com/documentation/bundleresources/information_property_list/nslocationalwaysandwheninuseusagedescription) key that tells the user why the app is requesting access to the user's location at all times. Also, include a [**UIBackgroundModes**](https://developer.apple.com/documentation/bundleresources/information_property_list/uibackgroundmodes/) that specifies the app's services that require it to run in the background.

For `android`, declare [**ACCESS_BACKGROUND_LOCATION**](https://developer.android.com/reference/android/Manifest.permission#ACCESS_BACKGROUND_LOCATION) under permissions to be able to request background permission.

Update your `app.json` file to include these configurations:

```json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSLocationAlwaysAndWhenInUseUsageDescription": "REASON_FOR_REQUEST",
        "UIBackgroundModes": ["location", "fetch"]
      }
    },
    "android": {
      "permissions": ["ACCESS_BACKGROUND_LOCATION"]
    }
  }
}
```

To run tasks like tracking background location over an extended time, install [expo-task-manager](https://docs.expo.dev/versions/latest/sdk/task-manager/) by running `expo install expo-task-manager`.

Import Task Manager and define the task for tracking:

```javascript
import * as TaskManager from "expo-task-manager";

const LOCATION_TASK_NAME = "background-location-task";

// Define the background task for location tracking
TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
  if (error) {
    console.error(error);
    return;
  }
  if (data) {
    // Extract location coordinates from data
    const { locations } = data;
    const location = locations[0];
    if (location) {
      // Do something with captured location coordinates
    }
  }
});
```

Now you can watch for background location updates using the [**startLocationUpdatesAsync()**](https://docs.expo.dev/versions/latest/sdk/location/#locationstartlocationupdatesasynctaskname-options) method.

 

This method takes `LOCATION_TASK_NAME` and location task options as arguments:

```javascript
const startBackgroundTracking = async () => {
  await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
    //Location Task Options
  });
};
```

You can find all location task options in the [Expo documentation](https://docs.expo.dev/versions/latest/sdk/location/#locationtaskoptions).

**Note:** Task Manager may not work as expected in the Expo Go app on iOS. You'll need to test it using [a development build](https://docs.expo.dev/development/introduction/).



<h2>Session Replay for Developers</h2> 
<p><em>
Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data
</em></p>
<img alt="OpenReplay" width="768" height="400" src="https://blog.openreplay.com/assets/overview_Z17Qdyg.png" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em>





## Overview of Expo Permissions

The Expo Permissions can be used to request the following permissions:

- **[AUDIO_RECORDING](https://docs.expo.dev/versions/latest/sdk/audio/#recording-sounds)**: access to the device's microphone for audio recording
- **[CALENDAR](https://docs.expo.dev/versions/latest/sdk/calendar/)**: access to the device's calendar (iOS only)
- **[CAMERA](https://docs.expo.dev/versions/latest/sdk/camera/)**: access to the device's camera
- **[CONTACTS](https://docs.expo.dev/versions/latest/sdk/camera/)**: access to the device's contact list
- **[LOCATION](https://docs.expo.dev/versions/latest/sdk/location/)**: access to the device's location
- [**MEDIA-LIBRARY**](https://docs.expo.dev/versions/latest/sdk/media-library/): access to the device’s photo and video library. The application will be able to view or write to the library.
- **[NOTIFICATIONS](https://docs.expo.dev/versions/latest/sdk/notifications/)**: access to the device's notification system
- **[REMINDER](https://docs.expo.dev/versions/latest/sdk/calendar/#reminder)**: access to the device's reminders (iOS only)
- [**SENSORS**](https://docs.expo.dev/versions/latest/sdk/sensors/): access to the device’s sensors to measure motion, orientation, pressure, magnetic fields, and step count

To request permission to access any of the above-listed features with Expo, you must install the specific expo library and ensure that you have the necessary native configuration for each permission you request. The configurations are different for each library and each Operating system platform.

For example, to request Camera permissions on an iOS and Android platform, you will need to install the `expo-camera` library and add an [**NSCameraUseUsageDescription**](https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription) to your `Info.plist` (iOS) and **CAMERA** value to the `Permissions` object (Android):

iOS:

```json
"ios": {
  "infoPlist": {
        "NSCameraUseUsageDescription": "REASON_FOR_REQUEST",
      "UIBackgroundModes": ["Camera"]
  }
}
```

Android:

```json
"android": {
  "permissions": ["CAMERA"]
}
```

For a list of the native configuration required for each permission, see the documentation for the Expo API Reference: 

## Challenges To Handle When Requesting Permissions

Requesting permissions can present several challenges for developers. One of the main challenges is ensuring that the app requests the correct permissions for the specific device and operating system. This is because different devices and operating systems have different permission models and configuration requirements, making it difficult to write code seamlessly across all platforms.

Another challenge is handling the different states of permissions. For example, an app may request permission, and the user may choose to grant or deny it. The app must then be able to handle both scenarios and respond appropriately, such as disabling certain features if permission is denied. Users can also revoke permissions at any time, which can cause unexpected behavior in the app.

Lastly, iOS and Android systems have strict restrictions and privacy settings. These are efforts to protect users from private data leaks and misuse, which they may not be aware of. Providing clear and informative explanations to the user about why the app needs certain permission is an absolute must. This is especially important for sensitive permissions such as access to the location or microphone, as users may be more likely to deny them if they do not understand why the app needs them. 

## Conclusion

In this post, you successfully learned how to request permission to access a user's location data. You also learned about other available Expo permissions and their features. 

Following the proper native configuration and best practices for requesting permissions, you can ensure that your app has the necessary permissions to provide a seamless and enjoyable user experience.


[![newsletter](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)