npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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.

npm npm downloads license

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-crowdconnected

iOS

cd ios && pod install

Your 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 key
  • clientId - CrowdConnected client ID
  • clientSecret - CrowdConnected client secret
  • navigationType - Positioning type: 'all' (GPS + IPS), 'GEO' (GPS only), 'IPS' (indoor only)
  • isBackgroundUpdateEnabled - Enable background location updates
  • isBluetoothEnabled - Enable Bluetooth-based positioning
  • isHeadingEnabled - Enable compass/heading tracking
  • aliases? - 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 the sid session ID and exp claims)
  • 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 prepare

Commands

  • yarn lint - Run ESLint
  • yarn typecheck - Check TypeScript types
  • yarn test - Run Jest tests
  • yarn example ios - Run iOS example app
  • yarn example android - Run Android example app
  • yarn clean - Clean build artifacts

Support