@expofp/react-native-efp-crowdconnected
v0.1.11
Published
React Native wrapper for ExpoFP around CrowdConnected SDK
Readme
@expofp/react-native-efp-crowdconnected
React Native Turbo Module for CrowdConnected location tracking and indoor positioning services. Provides cross-platform access to GPS, IPS (Indoor Positioning System), and Bluetooth-based positioning on iOS and Android.
Features
- 📍 Multi-positioning support: GPS, Indoor Positioning (IPS), and Bluetooth
- 📱 Cross-platform: Native iOS (Swift) and Android (Kotlin) implementations
- ⚡ React Native New Architecture: Built as a Turbo Module for optimal performance
- 🔔 Event-based: Real-time location updates via event listeners
- 🔄 Background support: Optional background location updates
- 🎯 Heading tracking: Compass/bearing information
- 📦 TypeScript first: Full type safety with generated type definitions
Requirements
- Android 7.0+ (API level 24+)
- iOS 16.0+ (required by the bundled CrowdConnected SDK)
Installation
npm install @expofp/react-native-efp-crowdconnected
# or
yarn add @expofp/react-native-efp-crowdconnectediOS
cd ios && pod installYour host app's Info.plist must declare the relevant location/Bluetooth usage descriptions and UIBackgroundModes entries. See example/ios/ExpofpCrowdconnectedExample/Info.plist for a working configuration.
Android
Gradle resolves the dependencies automatically. The CrowdConnected SDK AARs (net.crowdconnected.android.{core,background,geo,ips}, fetched from CrowdConnected's Maven repository) contribute the foreground-service declaration and the following permissions via Gradle's manifest merger. You do not need to declare them in your host app's AndroidManifest.xml: INTERNET, ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, FOREGROUND_SERVICE, FOREGROUND_SERVICE_LOCATION, BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and the legacy BLUETOOTH / BLUETOOTH_ADMIN (maxSdkVersion=30).
If you set isBackgroundUpdateEnabled: true, your host app must also declare:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />ACCESS_BACKGROUND_LOCATION cannot be granted from the standard runtime prompt on Android 11+; the system redirects the user to the app's settings screen, where they must select "Allow all the time".
Quick Start
import { CrowdConnectedLocationProvider } from '@expofp/react-native-efp-crowdconnected';
// Initialize
await CrowdConnectedLocationProvider.setup({
appKey: 'your-app-key',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
navigationType: 'all', // 'all' | 'GEO' | 'IPS'
isBackgroundUpdateEnabled: false,
isBluetoothEnabled: true,
isHeadingEnabled: true,
});
// Listen to location updates
const unsubscribe = CrowdConnectedLocationProvider.onLocationChange((position) => {
console.log('Location:', position);
// { lat: number, lng: number, x?: number, y?: number, z?: string | number, angle?: number }
});
// Listen to errors
const unsubscribeError = CrowdConnectedLocationProvider.onError((error) => {
console.error('Location error:', error);
});
// Start tracking
CrowdConnectedLocationProvider.startUpdatingLocation();
// Check if location tracking is active
const isUpdating = await CrowdConnectedLocationProvider.isLocationUpdating();
// Stop tracking
CrowdConnectedLocationProvider.stopUpdatingLocation();
// Cleanup
unsubscribe();
unsubscribeError();API Reference
setup(settings: ExpoFpLocationSettings): Promise<ExpoFpProviderInfo>
Initializes the CrowdConnected SDK with configuration.
Parameters:
appKey- CrowdConnected application keyclientId- CrowdConnected client IDclientSecret- CrowdConnected client secretnavigationType- Positioning type:'all'(GPS + IPS),'GEO'(GPS only),'IPS'(indoor only)isBackgroundUpdateEnabled- Enable background location updatesisBluetoothEnabled- Enable Bluetooth-based positioningisHeadingEnabled- Enable compass/heading trackingaliases?- Custom location aliases (optional)
Returns: Promise resolving to ExpoFpProviderInfo ({ deviceId?, isLocationUpdating })
startUpdatingLocation(): Promise<ExpoFpProviderInfo>
Starts location tracking.
stopUpdatingLocation(): Promise<ExpoFpProviderInfo>
Stops location tracking.
isLocationUpdating(): Promise<ExpoFpProviderInfo>
Returns the current provider state.
onLocationChange(callback: (position: ExpoFpPosition) => void): Unsubscribe
Subscribes to location updates.
Position object:
{
lat?: number; // Latitude
lng?: number; // Longitude
x?: number; // X coordinate (indoor)
y?: number; // Y coordinate (indoor)
z?: string|number; // Z coordinate (floor/level)
angle?: number; // Heading in degrees
}Returns: Unsubscribe function
onError(callback: (error: Error) => void): Unsubscribe
Subscribes to location errors.
Returns: Unsubscribe function
Simulation Mode
Simulation mode replays GPS/IPS paths on the device without physical movement. Simulated positions arrive through the regular onLocationChange listener.
const simulationToken = '<signed JWT for the simulation session>';
// The SDK must already be started (startUpdatingLocation) before activating.
const unsubConnected = CrowdConnectedLocationProvider.onSimulationConnected(() => {
console.log('Simulation connected');
});
const unsubDisconnected = CrowdConnectedLocationProvider.onSimulationDisconnected(() => {
console.log('Simulation disconnected');
});
const unsubError = CrowdConnectedLocationProvider.onSimulationError((error) => {
console.error('Simulation error:', error.message);
});
CrowdConnectedLocationProvider.activateSimulation(simulationToken);
// ...later
CrowdConnectedLocationProvider.deactivateSimulation();
// Cleanup
unsubConnected();
unsubDisconnected();
unsubError();activateSimulation(token: string): void
Starts a simulation session. Fire-and-forget: the outcome is reported via the onSimulationConnected / onSimulationError events.
token- A signed JWT issued for the simulation session (contains thesidsession ID andexpclaims)- The SDK must already be started via
startUpdatingLocation() - Calling it again replaces the current session
- Deactivate the simulation before calling
stopUpdatingLocation()when a session is active
deactivateSimulation(): void
Stops the active simulation session. Safe no-op when no session is active.
onSimulationConnected(callback: () => void): Unsubscribe
Fires when the simulation session is established.
onSimulationDisconnected(callback: () => void): Unsubscribe
Fires when the simulation session ends.
onSimulationError(callback: (error: Error) => void): Unsubscribe
Fires when the simulation session fails (e.g. invalid or expired token).
Development
Setup
yarn install
yarn prepareCommands
yarn lint- Run ESLintyarn typecheck- Check TypeScript typesyarn test- Run Jest testsyarn example ios- Run iOS example appyarn example android- Run Android example appyarn clean- Clean build artifacts
