Roomio SDK for React Native
Scan a space from your own scanning screen. <RoomioScanView> shows the camera, the scan as it builds, the SDK's scanning guidance, and the buttons to complete or exit the scan; you start the scan and follow it through a RoomioScanSession.
Works in React Native 0.80 or later with the new architecture, with or without Expo (SDK 56 or later).
Install
npm install https://cdn.roomio.io/sdk/react-native/<version>/roomio-react-native-sdk-<version>.tgz
The package includes the iOS SDK. The Android SDK of the same version comes from the Maven repository at https://cdn.roomio.io/sdk/android/maven, which your app needs to list.
Requirements: iOS 17 or later; Android 7.0 (API 24) or later on an ARCore-supported arm64 phone. Scanning needs a real device.
Expo
Add the plugin, the iOS deployment target and expo-build-properties to your app config, then use a development build (npx expo run:ios, npx expo run:android or EAS Build). Expo Go cannot run the SDK.
{
"expo": {
"ios": { "deploymentTarget": "17.0" },
"plugins": [
["@roomio/react-native-sdk", { "cameraPermission": "The camera is used to scan the space." }],
["expo-build-properties", { "android": { "buildArchs": ["arm64-v8a"] } }]
]
}
}
The plugin adds the camera usage text and the Android SDK's repository, and stops prebuild if the deployment target is below 17. expo-build-properties builds Android for arm64 only.
React Native without Expo
- iOS: add
NSCameraUsageDescriptiontoInfo.plist, and set the deployment target to 17 in yourPodfileand Xcode project. Then runpod install. - Android: add
maven { url "https://cdn.roomio.io/sdk/android/maven"; content { includeGroup "io.captur3d" } }toallprojects.repositoriesinandroid/build.gradle, and setreactNativeArchitectures=arm64-v8ainandroid/gradle.properties.
Use
import { useEffect } from 'react';
import { StyleSheet, View } from 'react-native';
import { Roomio, RoomioScanView } from '@roomio/react-native-sdk';
Roomio.configure('roomio_pub_live_…');
const session = await Roomio.startScan();
function ScanScreen() {
// Recording begins once the user is through the onboarding.
useEffect(() => {
session.start();
}, []);
return (
<View style={{ flex: 1 }}>
<RoomioScanView session={session} style={StyleSheet.absoluteFill} />
</View>
);
}
// When state.type is 'finished':
const bundle = await session.export();
session.close();
// When state.type is 'cancelled', the user exited the scan:
session.close();
API
Roomio.configure(publishableKey) |
Configure the SDK. Call once, first. If Roomio rejects the key, publishable_key_rejected shows in the device log; scanning still works |
Roomio.version |
The SDK version, to quote to Roomio support |
Roomio.flush() |
Send any waiting reports now, in the background. Does nothing while a scan is recording |
Roomio.isSupported() |
supported, supported_needs_update or checking (Android), or unsupported. Offer scanning for anything but unsupported; the scan view handles the ARCore install |
Roomio.startScan({ showsOnboarding }) |
Create a session. It isn't recording yet |
Roomio.exportDiagnostics(scanId?) |
An encrypted diagnostics file for Roomio support |
<RoomioScanView session /> |
The camera, scan, guidance, and the Complete scan and close buttons. One view per session |
<RoomioScanView primaryColor secondaryColor /> |
Your own colours: primaryColor fills the main buttons, secondaryColor is their text and the fill of the others. Roomio's by default |
useRoomioScanSession(session) |
{ state, isShowingOnboarding, isShowingDialog }, re-rendering when they change. Hide your own controls while either is true. state.type is idle, starting, scanning (with tracking), paused, recovering, saving, finished, cancelled or failed (with error) |
session.startPreview() |
Start the camera before recording. iOS only; Android starts it when the view shows, or once the onboarding ends |
session.start() |
Start recording. Call it when you show the view; while the onboarding shows, recording begins once the user finishes or skips it |
session.pause(), resume() |
Pause and resume the recording |
session.stop() |
Finish recording, as the view's Complete scan button does. Rejects with not_ready in the first few seconds of a scan |
session.export() |
The packaged scan, once the state is finished: { path, sizeBytes, scanId }. path is a plain file path (no file://) in the app's private storage, kept until you delete it. scanId can be null |
session.close() |
Release the camera. Call when the user leaves the scan |
session.addListener(listener) |
Tracking, progress, guidance and failure events: { type: 'trackingChanged' | 'progressUpdated' | 'guidanceChanged' | 'failed', … }. Returns a subscription with remove(). Subscribe before start(); past events aren't replayed |
The scan pauses when the app goes to the background and resumes when it returns.
Errors
Promises reject with an Error carrying code, message, severity and isRetryable. code is the SDK's error code, for example permission_denied, not_configured, device_not_supported, not_ready or export_failed. A failure during the scan moves state to { type: 'failed', error }, with error carrying the same fields; the scan has stopped, so close the session.
severity is recoverable (the scan continues) or fatal (the scan has stopped). If isRetryable is true, offer a new scan, or on export_failed call export() again: the scan is kept. There's no cancel(): close() discards an unfinished scan.
On the web, importing the package is safe: isSupported() resolves unsupported and <RoomioScanView> renders nothing.