One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Light Sensor

Ambient light level in lux from the device light sensor

One.LightSensor streams the ambient light level in lux. Reach for it for auto-brightness companions, day and night theming, and camera exposure hints.

On Android it reads the light sensor through SensorManager. On iOS there is no public ambient light API, so the sensor reads unavailable and listeners never fire. On web the generic-sensor AmbientLightSensor supplies live lux where the browser has it.

Usage

import { useEffect, useState } from 'react'
import { Text } from 'react-native'
import { One } from 'one'
function LightLevel() {
const [lux, setLux] = useState<number | null>(null)
useEffect(() => {
if (!One.LightSensor.isAvailable()) return
One.LightSensor.setUpdateInterval(1000)
const subscription = One.LightSensor.addListener((event) => {
setLux(event.illuminance)
})
return () => subscription.remove()
}, [])
if (lux === null) return null
return <Text>{lux.toFixed(0)} lux</Text>
}

Availability gates the subscription, so iOS renders nothing instead of an empty stream. The interval keeps delivery to one event per second.

How it works

isAvailable is synchronous: a light sensor on Android, always false on iOS. Each event carries illuminance in lux and a timestamp: seconds since boot on Android, Unix seconds on web, so compare timestamps only within one platform. setUpdateInterval paces Android delivery. The first listener starts the native sensor and the last remover stops it.

API reference

MethodsTypeDescription
isAvailable() => booleanWhether this device reports light.
() => booleanWhether this device reports light.
setUpdateInterval(intervalMs: number) => voidPace Android delivery.
(intervalMs: number) => voidPace Android delivery.
addListener(listener: (event: LightSensorMeasurement) => void) => LightSensorSubscriptionStream lux events.
(listener: (event: LightSensorMeasurement) => void) => LightSensorSubscriptionStream lux events.
MeasurementTypeDescription
illuminancenumberAmbient light in lux.
numberAmbient light in lux.
timestampnumberBoot seconds on Android, Unix seconds on web.
numberBoot seconds on Android, Unix seconds on web.
SubscriptionTypeDescription
remove() => voidStop this listener.
() => voidStop this listener.

Platform differences

iOSAndroidWeb
EngineNone publicLight sensorGeneric sensor
AvailableNeverWith sensorWith browser API
TimestampNoneBoot secondsUnix seconds

Limits and gotchas

Examples

Switch theme by ambient light

import { useEffect, useState } from 'react'
import { One } from 'one'
function useAmbientTheme() {
const [dark, setDark] = useState(false)
useEffect(() => {
if (!One.LightSensor.isAvailable()) return
const subscription = One.LightSensor.addListener((event) => {
setDark(event.illuminance < 30)
})
return () => subscription.remove()
}, [])
return dark ? 'dark' : 'light'
}

A 30-lux threshold splits dim rooms from lit ones without flickering at the boundary of a single reading. Manual theme choice should still win over this signal.

Sample light without streaming

import { One } from 'one'
async function readLight(timeoutMs = 5000): Promise<number | null> {
if (!One.LightSensor.isAvailable()) return null
return new Promise((resolve) => {
const timer = setTimeout(() => {
subscription.remove()
resolve(null)
}, timeoutMs)
const subscription = One.LightSensor.addListener((event) => {
clearTimeout(timer)
subscription.remove()
resolve(event.illuminance)
})
})
}

One-shot reads subscribe and remove on the first event, with a timeout that resolves null where the sensor stays silent.

Edit this page on GitHub.