A cross-platform React Native module for accessing the device proximity sensor using the New Architecture (JSI/TurboModules).
- ✅ Cross-platform: Works on both iOS and Android
- ✅ New Architecture: Built with TurboModules for optimal performance
- ✅ TypeScript: Full TypeScript support with type definitions
- ✅ Event-driven: Subscribe to proximity changes in real-time
- ✅ Sensor validation: Check if the proximity sensor is available and functional
npm install react-native-proximityor
yarn add react-native-proximityimport {
isProximityAvailable,
addProximityListener,
removeProximityListener,
validateSensor
} from 'react-native-proximity';
// Check if proximity sensor is available
const available = await isProximityAvailable();
console.log('Proximity sensor available:', available);
// Subscribe to proximity changes
const subscription = addProximityListener((data) => {
console.log('Near:', data.near);
console.log('Distance (Android only):', data.distance);
});
// Validate sensor functionality
const validation = await validateSensor(2000); // 2 second timeout
console.log('Sensor works:', validation.ok);
console.log('Reason:', validation.reason);
console.log('Samples received:', validation.samples);
// Unsubscribe when done
subscription.remove();
// or
removeProximityListener();Checks if the proximity sensor is available on the device.
Returns: Promise<boolean> - true if sensor is available, false otherwise.
Example:
const available = await isProximityAvailable();Subscribes to proximity sensor changes.
Parameters:
callback: Function called when proximity changesdata.near(boolean):trueif object is near the sensordata.distance(number | null): Distance in cm (Android only,nullon iOS)
Returns: EmitterSubscription - Subscription object with .remove() method
Example:
const subscription = addProximityListener((data) => {
if (data.near) {
console.log('Object detected nearby!');
}
});
// Later...
subscription.remove();Removes all proximity listeners. Alternative to calling .remove() on the subscription.
Example:
removeProximityListener();Validates that the proximity sensor is functional.
Parameters:
timeoutMs(number): Timeout in milliseconds (Android only, ignored on iOS)
Returns: Promise<ValidationResult>
ok(boolean):trueif sensor is functionalreason(string): Reason code (see Platform Differences below)samples(number): Number of sensor events received
Example:
const result = await validateSensor(2000);
if (result.ok) {
console.log('Sensor is working!');
} else {
console.log('Sensor issue:', result.reason);
}- Type: Continuous sensor that reports distance values
- Data: Returns actual distance in centimeters (typically 0-5cm range)
- Events: Fires continuously at high frequency when registered
- Validation: Counts sensor events during timeout period
- Uses the
timeoutMsparameter to wait for sensor events - Registers sensor with
SENSOR_DELAY_FASTESTfor maximum sampling - Counts how many events are received during the timeout
- Returns validation result based on event count:
NO_EVENTS_IN_TIMEOUT: Sensor didn't respondTOO_FEW_EVENTS__DOUBTFUL: Only 1 event received (suspicious)EVENTS_RECEIVED: Multiple events received (sensor working)
Example result:
{
ok: true,
reason: "EVENTS_RECEIVED",
samples: 47 // Received 47 events in 2 seconds
}// Android proximity logic
const near = distance < 5.0; // Object within 5cm threshold- Type: Binary sensor (near/far states only)
- Data: Only boolean state, no distance values
- Events: Only fires when state changes (covered ↔ uncovered)
- Validation: Checks if sensor can be enabled
- Ignores
timeoutMsparameter (validation is instant) - Simply attempts to enable
proximityMonitoringEnabled - Checks if the property successfully changed
- Immediately disables sensor after check
- Returns result instantly:
SENSOR_AVAILABLE: Sensor can be enabledSENSOR_NOT_AVAILABLE: Sensor cannot be enabled
Example result:
{
ok: true,
reason: "SENSOR_AVAILABLE",
samples: 1 // Always 1 if available on iOS
}// iOS proximity logic
const near = device.proximityState; // true/false only
const distance = null; // iOS doesn't provide distance| Feature | Android | iOS |
|---|---|---|
| Sensor Type | Continuous | Binary (event on state change) |
| Distance Value | ✅ Yes (0-5cm typically) | ❌ No (null) |
| Event Frequency | High (hundreds/sec) | Low (only on state change) |
validateSensor Duration |
Uses timeoutMs |
Instant (ignores timeoutMs) |
| Validation Method | Count events in timeout | Check if sensor enables |
Typical samples Value |
20-100+ | Always 1 (if available) |
| Thread Safety | Handler-based | Main thread dispatched |
- The proximity sensor must be available for the validation to succeed
- Validation requires the sensor to emit events, so results may vary if the sensor is already covered
- Battery usage: Sensor uses power, so only enable when needed
- Thread-safe implementation using
AtomicIntegerfor listener counting
- The sensor only notifies on state changes, not continuously
distancewill always benullin the callback data- Validation is instant and doesn't require user interaction
- The sensor may not work if covered when first enabled
- All sensor operations are dispatched to the main thread for safety
- Make sure the device has a proximity sensor (some tablets don't)
- Check if sensor is already covered when enabling
- Try a longer timeout (3000-5000ms)
- This is normal! iOS only fires events on state changes
- Move your hand near/away from the sensor to trigger events
- Don't rely on event count for validation on iOS
- Check if the listener was properly removed and re-added
- Ensure the app is in the foreground
- On Android, check if the sensor was unregistered
import { addProximityListener } from 'react-native-proximity';
import { useState, useEffect } from 'react';
function ProximityScreenLock() {
const [isNear, setIsNear] = useState(false);
useEffect(() => {
const subscription = addProximityListener((data) => {
setIsNear(data.near);
if (data.near) {
// Turn off screen or pause video
console.log('Object nearby - locking screen');
} else {
// Turn on screen or resume video
console.log('Object moved away - unlocking screen');
}
});
return () => subscription.remove();
}, []);
return (
<View>
<Text>Proximity: {isNear ? 'NEAR' : 'FAR'}</Text>
</View>
);
}See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT
Made with create-react-native-library