Develop
Develop
Select your platform

Location API

Overview

The VR Location API provides rich location capabilities to Meta Quest headsets running OS version 57 or greater.
The VR Location API leverages the native Android Location Manager API to seamlessly implement Android’s native location manager API on VR devices. Therefore, you can get location information on VR devices like you would on a standard Android device.
Note: Meta Quest headsets currently lack GPS functionality. Consequently, the VR Location API relies on Wi-Fi geolocation to determine location.

Prerequisites

To utilize the VR Location API, the headset must be running OS version v57 or greater.
The VR Location API supports the following devices:

Usage

Location permissions

To protect user privacy, application developers must explicitly request location permissions from the user—like any other runtime permission—and only request the minimum permissions necessary for their applications.

Types of Location Access

Each permission has a combination of the following characteristics:
  • Category: Foreground location (Meta Quest headsets do not support background location access; see Prohibited Android Permissions).
  • Accuracy: Either precise location or approximate location (see the definition of precise and approximate location here).

Integration steps

Step 1

Declare the permissions you want access to in your application manifest. For example:
  • Use android.permission.ACCESS_COARSE_LOCATION if your app needs approximate location information.
  • Use android.permission.ACCESS_FINE_LOCATION if your app needs precise location information.
<manifest ... >
<!-- Always include this permission -->
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
 />
<!--Include only if your app benefits from precise location access. -->
  <uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
 />
</manifest>

Step 2

Request location access at runtime. Wait until the user engages with a feature in your app before requesting location access permissions. This approach aligns with the recommended practice of seeking runtime permissions within the appropriate context.
Note: Your users can request that your app retrieve only approximate location information, even when your app requests the ACCESS_FINE_LOCATION runtime permission. To accommodate this user preference, avoid requesting the ACCESS_FINE_LOCATION permission in isolation. Instead, make a single runtime request for the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
// Create a class-level field for the ActivityResultLauncher
private ActivityResultLauncher<String[]> locationPermissionLauncher;

// Initialize the ActivityResultLauncher in your onCreate or initialization method
locationPermissionLauncher = registerForActivityResult(
    new ActivityResultContracts.RequestMultiplePermissions(),
    new ActivityResultCallback<Map<String, Boolean>>() {
        @Override
        public void onActivityResult(Map<String, Boolean> permissions) {
            if (permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false)) {
                // Precise location access granted.
            } else if (permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false)) {
                // Only approximate location access granted.
            } else {
                // No location access granted.
            }
        }
    }
);
Sample Location Prompt
The following table illustrates the permissions granted to your app by the system, depending on the user’s selections in the permissions runtime dialog.
PermissionPreciseApproximate
While using the app
ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Only this time
ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION
ACCESS_COARSE_LOCATION
Deny
No location permissions
No location permissions

Step 3

Create a location subscription. The system provides location information based on the parameters you specify in the location updates call.
  1. Create an instance of Location Manager.
     LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    
  2. Request location updates from the LocationManager.
     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
    
  3. Implement a LocationListener to receive location updates.
     private final LocationListener locationListener = new LocationListener() {
         @Override
         public void onLocationChanged(Location location) {
             // Handle location updates here
         }
     };
    

APIs

Android Location Manager

We support the following APIs in Android Location Manager:
  •   public Location getLastKnownLocation (String provider)
    
    This call returns the last known location from the given provider or null if no previous location exists. The returned location may be quite old in some circumstances, so you should always check the age of the location.
  •   public void getCurrentLocation (String provider,
                      LocationRequest locationRequest,
                      CancellationSignal cancellationSignal,
                      Executor executor,
                      Consumer<Location> consumer)
    
    Asynchronously returns a single current location fix from the given provider based on the given LocationRequest.
  •   public void requestLocationUpdates (String provider,
                      long minTimeMs,
                      float minDistanceM,
                      LocationListener listener)
    
    Register for location updates from the given provider with the given arguments and a callback on the Looper of the calling thread.
      public void requestLocationUpdates (String provider,
                  long minTimeMs,
                  float minDistanceM,
                  PendingIntent pendingIntent)
    
    Register for location updates using the named provider and callbacks delivered via the provided PendingIntent.
      public void requestLocationUpdates (String provider,
                  LocationRequest locationRequest,
                  PendingIntent pendingIntent)
    
    Register for location updates from the specified provider using a LocationRequest, and callbacks delivered via the provided PendingIntent.
      public void requestLocationUpdates (String provider,
                      LocationRequest locationRequest,
                      Executor executor,
                      LocationListener listener)
    
    Register for location updates using the named provider and a callback on the specified Executor.
  •  public void removeUpdates (LocationListener listener)
    
    Remove all location updates for the specified LocationListener.

Supported APIs

Note: Some API behaviors, such as getCurrentLocation(), might differ from the AOSP.
Public methods 
getAllProviders() returns a list of the names of all available location providers.
getCurrentLocation() asynchronously returns a single current location fix from the given provider based on the given LocationRequest. Note: Your Meta Quest headset may provide a cached location for this call.
getLastKnownLocation(String provider) Gets the last known location by provider from the cache.
getProvider(String provider) returns a list of the names of available location providers. Note: Android deprecated this method in version 31 of the API.
getProviderProperties(String provider) returns the properties of the given provider or null if the properties are currently unknown.
getProviders() returns a list of the names of available location providers.
hasProvider() returns true if the given location provider exists on this device, irrespective of whether it is currently enabled.
isLocationEnabled() returns the current enabled/disabled state of the location. To listen for changes, see MODE_CHANGED_ACTION.
isProvidedEnabled() returns the current enabled/disabled status of the given provider. To listen for changes, see PROVIDERS_CHANGED_ACTION.
requestFlush() requests that the given provider flush any batched locations to listeners.
requestLocationUpdates() registers for location updates from the given provider
requestSingleUpdate() registers for a single location update using a named provider and pending intent. Note: Android deprecated this method in version 30 of the API.

Unsupported APIs

Note: None of the GNSS-related APIs, such as addGpsStatusListener(), are supported.
Public methods 
addGpsStatusListener() Meta Quest headsets do not have a GPS chipset.
addNmeaListener() Meta Quest headsets do not have a GPS chipset.
addProximityAlert() ACCESS_BACKGROUND_LOCATION permission is prohibited
addTestProvider() Leads to SecurityException.
clearTestProvider() Lead to SecurityException
getGnssAntennaInfo() Meta Quest headsets do not have a GPS chipset.
getGnssCapabilitie() Meta Quest headsets do not have a GPS chipset.
getGnssHardwareModelName() Meta Quest headsets do not have a GPS chipset.
getGnssYearofHardware() Meta Quest headsets do not have a GPS chipset.
getGPSStatus() Meta Quest headsets do not have a GPS chipset.
registerAntennaInfoListener() Meta Quest headsets do not have a GPS chipset.
registerGnssMeasurementsCallback() Meta Quest headsets do not have a GPS chipset.
registerGnssNavigationCallback() Meta Quest headsets do not have a GPS chipset.
registerGnssStatusCallback() Meta Quest headsets do not have a GPS chipset.
removeGpsStatusListener() Meta Quest headsets do not have a GPS chipset.
removeNmeaListener() Meta Quest headsets do not have a GPS chipset.
removeProximityAlert() ACCESS_BACKGROUND_LOCATION permission is prohibited.
removeTestProvider() Leads to SecurityException.
sendExtraCommand() ACCESS_LOCATION_EXTRA_COMMANDS permission is prohibited.
setTestProviderEnabled() Leads to SecurityException.
setTestProviderLocation() Leads to SecurityException.
setTestProviderStatus() Leads to SecurityException.
unregisterAntennaInfoListener() Meta Quest headsets do not have a GPS chipset.
unregisterGnssNavigationMessageCallback() Meta Quest headsets do not have a GPS chipset.

Best practices

Follow these best practices to optimize your usage of the VR Location API and adhere to legal, contractual, and privacy obligations regarding location data:
  • Request location updates only when necessary to minimize battery consumption.
  • Use coarse location data when you don’t require precise location data to respect users’ privacy.
  • Clearly explain to users why your app requires access to their location.
Did you find this page helpful?
Thumbs up icon
Thumbs down icon