Sensors and location

Updated: Sep 19, 2026

Sensors

Meta Ray-Ban Display glasses expose motion and orientation through DeviceMotionEvent and DeviceOrientationEvent. These high-frequency readings are permission-gated, nullable, and time-sensitive. Feature-detect the APIs, request access in response to a clear user action, and keep the app usable when access is denied or readings stop.

Request permission

The device provides requestPermission() on both event constructors. They share one sensor permission, so call either available method once:
let sensorListenersAttached = false;

function attachSensorListeners() {
  if (sensorListenersAttached) {
    return;
  }

  window.addEventListener('devicemotion', handleMotion);
  window.addEventListener('deviceorientation', handleOrientation);
  sensorListenersAttached = true;
}

async function requestSensorAccess() {
  const orientation = window.DeviceOrientationEvent;
  const motion = window.DeviceMotionEvent;
  if (!orientation && !motion) {
    showSensorUnavailable('Sensors are not supported.');
    return;
  }

  const permissionOwner =
    typeof orientation?.requestPermission === 'function'
      ? orientation
      : typeof motion?.requestPermission === 'function'
        ? motion
        : null;

  try {
    const state = permissionOwner
      ? await permissionOwner.requestPermission()
      : 'granted';

    if (state !== 'granted') {
      showSensorUnavailable('Sensor access was not granted.');
      return;
    }

    attachSensorListeners();
  } catch (error) {
    showSensorUnavailable('Sensor access is unavailable.');
  }
}

document
  .getElementById('enable-sensors')
  .addEventListener('click', requestSensorAccess);
Requesting access from a button gives the user context and also works on browsers that require transient activation for sensor permission. Track listener state so repeated permission requests do not attach duplicate listeners.
Remove listeners when the feature or page no longer needs them:
function stopSensors() {
  window.removeEventListener('devicemotion', handleMotion);
  window.removeEventListener('deviceorientation', handleOrientation);
  sensorListenersAttached = false;
}

Motion data

DeviceMotionEvent can provide acceleration, acceleration including gravity, rotation rate, and the interval between readings. Guard both each containing object and each numeric member:
function finite(value) {
  return typeof value === 'number' && Number.isFinite(value);
}

function handleMotion(event) {
  const acceleration = event.accelerationIncludingGravity;
  if (
    acceleration &&
    finite(acceleration.x) &&
    finite(acceleration.y) &&
    finite(acceleration.z)
  ) {
    updateAcceleration({
      x: acceleration.x,
      y: acceleration.y,
      z: acceleration.z,
      interval: event.interval,
    });
  }

  const rotation = event.rotationRate;
  if (
    rotation &&
    finite(rotation.alpha) &&
    finite(rotation.beta) &&
    finite(rotation.gamma)
  ) {
    updateRotation({
      alpha: rotation.alpha,
      beta: rotation.beta,
      gamma: rotation.gamma,
    });
  }
}
FieldUnitAvailability
accelerationIncludingGravity.x/y/z
Meters per second squared
Values can be null; validate before use.
acceleration.x/y/z
Meters per second squared
Gravity-removed readings can be unavailable.
rotationRate.alpha/beta/gamma
Degrees per second
Values can be null. This differs from Generic Sensor Gyroscope, which uses radians per second.
interval
Milliseconds
Treat as reported timing, not a guaranteed fixed frequency.
Use orientation or a suitable fusion method for sustained tilt. Dynamic acceleration alone does not provide a stable orientation reference. Throttle visual updates instead of writing to the DOM for every sensor event.

Orientation data

Orientation events expose alpha, beta, gamma, and absolute. Values can be missing or relative to different reference frames, so inspect absolute and validate every number before use:
function handleOrientation(event) {
  if (
    !finite(event.alpha) ||
    !finite(event.beta) ||
    !finite(event.gamma)
  ) {
    showOrientationUnavailable();
    return;
  }

  updateOrientation({
    alpha: event.alpha,
    beta: event.beta,
    gamma: event.gamma,
    absolute: event.absolute === true,
    receivedAt: performance.now(),
  });
}
The runtime can improve heading when a higher-quality source is available. Treat Earth-relative or compass-grade heading as conditional on the event and source. Calibrate the experience for its intended use and retain a fallback when heading or accuracy is insufficient. deviceorientationabsolute can be available on supported builds; feature-detect it rather than assuming universal browser support.

Permission loss and stale readings

A user can revoke sensor access while the app is open. When access is revoked, the browser stops event delivery, but it does not dispatch a public revocation event to the page. The runtime retains the page’s registered listeners, so a later successful requestPermission() call resumes forwarding without requiring the app to register them again.
Track when the last reading arrived. When updates stop, move the interface to a neutral or stale state before the old reading can drive navigation, safety-sensitive decisions, or persistent state. Offer an explicit action to request access again.

Location

Meta Ray-Ban Display implements navigator.geolocation. One-shot positions are normally sourced through the paired phone because the glasses do not contain a standalone satellite-navigation receiver. Availability and accuracy depend on permission, the paired-device connection, environment, and location services.

Request one position

Always provide success and error callbacks:
function requestPosition() {
  if (!navigator.geolocation) {
    showLocationUnavailable('Location is not supported.');
    return;
  }

  navigator.geolocation.getCurrentPosition(
    (position) => {
      const {coords} = position;
      showPosition({
        latitude: coords.latitude,
        longitude: coords.longitude,
        accuracy: coords.accuracy,
        altitude: coords.altitude,
        altitudeAccuracy: coords.altitudeAccuracy,
        heading: coords.heading,
        speed: coords.speed,
        timestamp: position.timestamp,
      });
    },
    (error) => {
      showLocationUnavailable(locationErrorMessage(error));
    },
    {timeout: 15000},
  );
}
ErrorMeaning
PERMISSION_DENIED
The user denied location access.
POSITION_UNAVAILABLE
The runtime could not obtain a position. This can have several causes and does not prove that the phone is offline.
TIMEOUT
A position was not available within the effective timeout.
Use coords.accuracy rather than promising a fixed accuracy range. Altitude, altitude accuracy, heading, and speed can be null.

Watch position changes

Use watchPosition() when a feature needs ongoing updates, and clear the watch as soon as it is no longer needed:
let watchId = null;

function startLocationWatch() {
  watchId = navigator.geolocation.watchPosition(
    (position) => updateMap(position.coords),
    (error) => showLocationUnavailable(locationErrorMessage(error)),
    {enableHighAccuracy: true},
  );
}

function stopLocationWatch() {
  if (watchId !== null) {
    navigator.geolocation.clearWatch(watchId);
    watchId = null;
  }
}
A watch is active only while the page and runtime are active; it is not a background-execution contract. Stop it during route teardown or when the feature is hidden.

Position options on the device

On Meta Ray-Ban Display glasses, the supported option set is narrower than in a general desktop browser:
MethodSupported options
getCurrentPosition()
timeout. The host applies its own default and upper bound. enableHighAccuracy and maximumAge are not used for one-shot requests.
watchPosition()
enableHighAccuracy is a request for the best available watch source and can fall back. timeout and maximumAge are not used for watches.
Base feature behavior on reported accuracy rather than a particular source or precision tier.

Privacy and resilience

Motion and location can reveal sensitive user behavior. Explain why access is needed before requesting it. Collect for the shortest practical duration, keep logging and persistence to the minimum the feature needs, and transmit readings only when the user expects it.
Provide a meaningful experience when permission is denied, the paired phone is unavailable, sensor delivery stops, or a location request fails. Test first use, denial, later grant, revocation, stale readings, route cleanup, and recovery on the device.