Getting Started with React Native CaptureSDK¶
Requirements¶
The Socket Mobile CaptureSDK uses Bluetooth Classic for the barcode scanner products and Bluetooth Low Energy (BLE) for the Contactless Reader/Writer products (Socket Mobile D600, S550) and the new S721 barcode scanner.
Even though the React Native CaptureSDK allows to develop an app to run on iOS and Android the underlying Capture architecture on these 2 platforms is different.
On Android there is a service embedded in the Socket Mobile Companion app that is required in order to connect the Socket Mobile device to the Android host.
On iOS the communication with the Socket Mobile devices are embedded in the React Native Module therefore adding more configuration to be taken care of in the application itself.
Requirements for iOS platform
For applications that need to work with barcode scanners, make sure the following requirements are met:
Your iOS application needs to be registered in our Apple MFI Approved Application list before submitting your application to the Apple Store. It will not pass the Apple Store review if this is not done.
Your application must have the string
com.socketmobile.chsin the Supported External Protocol setting.

In your Info.plist, you need to add the
sktcompanionscheme to theLSApplicationQueriesSchemesarray.
<key>NSCameraUsageDescription</key>
<string>Need to enable camera access for SocketCam products such as C820</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sktcompanion</string>
</array>
4. Your application must add some security descriptions for the Bluetooth permissions shown here:

Note
For more info on enabling your app for iOS, check out the documentation pertaining to iOS.
Requirements for Android platform
Add the below lines to your
AndroidManifest.xmlfile, found in your app’sandroid/app/src/mainfolder, right under your opening<manifest>tag.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Add the below lines to your
AndroidManifest.xmlfile.
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<meta-data android:name="com.socketmobile.capture.APP_KEY" android:value="YOUR_APP_KEY"/>
<meta-data android:name="com.socketmobile.capture.DEVELOPER_ID" android:value="YOUR_DEVELOPER_ID"/>
Next, you will need to enable communication to Socket Mobile Companion. Right before your closing
</manifest>tag, put the belowqueriesproperty.
<queries>
<package android:name="com.socketmobile.companion"/>
</queries>
Next you will need to update the
<application>tag to includeandroid:networkSecurityConfig="@xml/network_security_config". It should look something like the below.
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" android:networkSecurityConfig="@xml/network_security_config">
Next, add a file called
network_security_config.xmlto yourxmldirectory, which can be found in your app’sandroid/app/src/main/resfolder. This file should look like this.
<?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>
The final step is to add Socket Mobile’s Maven repository to your project so that Gradle can resolve all transitive dependencies (including
com.honeywell:swiftdecoder, which is required bycapture-socketcam). Add the following to therepositoriesblock used for dependency resolution in your project (e.g.settings.gradleunderdependencyResolutionManagement, orbuild.gradleunderallprojects):
maven {
url "https://bin.socketmobile.com/repo/releases"
}
Note
For more info on enabling your app for Android, check out the documentation pertaining to Android.
Requirements for both iOS and Android platforms
Your application will need a SocketMobile AppKey. Follow the link to create an AppKey. AppKeys can be generated online and at no additional cost beyond the nominal one time registration fee. The AppKey is validated by the SDK library on the device, no internet connection is required. Note: You don’t need to create your own AppKey to compile and run the sample apps.
The scanner needs to be paired with your devices in Application Mode. This can be done using Socket Mobile Companion app which can be downloaded from the App Store .
Try our React Native sample app Single Entry React Native.
SDK Installation¶
The React Native CaptureSDK is released as a NPM (Node Package Manager) package.
Using yarn
yarn add react-native-capture
Using npm
npm install --save react-native-capture
Using CaptureSDK with CaptureHelper (recommended)¶
Version 2.0 introduces CaptureHelper, which manages the entire SDK lifecycle. Import it along with the types you need:
import {
CaptureHelper,
type CaptureHelperDevice,
type AppInfoRn,
type DecodedData,
SocketCamTypes,
BluetoothDiscoveryMode,
Trigger,
} from 'react-native-capture';
Here are the steps to follow:
Create a
CaptureHelperinstance with your app credentials and callbacksCall
helper.open()to start receiving eventsConnected devices are delivered as
CaptureHelperDeviceobjects viaonDeviceArrivalDecoded data arrives via
onDecodedDataCall
helper.close()when done
Opening CaptureHelper
const appInfo: AppInfoRn = {
appIdIos: 'ios:com.socketmobile.reactjs.native.example.example',
appIdAndroid: 'android:com.example',
developerId: 'ecc6c526-970b-ec11-b6e6-0022480a2304',
appKeyIos: 'MC0CFHL9no0HS6LohlvgGj3s6R4fUTTGAhUAjkIUkoWjCi8NXAjDB9uk9WMdlJc=',
appKeyAndroid:
'MC0CFBJxr9ERxurLZQk8voZsFC7BH+8zAhUAxbT41GqB8EwOu7JtVYhffCnTdmI=',
};
const App = () => {
const [devices, setDevices] = useState<CaptureHelperDevice[]>([]);
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) => {
setStatus(`Scanned from ${device.name}: ${data.name}`);
},
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(() => {}); };
}, []);
Using device methods
Once a device arrives, you can call typed methods directly:
const device = devices[0];
// Get device information
const name = await device.getFriendlyName();
const firmware = await device.getFirmwareVersion();
const battery = await device.getBatteryLevel(); // returns 0–100
// Trigger a scan
await device.setTrigger(Trigger.Start);
// Enable a symbology
await device.setDataSource(
CaptureDataSourceID.SymbologyQRCode,
CaptureDataSourceStatus.Enable,
);
// Confirm data
await device.setDataConfirmation(
DataConfirmationLed.Green,
DataConfirmationBeep.Good,
DataConfirmationRumble.Good,
);
For a complete API reference, see CaptureHelper for The React Native CaptureSDK.
Using CaptureSDK with CaptureRn (low-level)¶
The low-level CaptureRn class is still available for developers who need full control. Import it as follows:
import { CaptureRn, CaptureEventIds, SktErrors } from 'react-native-capture';
Here are the usual steps to follow:
Open Capture with the App credentials and provide event handler function
Handle device arrival and open the device in the event handler function
Handle device removal and close the device in the event handler function
Handle decoded data in the event handler function
Opening Capture with App credentials
The React Native CaptureSDK is an extension of the CaptureJS SDK. The main difference is the first instance that uses CaptureRn instead of Capture:
const appInfo: AppInfoRn = {
appIdIos: 'ios:com.socketmobile.reactjs.native.example.example',
appIdAndroid: 'android:com.example',
developerId: 'ecc6c526-970b-ec11-b6e6-0022480a2304',
appKeyIos: 'MC0CFHL9no0HS6LohlvgGj3s6R4fUTTGAhUAjkIUkoWjCi8NXAjDB9uk9WMdlJc=',
appKeyAndroid:
'MC0CFBJxr9ERxurLZQk8voZsFC7BH+8zAhUAxbT41GqB8EwOu7JtVYhffCnTdmI=',
};
const App = () => {
const [capture] = useState(new CaptureRn());
const [status, setStatus] = useState<string>('Opening Capture...');
const [isOpen, setIsOpen] = useState<boolean>(false);
const openCapture = () => {
capture
.open(appInfo, onCaptureEvent as Notification)
.then(() => {
setStatus('capture open success');
setIsOpen(true);
})
.catch((err: any) => {
const {error} = err;
const {code, message} = error;
setStatus(`failed to open Capture: ${code} \n ${message}`);
if (code === SktErrors.ESKT_UNABLEOPENDEVICE) {
setStatus('Is Socket Mobile Companion app installed?');
}
});
};
Handle device arrival and open the device
When the application receives a Device Arrival notification, it can create a new CaptureRn object that represents the new device.
The application opens the device by passing GUID and the main CaptureRn reference as arguments of the device open function.
Opening the device allows to receive the decoded data from this device.
Note
the device GUID changes everytime the device connects. It identifies a connection session with a device.
Note
If a Socket Mobile device is already connected to the host prior to the app opening CaptureSDK, the device arrival notification will still be sent to make the application aware that the device is connected.
const onCaptureEvent = (e, handle) => {
if (!e) {
return;
}
switch (e.id) {
case CaptureEventIds.DeviceArrival:
const newDevice = new CaptureRn();
openDeviceHelper(newDevice, e, false);
break;
// OTHER EVENT CASES
}
Handle device removal and close the device
The device removal occurs when the Socket Mobile is no longer connected to the host. It is recommended to close it.
case CaptureEventIds.DeviceRemoval:
let index = devs.findIndex((d: CaptureDeviceInfo) => {
return d.guid === e.value.guid;
});
if (index >= 0) {
let removeDevice = devs[index];
removeDevice!.devCapture
.close()
.then((result: number) => {
devs.splice(index, 1);
setDevices(devs);
})
.catch((res: JRpcError) => {
let {error} = res;
let {message, code} = error;
setStatus(`error closing a device: ${code}: ${message}`);
});
}
break;
Handle decoded data in the event handler function
Each time a Socket Mobile device is successful at reading a barcode or an NFC tag, the decoded data notification is sent:
case CaptureEventIds.DecodedData:
let devWithInfo = stateRef.current.devices.find(
(d: CaptureDeviceInfo) => {
return d.handle === handle;
},
);
if (devWithInfo) {
setStatus('Decoded Data from ' + devWithInfo.name);
}
lastDecodedData = {
data: arrayToString(e.value.data),
length: e.value.data.length,
name: e.value.name,
};
setDecodedData(lastDecodedData);
break;