react-native-capture
v2.0.11
Published
Socket Mobile CaptureSDK for React Native
Downloads
2,672
Readme
React Native CaptureSDK - Version 2.0.11
This React Native module allows a React Native application to use and control Socket Mobile wireless barcode scanners, NFC Reader/Writer, and Camera to capture and deliver data capture to such application.
The React Native CaptureSDK fully supports the React Native new architecture.
Devices compatibility and CaptureSDK versions
| Devices | < 2.0 | 2.0 | | :--------------------------------------------: | :---: | :-: | | SocketCam C860 | ✅ | ✅ | | SocketCam C820 | ✅ | ✅ | | S720/D720/S820 | ✅ | ✅ | | D600, S550, and all other barcode scanners | ✅ | ✅ | | S370 | ✅ | ✅ | | S320 | ✅ | ✅ | | S721 (new Bluetooth LE barcode scanner) | ❌ | ✅ |
What's new in version 2.0
CaptureHelper — a simpler way to integrate
Version 2.0 introduces CaptureHelper, a high-level lifecycle manager that replaces the manual CaptureRn + onCaptureEvent switch/case pattern. Instead of constructing CaptureProperty objects and interpreting raw events yourself, you create a CaptureHelper instance with typed callbacks and call named methods.
import {
CaptureHelper,
type CaptureHelperDevice,
type AppInfoRn,
type DecodedData,
SocketCamTypes,
BluetoothDiscoveryMode,
Trigger,
} from 'react-native-capture';
const helper = new CaptureHelper({
appInfo,
onDeviceArrival: (device) => console.log(`Connected: ${device.name}`),
onDeviceRemoval: (device) => console.log(`Disconnected: ${device.name}`),
onDecodedData: (data, device) => console.log(`Scanned: ${data.data as number[]}`),
onError: ({ code, message }) => console.error(`Error ${code}: ${message}`),
});
await helper.open();CaptureHelperDevice — typed device methods
Connected devices are now wrapped in CaptureHelperDevice objects that expose typed methods. No more building CaptureProperty by hand:
// Before (v1.x) — manual property construction
const property = new CaptureProperty(
CapturePropertyIds.FriendlyNameDevice,
CapturePropertyTypes.None,
{},
);
const result = await device.devCapture.getProperty(property);
// After (v2.0) — typed method
const name = await device.getFriendlyName();Available device methods include getFriendlyName, setFriendlyName, getBatteryLevel, getFirmwareVersion, setTrigger, getDataSource, setDataSource, setDataConfirmation, getStandConfig, setStandConfig, and more.
Bluetooth LE device support
Version 2.0 adds support for Bluetooth LE devices such as the S721. These devices use a manual discovery flow that the SDK handles for you. See Connecting Bluetooth LE Devices.
Breaking changes from version 1.x
CaptureHelper is now an instance
CaptureHelper was previously a static utility class with methods like CaptureHelper.setSocketCamEnabled(...). It is now an instance-based lifecycle manager that must be created with new CaptureHelper({...}) and opened with helper.open().
Devices are CaptureHelperDevice objects
Callbacks like onDeviceArrival now receive CaptureHelperDevice instances instead of raw CaptureDeviceInfo. These objects have typed methods (getFriendlyName(), getBatteryLevel(), etc.) and properties (name, guid, type, handle).
The underlying CaptureRn instance is still accessible via device.devCapture if needed.
Battery level is a direct percentage
getBatteryLevel() now returns a plain number (0–100) instead of a bit-shifted value that required manual decoding.
Removed interfaces
The following interfaces have been removed: GetSocketCamEnabledArguments, SetSocketCamEnabledArguments, SocketCamTriggerButtonData, SocketCamStatusOption, SocketCamStatusSubOption.
Bluetooth LE devices require Companion or in-app discovery
Users who want to use Bluetooth LE readers have two options:
Option A — Install the Socket Mobile Companion app which handles discovery and pairing.
Option B — Implement the discovery flow in your own UI using the SDK's discovery methods. See Connecting Bluetooth LE Devices.
Installation
yarn add react-native-captureQuick start with CaptureHelper
1. Create and open CaptureHelper
import React, { useState, useEffect, useRef } from 'react';
import {
CaptureHelper,
type CaptureHelperDevice,
type AppInfoRn,
type DecodedData,
type DiscoveredDeviceInfo,
SocketCamTypes,
BluetoothDiscoveryMode,
Trigger,
} from 'react-native-capture';
const appInfo: AppInfoRn = {
appIdIos: 'ios:com.mycompany.myapp',
appKeyIos: 'MC0C...',
appIdAndroid: 'android:com.mycompany.myapp',
appKeyAndroid: 'MC0C...',
developerId: 'your-developer-id',
};
const App = () => {
const [devices, setDevices] = useState<CaptureHelperDevice[]>([]);
const [decodedData, setDecodedData] = useState<DecodedData | null>(null);
const [status, setStatus] = useState('Opening Capture...');
const helperRef = useRef<CaptureHelper | null>(null);
useEffect(() => {
const helper = new CaptureHelper({
appInfo,
onDeviceArrival: (device) => {
setDevices(d => [...d, device]);
},
onDeviceRemoval: (device) => {
setDevices(d => d.filter(dd => dd.guid !== device.guid));
},
onDecodedData: (data, device) => {
setDecodedData(data);
},
onError: ({ code, message }) => {
setStatus(`Error ${code}: ${message}`);
},
});
helperRef.current = helper;
helper
.open()
.then(() => setStatus('Capture open'))
.catch((err) => setStatus(`Failed: ${err?.error?.message}`));
return () => {
helper.close().catch(() => {});
};
}, []);
// ...
};2. Use typed device methods
Once a device arrives, you can call methods directly on the CaptureHelperDevice:
const device = devices[0];
// Get device info
const friendlyName = await device.getFriendlyName();
const firmware = await device.getFirmwareVersion();
// firmware: { major, middle, minor, build, year, month, day }
// Battery (returns 0–100 directly)
const battery = await device.getBatteryLevel();
// Trigger a scan
await device.setTrigger(Trigger.Start);
// Enable/disable a symbology
await device.setDataSource(CaptureDataSourceID.SymbologyQRCode, CaptureDataSourceStatus.Enable);3. Available CaptureHelper callbacks
interface CaptureHelperCallbacks {
onDeviceArrival?: (device: CaptureHelperDevice) => void;
onDeviceRemoval?: (device: CaptureHelperDevice) => void;
onDecodedData?: (data: DecodedData, device: CaptureHelperDevice) => void;
onSocketCamCanceled?: (device: CaptureHelperDevice) => void;
onDiscoveredDevice?: (device: DiscoveredDeviceInfo) => void;
onDiscoveryEnd?: (result: number) => void;
onBatteryLevel?: (level: number, device: CaptureHelperDevice) => void;
onPowerState?: (state: PowerState, device: CaptureHelperDevice) => void;
onButtons?: (state: Notifications, device: CaptureHelperDevice) => void;
onError?: (error: { code: number; message: string }) => void;
}4. Available CaptureHelper methods
// Lifecycle
await helper.open();
await helper.close();
// Get connected devices
const devices = helper.getDevices();
// Access the underlying CaptureRn instance (needed for SocketCamViewContainer)
const rootCapture = helper.rootCapture;
// SDK info
const version = await helper.getVersion();
// SocketCam
await helper.setSocketCamEnabled(true);
await helper.getSocketCamEnabled();
// BLE discovery (see next section)
await helper.addBluetoothDevice(BluetoothDiscoveryMode.BluetoothLowEnergy);
await helper.connectDiscoveredDevice(discoveredDevice);
await helper.removeBleDevice(connectedDevice);Connecting Bluetooth LE Devices
For Bluetooth LE products (S721, D600, S550, S370...) the SDK uses a manual discovery flow. With CaptureHelper, this is straightforward:
1. Discover nearby devices
Call addBluetoothDevice on your CaptureHelper instance. Each nearby device triggers the onDiscoveredDevice callback.
const [discoveredDevices, setDiscoveredDevices] = useState<DiscoveredDeviceInfo[]>([]);
// In your CaptureHelper callbacks:
const helper = new CaptureHelper({
appInfo,
onDiscoveredDevice: (device) => {
setDiscoveredDevices(d => {
if (d.find(dd => dd.identifierUuid === device.identifierUuid)) return d;
return [...d, device];
});
},
onDiscoveryEnd: () => {
setStatus('Discovery finished');
},
// ...other callbacks
});
// Start scanning
await helper.addBluetoothDevice(BluetoothDiscoveryMode.BluetoothLowEnergy);2. Connect a discovered device
const connectDevice = async (device: DiscoveredDeviceInfo) => {
await helper.connectDiscoveredDevice(device);
// A successful connection triggers onDeviceArrival with a CaptureHelperDevice
};3. Disconnect a device
const disconnectDevice = async (device: CaptureHelperDevice) => {
await helper.removeBleDevice(device);
// Triggers onDeviceRemoval
};SocketCam
SocketCam (C820 / C860) lets your app use the device camera as a barcode scanner. In version 2.0, the SocketCamViewContainer component handles the native camera view and the SocketCam extension lifecycle.
Enable SocketCam
// Toggle SocketCam on — this triggers a DeviceArrival for the SocketCam virtual device
await helper.setSocketCamEnabled(true);
// The SocketCam device appears in your devices list
const socketCamDevice = devices.find(d => SocketCamTypes.indexOf(d.type) > -1);SocketCamViewContainer
Import and use the SocketCamViewContainer component where you want the camera view:
import { SocketCamViewContainer, Trigger, SocketCamTypes } from 'react-native-capture';
<SocketCamViewContainer
openSocketCamView={openSocketCamView}
handleSetSocketCamEnabled={handleSetSocketCamEnabled}
clientOrDeviceHandle={helper.rootCapture?.clientOrDeviceHandle}
triggerType={Trigger.Start}
socketCamCapture={helper.rootCapture}
socketCamDevice={socketCamDevice}
handleSetStatus={setStatus}
handleSetSocketCamExtensionStatus={setExtensionStatus}
socketCamCustomModalStyle={{
presentationStyle: 'overFullScreen',
animationType: 'fade',
transparent: true,
}}
socketCamCustomStyle={customStyles}
androidSocketCamCustomView={<MyCustomAndroidView />}
/>Android note: On Android, mount SocketCamViewContainer as soon as helper.rootCapture is available (before the user enables SocketCam). This starts the SocketCam extension process in the background. Without this, enabling SocketCam returns error -32 (ESKT_NOTAVAILABLE).
For more on SocketCam, check out the docs. For custom views, read more here.
Migration guide from 1.x to 2.0
Step 1 — Replace CaptureRn + onCaptureEvent with CaptureHelper
// ❌ Before (v1.x)
const capture = new CaptureRn();
await capture.open(appInfo, onCaptureEvent);
// ...then a big switch/case in onCaptureEvent
// ✅ After (v2.0)
const helper = new CaptureHelper({
appInfo,
onDeviceArrival: (device) => { /* ... */ },
onDecodedData: (data, device) => { /* ... */ },
// ...
});
await helper.open();Step 2 — Use CaptureHelperDevice methods instead of raw properties
// ❌ Before
const prop = new CaptureProperty(CapturePropertyIds.FriendlyNameDevice, CapturePropertyTypes.None, {});
const result = await deviceCapture.getProperty(prop);
const name = result.value;
// ✅ After
const name = await device.getFriendlyName();Step 3 — Update SocketCam code
// ❌ Before
await CaptureHelper.setSocketCamEnabled({ socketCamCapture, ... });
// ✅ After
await helper.setSocketCamEnabled(true);Step 4 — Use discovery callbacks for BLE devices
// ❌ Before — manual DeviceManagerArrival handling, CaptureProperty for AddDevice
// ✅ After
await helper.addBluetoothDevice(BluetoothDiscoveryMode.BluetoothLowEnergy);
// onDiscoveredDevice callback fires for each device found
await helper.connectDiscoveredDevice(discoveredDevice);Using the low-level API
The low-level CaptureRn class and all property types/enums are still exported and can be used directly if you need full control. CaptureHelper is the recommended approach for most applications.
Referencing Socket Mobile's Android CaptureSDK
In your build.gradle file, add the Socket Mobile release repo in the repositories section:
maven {
url "https://bin.socketmobile.com/repo/releases"
}In your app/build.gradle, add:
packagingOptions {
pickFirst '/lib/arm64-v8a/libc++_shared.so'
pickFirst '/lib/armeabi-v7a/libc++_shared.so'
}Enable Start Capture Service on Android
To enable Start Capture Service on Android (so that the developer doesn't need to actively run/open Companion), add a network security configuration.
In your-app/android/app/src/main/res/xml/network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="false">localhost</domain>
<domain includeSubdomains="false">127.0.0.1</domain>
</domain-config>
</network-security-config>In AndroidManifest.xml, add to the <application> tag:
android:networkSecurityConfig="@xml/network_security_config"And before the closing </manifest> tag:
<queries>
<package android:name="com.socketmobile.companion"/>
</queries>For more details, see the Android docs.
Enabling SocketCam on iOS
In your Info.plist, add camera access and the Companion URL scheme:
<key>NSCameraUsageDescription</key>
<string>Need to enable camera access for SocketCam products</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sktcompanion</string>
</array>Documentation
More documentation available at Socket online documentation.
