Camera scanning with SocketCam

Support

The React Native CaptureSDK has support for both SocketCam C820 and C860.

Requirements

In order to use SocketCam in your React Native app, you will need to install or upgrade the React Native CaptureSDK to version 1.4 or higher.

iOS Requirements

You will need to update pods because in version 1.4 we updated the iOS SDK version from 1.3.34 to 1.6.39. You may need to use pod install --repo-update. Doing a regular pod install might result in an error like the one below.

[!] CocoaPods could not find compatible versions for pod "CaptureSDK":
    In Podfile:
        react-native-capture (from `../node_modules/react-native-capture`) was resolved to 1.3.37, which depends on
        CaptureSDK (~> 1.6.39)

In your Info.plist, you need to add the key to allow access to the camera. Add the below code to the bottom of your dict tag.

<key>NSCameraUsageDescription</key>
        <string>Need to enable camera access for SocketCam products such as C820</string>
<key>UIViewControllerBasedStatusBarAppearance</key>

Android Requirements

In AndroidManifest.xml you will need to add the below code.

<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}"/>

Using SocketCam C820

Once you have all of the changes above, you can start using SocketCam in your React Native App.

SocketCamViewContainer

In order to use SocketCam in your app, you will need to import the new SocketCamViewContainer component provided by our CaptureSDK. This component is a container that contains logic, interfaces and variables for the below items that the developer is no longer required to do on their own.

  • Starting the SocketCam extension (for Android).

  • Checking whether or not SocketCam is enabled.

  • Setting the trigger property on the SocketCam device.

  • The SocketCam trigger options.

Now all the developer needs to is import the SocketCamViewContainer and provide a few props that are required by the component. Below is an example of the new SocketCamViewContainer component.

<SocketCamViewContainer
        openSocketCamView={openSocketCamView}
        handleUpdateSocketCamEnabled={handleUpdateSocketCamEnabled}
        clientOrDeviceHandle={clientOrDeviceHandle}
        triggerType={triggerType}
        socketCamCapture={socketCamCapture}
        socketCamDevice={socketCamDevice}
        myLogger={myLogger}
        handleSetStatus={handleSetStatus}
        handleSetSocketCamExtensionStatus={
          handleSetSocketCamExtensionStatus
        }
      />

Required Props

Below are the required props for SocketCamViewContainer.

clientOrDeviceHandle: number;
triggerType: number;
openSocketCamView: boolean;
socketCamCapture: CaptureRn;
socketCamDevice: CaptureDeviceInfo;
handleSetSocketCamEnabled: Function;

The clientOrDeviceHandle, socketCamDevice and socketCamCapture are the same as they’ve always been. The triggerType, once used for UI purposes in an example app is now required in order for the SocketCamViewContainer to be able to set the trigger property when the view component loads. The button options for available trigger types for SocketCam are provided by the React Native CaptureSDK CaptureHelper class (more info).

static SocketCamTriggerOptions: SocketCamTriggerButtonData[] = [
    { label: 'Start', value: `${Trigger.Start}` },
    { label: 'Continuous Scan', value: `${Trigger.ContinuousScan}` },
];

To use them, you can simply import them with your other react-native-capture, as seen below.

import {
    CaptureRn,
    Trigger,
    type CaptureDeviceInfo,
    CaptureHelper,
} from 'react-native-capture';

const {SocketCamTriggerOptions} = CaptureHelper; // alternatively you can use CaptureHelper.SocketCamTriggerOptions

The next prop, handleSetSocketCamEnabled is a required method that you provide in order for our helper functions to be able to update your app or component state to determine that SocketCam is enabled (SocketCam is enabled by default).

See an example below.

const [socketCamEnabled, setSocketCamEnabled] = useState<number>(1);

    const handleSetSocketCamEnabled = (stat: number) => {
        setSocketCamEnabled(stat);
    };

The last required prop is openSocketCamView. This one is straight forward: the prop that determines whether or not SocketCam should be opened or not!

Optional Props

Below are the optional props that can be accepted by SocketCamViewContainer .

myLogger?: SocketLogger;
handleSetStatus?: Function;
handleSetSocketCamExtensionStatus?: Function;
socketCamCustomModalStyle?: SocketCamModalStyleProps;
socketCamCustomStyle?: StyleProp<ViewStyle>;
androidSocketCamCustomView?: React.ReactElement;

The myLogger prop is the same as it’s always been: the (optional) SocketLogger instance you create to help log results from capture events. As it is optional in your React Native application as a whole, it is optional in this React Native CaptureSDK component as well.

The handleSetStatus and handleSetSocketCamExtensionStatus props are similar methods that serve different purposes.

Note

The props socketCamCustomModalStyle, socketCamCustomStyle, and androidSocketCamCustomView are related to creating a custom view for SocketCam in your React Native application. You can read more about this latest feaure in the docs here.

Also, socketCamDevice can technically be null or undefined at first because, depending on the platform, SocketCamViewContainer will need to start the SocketCam extension before looking for the regular SocketCam device arrival. However, it will eventually need to be defined to actually open SocketCam. This can be done in the DeviceArrival event in your onCaptureEvent method. While socketCamDevice can technically be undefined or null, you will still need to explicitly name it as a prop, or else TypeScript will throw an error.

Differentiating SocketCam from other devices

It is recommended in the UI to save the capture instance that is tied to SocketCam separately from other device capture instances as to avoid get/set property and usage conflicts. You can differentiate a SocketCam device from another device, such as a D740, by checking the device type in the device arrival event.

See the below code from an onCaptureEvent callback. There is a section where we explicitly check for and set a SocketCam device-specified with the comment // check for SocketCam device type.

const onCaptureEvent = (e: CaptureEvent<any>, handle: number) => {
    if (!e) {
    return;
    }

    let devs: CaptureDeviceInfo[] = [...stateRef.current.devices];
    switch (e.id) {
        case CaptureEventIds.DeviceArrival:
            const newDevice = new CaptureRn();
            openDeviceHelper(newDevice, e, false);
            break;

        // OTHER EVENT CASES
    }
}

const genDevice = (
    dev: CaptureRn,
    guid: String,
    name: String,
    type: number,
) => {
return {
    guid,
    name,
    type,
    handle: dev.clientOrDeviceHandle,
    devCapture: dev,
} as CaptureDeviceInfo;
};

const openDeviceHelper = (
    dev: CaptureRn,
    e: CaptureEvent<any>,
    isManager: boolean,
    ) => {
    let {name, guid, type} = e.value;
    let loggedOption = isManager ? 'device manager' : 'device';
    dev
    .openDevice(guid, capture)
    .then((result: number) => {
        myLogger.log(`opening a ${loggedOption} returns: `, `${result}`);
        setStatus(`result of opening ${name} : ${result}`);
        let myMap = {...stateRef.current.deviceGuidMap};
        if (!myMap[guid] && !isManager) {
            let device = genDevice(dev, guid, name, type);
            let devs = [...stateRef.current.devices, device];
            setDevices(devs);
            myMap[guid] = '1';
            setDeviceGuidMap(myMap);
        }
        if (!isManager) {
        // check for SocketCam device type
        if (SocketCamTypes.indexOf(e.value.type) > -1) {
            let device = genDevice(dev, guid, name, type);
            setSocketCamDevice(device);
        } else {
            setDeviceCapture(dev);
        }
        } else {
            setBleDeviceManagerCapture(dev);
            getFavorite(dev);
        }
    })
    .catch((res: JRpcError) => {
        let {error} = res;
        const {code, message} = error;
        myLogger.error(resToString(error));
        setStatus(`error opening a device: ${code} \n ${message}}`);
    });
};