Air pressure and relative altitude from the device barometer
One.Barometer streams air pressure from the device barometer, plus
relative altitude on iOS. Reach for it for weather-aware UI, elevation
gain on hikes, and floor-change hints indoors.
On iOS it uses CMAltimeter from Core Motion, with state on the main
thread. On Android it reads the pressure sensor through SensorManager.
On web browsers expose no barometer, so the sensor reads unavailable and
listeners never fire.
import { useEffect, useState } from 'react'import { Text } from 'react-native'import { One } from 'one'
function Pressure() { const [pressure, setPressure] = useState<number | null>(null)
useEffect(() => { if (!One.Barometer.isAvailable()) return One.Barometer.setUpdateInterval(1000) const subscription = One.Barometer.addListener((event) => { setPressure(event.pressure) }) return () => subscription.remove() }, [])
if (pressure === null) return null return <Text>{pressure.toFixed(1)} hPa</Text>}The first listener starts the native sensor, so the first event can never race the subscription. Removing the last listener stops the hardware.
isAvailable is synchronous: relative-altitude hardware on iOS, a
pressure sensor on Android. Each event carries pressure in hectopascals
(iOS reports kilopascals and converts), the iOS-only relative altitude
in meters above the first reading, and a timestamp in seconds since
boot. setUpdateInterval paces delivery on Android; on iOS the
altimeter has no interval API, so the call is accepted and ignored and
delivery runs at the hardware rate.
On iOS physical devices need the motion usage description before the
altimeter delivers anything; set native.app.pedometer.usage (see the
pedometer). The interval and listener are
validated before subscribing, throwing on a bad interval or callback.
| Methods | Type | Description |
|---|---|---|
isAvailable() => booleanWhether this device has a barometer. | () => boolean | Whether this device has a barometer. |
setUpdateInterval(intervalMs: number) => voidPace Android delivery. Accepted, ignored on iOS. | (intervalMs: number) => void | Pace Android delivery. Accepted, ignored on iOS. |
addListener(listener: (event: BarometerMeasurement) => void) => BarometerSubscriptionStream pressure events. | (listener: (event: BarometerMeasurement) => void) => BarometerSubscription | Stream pressure events. |
| Measurement | Type | Description |
|---|---|---|
pressurenumberHectopascals. | number | Hectopascals. |
relativeAltitudenumberMeters above the first reading. iOS only. | number | Meters above the first reading. iOS only. |
timestampnumberSeconds since boot. | number | Seconds since boot. |
| Subscription | Type | Description |
|---|---|---|
remove() => voidStop this listener. | () => void | Stop this listener. |
| iOS | Android | Web | |
|---|---|---|---|
| Engine | Altimeter | Pressure sensor | None |
| Pressure | Hectopascals | Hectopascals | Never fires |
| Altitude | Above first | Omitted | Omitted |
| Interval | Ignored | Honored | Ignored |
| Setup | Motion text | Nothing | Nothing |
import { useEffect, useRef, useState } from 'react'import { Text } from 'react-native'import { One } from 'one'
function ElevationGain() { const [gain, setGain] = useState(0) const lowest = useRef<number | null>(null)
useEffect(() => { if (!One.Barometer.isAvailable()) return const subscription = One.Barometer.addListener((event) => { if (event.relativeAltitude === undefined) return if (lowest.current === null) lowest.current = event.relativeAltitude setGain(Math.max(0, event.relativeAltitude - lowest.current)) }) return () => subscription.remove() }, [])
return <Text>Climbed {gain.toFixed(0)} m</Text>}The lowest reading anchors the gain so descents never subtract from the total. The undefined guard keeps Android quiet, where altitude is omitted.
import { One } from 'one'
async function readPressure(timeoutMs = 5000): Promise<number | null> { if (!One.Barometer.isAvailable()) return null One.Barometer.setUpdateInterval(60_000) return new Promise((resolve) => { const timer = setTimeout(() => { subscription.remove() resolve(null) }, timeoutMs) const subscription = One.Barometer.addListener((event) => { clearTimeout(timer) subscription.remove() resolve(event.pressure) }) })}One-shot reads still go through a listener, removing it on the first event. The timeout resolves null where the sensor stays silent, and the minute interval keeps slow polling cheap on Android.
Edit this page on GitHub.