Reader SDK Documents
Breadcrumbs

IFU011(01) Reader SDK React Native Integration Guide

Novarum DX Ltd
Instructions for Use / Guides

Document ID: IFU011
Revision: 01
Released: Dec 19, 2025

1. Overview

The Novarum SDK enables React Native applications to capture and analyze lateral flow tests using the device’s camera.
It handles camera setup, image analysis, and result delivery, allowing developers to focus on interpreting and presenting test results in their own UI.

This guide describes how to integrate the SDK into an React Native project using NPM.

2. Project Setup

2.1. Minimum Requirements

Requirement

Version

Expo SDK

52

Android compileSdk

26

iOS Minimum Deployment Target

15.1

2.2. AWS CLI Configuration

Access to the Novarum SDK Maven repository is provided via AWS CodeArtifact.
Before adding the dependency, you must install and configure the AWS CLI.

2.2.1. Installation

Refer to AWS Command Line Interface for installation details.
On macOS, you can install via Homebrew:

Bash
brew install awscli

2.2.2. Profile Configuration

You’ll need the AWS credentials provided by Novarum.

Interactive setup:

Bash
aws configure --profile ndxcodeartifact

You’ll be prompted for:

  • Access Key ID

  • Secret Access Key

  • AWS Region (e.g., eu-west-2)

For non-interactive environments (CI, build agents), configure directly:

Bash
aws configure set aws_access_key_id "${ECR_KEY}"
aws configure set aws_secret_access_key "${ECR_SECRET}"
aws configure set region "${AWS_REGION}"

2.3. NovarumDX NPM Registry Configuration

Setup NPM to have access to the NovarumDX NPM registry by running the codeartifact login command.

This will add the @novarumdx registry and it's authentication token to your ~/.npmrc to enable NPM or yarn to find NovarumDX packages.

Bash
aws codeartifact login --tool npm --domain novarumdx --domain-owner 945969778369 --repository novarum.client.npm --profile ndxcodeartifact --namespace novarumdx

2.3.1. Module Installation

Since version 3.0.0, the NPM module is self contained, including all native dependencies, bundling the iOS XCFramework and AAR dependencies files by leveraging Expo version 52 features.

Previous versions of ndx-imaging-expo required separate, Maven and Git authentication as well as Git-LFS, this is no longer required as of version 3.0.0.

By installing the NPM module you also download and link the required native dependencies.

npm install @novarumdx/ndx-imaging-expo

Or

yarn add @novarumdx/ndx-imaging-expo

Otherwise manually edit the package.json of your project dependencies section.

JSON
  "dependencies": {
    "@novarumdx/ndx-imaging-expo": "3.0.0"
  }

2.4. Expo Configuration

The minimum deployment targets can be configured in Expo app.json using the expo-build-properties plugin.

JSON
    "plugins": [
      [
        "expo-build-properties",
        {
          "ios": {
            "deploymentTarget": "15.1"
          },
          "android": {
            "minSdkVersion": 26
          }
        }
      ]
    ]

2.5. Camera Permissions Configuration

The SDK requires access to the camera. Camera permissions message can be configured in expo using the included @novarumdx/ndx-imaging-expo plugin.

If no camera permissions message is provided then a default of "Allow $(PRODUCT_NAME) to access your camera" is used if the plugin is used to request permissions.

      [
        "@novarumdx/ndx-imaging-expo",
        {
          "cameraPermission": "camera permission message",
        }
      ]

Request camera permission before displaying NdxImagingExpoView.

2.5.1. Camera Permissions Request Example

TypeScript
import React from "react";
import { View, Text, Button } from "react-native";
import { useCameraPermissions } from "@novarumdx/ndx-imaging-expo";

function AppContent() {
  return <Text>Camera is ready. Your app goes here.</Text>;
}

export default function App() {
  const [permission, requestPermission] = useCameraPermissions();

  // Permission state is still loading
  if (!permission) {
    return (
      <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
        <Text>Loading...</Text>
      </View>
    );
  }

  // Permission not granted yet: show a button to request
  if (!permission.granted) {
    return (
      <View style={{ flex: 1, alignItems: "center", justifyContent: "center", padding: 16 }}>
        <Text style={{ textAlign: "center", marginBottom: 16 }}>
          We need camera access to continue.
        </Text>
        <Button title="Grant Camera Permission" onPress={requestPermission} />
      </View>
    );
  }

  // Permission granted: render the app
  return <AppContent />;
}

3. Using the Reader View

The Novarum Analyzer Preview is the primary camera component used to display the live feed and perform the test analysis.

3.1. Loading the Analyzer Configuration

Load the analyzer configuration JSON file you were provided by Novarum:

TypeScript
import testConfigJson from './assets/test-config.json';
const testInfoJson = JSON.stringify(testConfigJson);

3.2. Displaying The Reader View

TypeScript
import { NdxImagingExpoView } from 'ndx-imaging-expo';
import testConfigJson from './assets/test-config.json';

export function ScannerPage({ navigation }) {
  const cameraRef = useRef<any>(null);
  const testInfoJson = JSON.stringify(testConfigJson);

  const handleAbort = () => {
    if (cameraRef.current) {
      cameraRef.current.abort();
    }
  };

  return (
    <View style={styles.container}>
      <NdxImagingExpoView
        ref={cameraRef}
        style={styles.camera}
        testInfoJson={testInfoJson}
        previewMode="Fit"
        onFrameCaptured={({ nativeEvent }) => {
          const { frame } = nativeEvent;
          console.log('Frame progress:', frame.progress);   // 0.0-1.0
          console.log('PMF Status:', frame.resultPMF);      // "Fit" | "MarginalFit" | "NoFit"
          console.log('Lux:', frame.lux);                   // Light level
          console.log('Orientation:', frame.orientation);   // [roll, pitch, yaw]
        }}
        onComplete={({ nativeEvent }) => {
          const { resultModel } = nativeEvent;
          console.log('Scan complete!');
          console.log('Frames captured:', resultModel.pmfStory.length);
          navigation.navigate('ResultDetail', resultModel);
          // resultModel.pmfStory - array of captured frames
          // resultModel.testStrips - analyzed test strips with T/C lines
          // resultModel.testConfiguration - test parameters used
        }}
        onAbort={({ nativeEvent }) => {
          const { resultModel } = nativeEvent;
          console.log('Scan aborted');
          navigation.navigate('ResultDetail', resultModel);
          // Contains partial results up to abort
          // May contain some images if scan was partially complete
        }}
      />
      <Button onPress={handleAbort} title="Abort Scan" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
  camera: {
    flex: 1,
  },
});

3.3. Parameter Overview

Parameter

Type

Description

testInfoJson

json string

The analyzer configuration JSON object defining the test setup and analysis parameters.

onComplete

CompleteEvent

Invoked when the analysis successfully completes. Provides the full analysis result.

onAbort

AbortEvent

Called when the scan is aborted manually via cameraRef.current.abort(). Returns partial results or null if none collected.

onFrameCaptured

FrameCapturedEvent

Triggered for every frame processed by the reader. Useful for updating progress indicators or monitoring lighting/orientation.

previewMode

PreviewMode

Controls camera scaling within the view. Options:

  • "Fill" – fills the container (may crop edges).

  • "Fit" – fits entirely within the view while maintaining aspect ratio.

To abort a running scan, call cameraRef.current.abort() on the NdxImagingExpoView instance.

The onAbort callback will then receive the partial analysis data.

3.4. Callback Data Structures

The SDK exposes several structured models representing frame-level and result-level data.

3.4.1. FrameCapturedCallback

TypeScript
export type FrameCapturedCallback = {
  /** Fractional progress of the capture or analysis (0.0 to 1.0). */
  progress: Float;
  /** Result from the Point Model Fitter (PMF) analysis. */
  resultPMF: keyof typeof ResultPMF;
  /** Statuses of detected strips in the frame. */
  stripStatuses: (keyof typeof StripStatus)[];
  /** Device or image orientation as [roll, pitch, yaw] (Euler angles). */
  orientation: Double[];
  /** Ambient light level in lux. */
  lux: Float;
};

3.4.2. ResultModel

TypeScript
/**
 * Contains the results of the image analysis process.
 */
export type ResultModel = {
  /** List of analysed test strips and their results. */
  testStrips: TestStrip[];
  /** Sequence of frame data captured during the scan. */
  pmfStory: FrameDataRecord[];
  /** The configuration used for the test. */
  testConfiguration: TestConfigurationRecord;
};

3.5. Related Data Types

Type

Description

ResultPMF

Indicates the per-frame fit result (Fit, MarginalFit, NoFit).

StripStatus

Indicates strip condition (None, ExposureError, BaselineError, Good, Done).

TestStrip

Contains data for one analyzed strip (C-line, T-lines, profiles, baselines).

FrameDataRecord

Metadata for each captured frame (lighting, homography, orientation, etc.).

TestConfigurationRecord

Configuration parameters used for the test analysis.

For full type definitions, refer to the generated documentation within Android Studio.

3.6. Behaviour Notes

  • previewMode determines how the live camera preview scales to your layout. Fill (default) maximizes coverage, while Fit ensures full frame visibility.

  • The cameraRef.current.abort() method immediately stops scanning and triggers onAbort, returning partial data.

3.7. Optional: SVG Overlay Visualisation

The SDK supports an optional SVG-based overlay rendering mode for higher-quality graphics and scalable test result visuals.

  • Default visualisation mode: dotMatrix

  • To enable SVG overlays, request an updated Analyser Configuration File from Novarum support.

  • No code changes are required — the overlay mode is controlled via configuration.

4. Version Compatibility Summary

Component

Current Version

Notes

Novarum Expo SDK

v3.0.0

Current release

Minimum Android SDK

26

Required

Android compileSdk

36

Required

Java / JVM Target

17

Required

OpenCV

4.12.0

Internal dependency

NDK

29.0.14033849 rc4

Required for native builds

CMake

3.22.1

Required for native builds

Minimum iOS Target

15.1

Required by Expo 54

5. Support & Troubleshooting

Issue

Possible Cause

Resolution

Build fails with “invalid target JDK”

Using JDK 11 or 1.8

Update Gradle JDK to 17

AGP / Gradle mismatch

AGP < 8.9.0

Update Android Gradle Plugin to 8.9.0 and Gradle Wrapper to 8.11.1

Cannot access CodeArtifact

Invalid or expired AWS token

Regenerate token or verify AWS CLI profile

Camera not activating

Missing Info.plist or android manifest permission

Ensure NSCameraUsageDescription is set correctly.

For access credentials, configuration files, or integration assistance, please contact your Novarum support representative or technical account manager.

 

For streamlined support and rapid troubleshooting, users can access the https://novarum.atlassian.net/servicedesk/customer/portal/15. This portal provides a direct channel for submitting integration queries, reporting issues, and tracking the status of your requests. In addition, the service desk is equipped with an intelligent agent capable of answering common technical questions and guiding you through standard troubleshooting steps.

We recommend using this resource for the fastest resolution of SDK-related issues or to obtain up-to-date technical guidance.

6. Document History

Revision

Summary

Date

01

Initial revision for 3.0.0 expo integration

Dec 18, 2025