Skip to main content

Installation

Requirements

The SDK is a native module, so it does not run in Expo Go. A custom dev client or a bare React Native project is required.

Install the Package

Then, for iOS:
That is the whole installation. Autolinking handles both platforms, so you do not need a pod entry, a post_install hook, a settings.gradle include, or a MainApplication registration. Pre-built native libraries ship in the package for both platforms. pod install should list MeshSdk under “Auto-linking React Native modules”. The iOS native binary ships as an XCFramework, so CocoaPods picks the right slice per build SDK and device and simulator builds both work with no linker configuration.
Upgrading from a version below 0.20.0? Delete these from your ios/Podfile. They now break the build:
  1. Any pod 'MeshSdk', ... line, with or without :modular_headers => true. A surviving line pointing into .../mesh-sdk/ios fails pod install outright with a “no podspec found” error.
  2. Any post_install hook that configured MeshSdk, in particular one setting DEFINES_MODULE, SWIFT_INCLUDE_PATHS, LIBRARY_SEARCH_PATHS, or OTHER_LDFLAGS.
  3. Any flag naming offline_protocol_uniffi_sim or offline_protocol_uniffi_device. Those archives no longer exist and linking them fails with library not found.
Simulator builds work from 0.20.0 onward. If you previously concluded this SDK was device-only, that was a packaging bug, and any workaround you carried must be removed.

iOS Setup

Info.plist

Both background modes are effectively mandatory: the SDK creates its central manager with a state-restoration identifier, which CoreBluetooth only honors when bluetooth-central is declared.

Additional keys for Wi-Fi Direct

The iOS Wi-Fi Direct path uses MultipeerConnectivity. iOS 14+ refuses local-network discovery without these:
The Bonjour service names must match the SDK’s MultipeerConnectivity service type, which is offline-proto. MultipeerConnectivity registers both the TCP and UDP variants, so declare both.
No entitlements or capabilities are required. The pod links Foundation, CoreBluetooth, and MultipeerConnectivity.

Android Setup

What the SDK already declares

The SDK ships its own AndroidManifest.xml, and these entries merge into your app automatically, so you do not need to copy them:
The neverForLocation flag on BLUETOOTH_SCAN and the maxSdkVersion="30" gating propagate into your merged manifest. neverForLocation has Play Console data-safety implications you inherit, so it is worth knowing it is there.

What your app must declare

The SDK deliberately does not force these on consumers, but the code requires them:
POST_NOTIFICATIONS is easy to miss. start() unconditionally launches a foreground service that posts a “Mesh Active” notification with a Stop action. On Android 13+ that notification is silently suppressed without the runtime grant, so users get no way to see or stop the mesh.

ProGuard / R8

Nothing to configure. The SDK ships consumerProguardFiles, so its keep rules are applied to your release build automatically. Without them, release builds would silently lose the BLE mesh transport while debug builds kept working, but the rules are already handled for you.

Runtime Permissions

Android

The SDK checks permissions but never requests them. Your app must request them before calling start(), or the SDK emits a diagnostic event at error level with “Missing Bluetooth permissions”.
BLUETOOTH and BLUETOOTH_ADMIN are install-time permissions on API 30 and below, so they do not need a runtime request. You can also check and prompt for Bluetooth itself:

iOS

No runtime API call is needed. The system prompts on first CoreBluetooth use, driven by the Info.plist usage descriptions.

Optional: Android Mesh Wake

This is the only manual native edit the SDK requires, and only if you want the mesh to recover after Android kills your process. Add to your app’s AndroidManifest.xml, inside <application>:
Then register the task at module scope in index.js, not inside a component:
Both halves are required; the manifest flag alone does nothing. See registerMeshWakeTask for the four caller obligations.
Mesh wake requires React Native 0.76.5+ when the New Architecture is enabled. Headless tasks did not work under bridgeless before 0.76 and were patchy until 0.76.5. On RN 0.84 and 0.85 a core bug (fixed in 0.86) can leave the wake service running after the task finishes.

Troubleshooting

Linking error

If you see the “doesn’t seem to be linked” error:
  1. Run pod install (iOS) and rebuild natively. A JS-only reload will not pick up native changes.
  2. Confirm pod install output lists MeshSdk under “Auto-linking React Native modules”.
  3. Run npx react-native config and check platforms.ios.podspecPath ends in MeshSdk.podspec.
  4. Remove any leftover manual pod 'MeshSdk' line; it can shadow the autolinked pod.
  5. Verify you are not using Expo Go.
Undefined symbols, or “building for iOS Simulator, but linking in object file built for iOS”, means a leftover manual post_install hook is still linking archives by hand. Remove it per the upgrade warning above.

Upgrading to 0.21.0

A native rebuild is required, because new source files are compiled in on both platforms. Run pod install for iOS. A JS-only update will not pick them up.
Downgrading is not a rollback. The first launch on 0.21.0 moves delivery state out of the credential store into the app container and deletes the old copy. An older build comes up with an empty outbox, an empty pending queue, and an empty block list, meaning every previously blocked peer is silently unblocked. Roll forward with a hotfix rather than reverting the binary.

Next Steps

Set up the SDK in your app