Skip to content

Expo (Managed / CNG)

Expo apps do not need the manual Platform Setup. The Alphyn package ships an Expo config plugin that applies the same native changes automatically during expo prebuild (which EAS Build runs for you in the cloud). You never edit native files and you do not eject.

  • A development build or EAS Build. Expo Go is not supported. Alphyn is native code and cannot load in Expo Go; use expo-dev-client locally or EAS Build. This is not an eject.
  • Expo SDK 53+, iOS 15.0+, Android minSdkVersion 26.
  • Android ABI: arm64-v8a, armeabi-v7a or x86_64. The engine ships native libraries for all three, so an ordinary x86_64 emulator works. 32-bit x86 is not shipped.
  • iOS: Apple-silicon simulators only. Alphyn.xcframework carries ios-arm64 and ios-arm64-simulator; there is no x86_64 simulator slice, so an Intel Mac cannot run it in the simulator.

From alphyn-cli 1.9.0, the CLI wires up a managed Expo project for you. Run it in the project root:

Terminal window
alphyn integrate --android-api-key <your Android app key> --ios-api-key <your iOS app key>

It declares the @alphyn/react-native-sdk dependency from the Alphyn package registry, writes the authenticated .npmrc that resolves it, and registers the config plugin in app.json. No tarball is vendored. alphyn remove reverses all three and returns package.json and app.json byte for byte.

One case it deliberately does not touch: if your project configures itself through app.config.js, app.config.ts or app.config.mjs, the CLI stops and prints the single line to add. Those files are JavaScript that Expo evaluates at prebuild, so their result cannot be known by reading them, and rewriting code whose output cannot be predicted is not something the CLI will do to your project. Everything else (the dependency and the registry .npmrc) is still handled for you.

integrate edits your project files; the native ios/ and android/ folders are generated when Expo builds, not by you. Two steps remain:

  1. Export your registry key so the build resolves the SDK’s native binaries from the registry (an EAS secret in the cloud, or an env var locally). It is your app API key; see SDK Registry Access:

    Terminal window
    export ALPHYN_REGISTRY_KEY=<YOUR_APP_API_KEY>
  2. Install, then make a development or EAS build. Use your project’s own package manager, then a build command that runs expo prebuild for you. A managed Expo project has no ios/ folder until prebuild, so do not run cd ios && pod install:

    Terminal window
    npm install # or: yarn / pnpm, whichever your project uses
    npx expo run:ios # or: run:android, a local dev build (runs prebuild and installs pods)
    # or build in the cloud:
    eas build

Check your setup at any time:

Terminal window
alphyn doctor

It reports what it can verify from your project and says plainly what it could not check - an evaluated app.config, or build-time API keys that live in an EAS secret it cannot see, are reported as unverified rather than as failures.

Everything the CLI does, you can do by hand.

You receive the SDK as a key-gated tarball from SDK Downloads (with your API key); the package is not published to public npm. Vendor it into your app and reference it as a file: dependency:

{
"dependencies": {
"@alphyn/react-native-sdk": "file:./vendor/alphyn-react-native-sdk-<version>.tgz"
}
}

Use a version-stamped filename and bump it for each new SDK release, so npm/yarn never serve a stale cached copy.

{
"expo": {
"plugins": ["@alphyn/react-native-sdk"]
}
}

For a development build, pin the debug hash so the SDK accepts your debug binaries:

{
"expo": {
"plugins": [
["@alphyn/react-native-sdk", { "iosDebugHash": "<64-hex>", "androidDebugHash": "<64-hex>" }]
]
}
}

You do not configure the attestation or signature host anywhere: the plugin reads them from the SDK’s build metadata, so they always match the binary you were issued.

The SDK’s AAR declares minSdkVersion 26, so an app below it fails the Android manifest merge.

{
"expo": {
"plugins": [["expo-build-properties", { "android": { "minSdkVersion": 26 } }]]
}
}

Your app API key does two jobs at build time, and both read it from the environment (an EAS secret in the cloud, or an env var locally):

  • Resolve the native binaries. The SDK’s native AAR and iOS framework are fetched from the Alphyn package registry during the build, so set ALPHYN_REGISTRY_KEY. Without it the Android Gradle build cannot resolve com.byterialab:alphyn-sdk and pod install cannot fetch Alphyn.xcframework. See SDK Registry Access.
  • Register the build. So each build enrolls its hash with the backend, set ALPHYN_IOS_API_KEY (iOS archive) and ALPHYN_ANDROID_API_KEY (Android build). A build with no registration key still compiles, but the app fails attestation until the build is registered.
Terminal window
eas build # cloud
npx expo run:ios # local dev build
npx expo run:android # local dev build

That is the whole integration. The config plugin starts the SDK at launch on both platforms (it installs the launch initializer in the iOS AppDelegate and the Android auto-init) and wired build registration for you, so you do not add an AlphynSDK.initialize() call yourself; a manual call is a safe no-op, because the launch init has already started the SDK through a shared gate. Import the SDK from JavaScript only when you need its API (device state, events, scan results), as in Initialization.

In a workspaces monorepo the SDK package is hoisted above your app. 1.3.0 supports this layout: the config plugin resolves the package rather than assuming it sits in the app’s own node_modules, so prebuild and the register hook find it wherever it is hoisted. The SDK’s AAR resolves from the Alphyn package registry wired at the project root, so it is unaffected by hoisting.

On releases up to and including 1.2.0 both halves assumed the flat layout, with two different symptoms. prebuild reported the package as missing and the Android register hook could not find its script, so the build succeeded with a warning and shipped an unregistered binary - the dangerous one, because nothing failed. Gradle separately failed to resolve the AAR with Could not find com.byterialab:alphyn-sdk:<version>, which names neither hoisting nor the path.

If you are pinned to one of those versions, install the SDK in the app’s own node_modules (an nohoist / .npmrc public-hoist-pattern entry, depending on your package manager) rather than at the workspace root.