[TOC]

React Native Darwinium SDK Module

Integrating the Darwinium SDK into a React Native app

Installation

Set up npm credentials for the Darwinium npm repository

File: ~/.npmrc @darwinium:registry=https://dwnedge.jfrog.io/artifactory/api/npm/dwn-npm //dwnedge.jfrog.io/artifactory/api/npm/dwn-npm/:_authToken= //dwnedge.jfrog.io/artifactory/api/npm/dwn-npm/:email=<user_email> //dwnedge.jfrog.io/artifactory/api/npm/dwn-npm/:always-auth=true

Via npm

Run npm install @darwinium/native-module-sdk --save

Via yarn

Run yarn add @darwinium/native-module-sdk

Latest native module version: 2.4.1

Linking

Android

This npm package supports the Darwinium Android SDK version:

SDK version: 2.4.1

Set up credentials for the Darwinium repository. Add the following entries to android/gradle.properties. The user and token are the same as in ~/.npmrc.

# Darwinium Artifactory credentials (do not commit real values).
# You can also provide these via environment variables:
#   DWN_MAVEN_USER, DWN_MAVEN_PASSWORD
DWN_MAVEN_USER=<user_email>
DWN_MAVEN_PASSWORD=<token>

In your global Gradle build file, for example android/build.gradle:

def dwnMavenUrl = System.getenv("DWN_MAVEN_URL") ?: providers.gradleProperty("DWN_MAVEN_URL").orNull ?: "https://packages.darwinium.com/artifactory/dwn-maven/"
def dwnMavenUser = System.getenv("DWN_MAVEN_USER") ?: providers.gradleProperty("DWN_MAVEN_USER").orNull
def dwnMavenPassword = System.getenv("DWN_MAVEN_PASSWORD") ?: providers.gradleProperty("DWN_MAVEN_PASSWORD").orNull

if (!dwnMavenUser || !dwnMavenPassword) {
    throw new GradleException("Missing Darwinium credentials. Set DWN_MAVEN_USER and DWN_MAVEN_PASSWORD in gradle.properties or environment variables.")
}

allprojects {
    repositories {
        maven {
            url = uri(dwnMavenUrl)
            credentials {
                username = dwnMavenUser
                password = dwnMavenPassword
            }
        }
    }
}

There is a hardcoded SDK version in the module. If you want to use a different SDK version, you can add this to your global build.gradle:

allprojects {
    configurations.configureEach {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == "com.darwinium" &&
                details.requested.name == "android_sdk") {
                details.useVersion("2.3.0")
            }
        }
    }
}

iOS

For CocoaPods, there are 2 repository options

First, get an SDK access token from the portal: Account -> Preference -> SDK Access. packages.darwinium.com requires a user and token for access.

Then set up user/token in ~/.netrc:

machine packages.darwinium.com
  login <user/account>
  password <access_token>

Git Repo

Two methods:

Method 1: Add the following line in the Podfile

pod 'dwn_ios_sdk', :git => 'https://packages.darwinium.com/sdk/dwn_ios_sdk.git', :tag => '<version>'

Method 2: Add packages.darwinium.com as a Pods source, which contains the full SDK release structure

JFrog Repo

In your Podfile:

source "https://packages.darwinium.com/artifactory/api/pods/dwn-pods"

    target 'MyApp' do
        pod 'dwn_ios_sdk', '<ios_sdk_version>'
    end

Install the pod

    pod install
    

Example

# Specs needed for SwiftProtobuf which dwn_ios_sdk depends on
source 'https://github.com/CocoaPods/Specs.git'

# SOURCE1: using git CocoaPods repo as source
source 'https://packages.darwinium.com/sdk/dwn_ios_sdk.git'

# SOURCE2: use jfrog CDN 
source "https://packages.darwinium.com/artifactory/api/pods/dwn-pods"

target 'MyApplication' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # this pod description doesn't need #SOURCE1/2/3
  # only for git repo
  pod 'dwn_ios_sdk', :git => 'https://packages.darwinium.com/sdk/dwn_ios_sdk.git', :tag => '<version>'

  # The following pod description requires one of above 3 SOURCEs
  pod 'dwn_ios_sdk', '2.3.0'

end
	

Usage

The Darwinium SDK native module is wrapped in a JavaScript class, located at:

	node_modules/@darwinium/native-module-sdk/index.js
import { NativeModules } from 'react-native';

class DarwiniumSDK {
    // Darwinium SDK supports multiple instances
    // viewName gives a name to each instance
    constructor(viewName) {
        this.viewName = viewName;
        if (NativeModules && NativeModules.DwnSDKModule) {
             this.is_valid = true;
        } else {
             console.log("DwnSDKModule doesn't exist");
             this.is_valid = false;
        }
    }

    start() {
        if (!this.is_valid) return;
        if (Platform.OS == 'android') {
            NativeModules.DwnSDKModule.profilingStart(this.viewName);
        } else if (Platform.OS == 'ios') {
            NativeModules.DwnSDKModule.start(this.viewName);
        }
    }
    // Call stop() when the view is removed/unmounted
    stop() {
        if (!this.is_valid) return;
        if (Platform.OS == 'android') {
            NativeModules.DwnSDKModule.profilingStop(this.viewName);
        } else if (Platform.OS == 'ios') {
            NativeModules.DwnSDKModule.stop(this.viewName);
        }
    }
    // Apply TextInput for keyboard biometrics detection
    // Each TextInput has to have a placeholder
    // Works for both Android and iOS SDK
    addTextView(placeHolder, dwnContext) {
        if (!this.is_valid) return;
        NativeModules.DwnSDKModule.addTextView(this.viewName, placeHolder, dwnContext);
    }

	// addTextViewByRef is a more convenient method: you can directly pass
	// the useRef of TextInput, and the SDK gets nativeId internally.
	// It only works for Android SDK.
	// iOS SDK does not support it because of a system limitation.
    addTextViewByRef(ref, dwnContext) {
        if (!this.is_valid) return;
        if (Platform.OS == 'android') {
            const nativeId = findNodeHandle(ref.current);
            this.addTextViewById(nativeId, dwnContext);
        } else if (Platform.OS == 'ios') {
            console.log("addTextViewByRef is not supported for iOS SDK");
        } 
    }

    // Another method to detect TextInput biometrics behavior without placeholder
    // There is a set of interfaces for it, but it only works for Android SDK

    // Pass the whole input field value directly to SDK, supported on both iOS and Android
    onTextChange(value, dwnContext) {
        if (!this.is_valid) return;
        NativeModules.DwnSDKModule.onTextChange(this.viewName, value, dwnContext);
    }
    // Call this function when focus switches on/off, supported on both iOS and Android
    onFocusChange(focus, dwnContext) {
        if (!this.is_valid) return;
        NativeModules.DwnSDKModule.onFocusChange(this.viewName, focus, dwnContext);
    }
    // Pass the pressed key value directly to SDK, supported on both iOS and Android
    onKeyPress(key, dwnContext) {
        if (!this.is_valid) return;
        NativeModules.DwnSDKModule.onKeyPress(this.viewName, key, dwnContext);
    }

    // Specify the configuration setting for SDK
    // Call it before sdk.start()
    // For Android SDK, if you set "permission" = "yes", SDK will show a permission popup
    //    e.g.  sdk.setConfig("permission", "yes")
    setConfig(key, value) {
        if (!this.is_valid) return;
        NativeModules.DwnSDKModule.setConfig(this.viewName, key, value);
    }

    // Get FP data blob (base64 string); callback function processes the data
    collect(callback) {
        if (!this.is_valid) return;
        if (Platform.OS == 'android') {
            NativeModules.DwnSDKModule.collect(this.viewName)
            .then(blob=> {
                callback(blob);
            })
            .catch(e => {
                console.log("Failed to get FP blob: " + e.toString());
            });
        } else if (Platform.OS == 'ios') {
            NativeModules.DwnSDKModule.collect(this.viewName, callback);
        }
    }

    // Get FP data blob (base64 string) using the async native API;
    // callback function processes the data once collection completes
    collectAsync(callback) {
        if (!this.is_valid) return;
        if (Platform.OS == 'android') {
            NativeModules.DwnSDKModule.collectAsync(this.viewName)
            .then(blob=> {
                callback(blob);
            })
            .catch(e => {
                console.log("Failed to get FP blob: " + e.toString());
            });
        } else if (Platform.OS == 'ios') {
            NativeModules.DwnSDKModule.collectAsync(this.viewName, callback);
        }
    }
}

export default DarwiniumSDK;

Here is an example of how to integrate the Darwinium native module into React Native code:

import DarwiniumSDK from '@darwinium/native-module-sdk'

const SigninScreen = ({signUp}) => {
  // Generate an SDK instance with a label
  // Darwinium supports multiple SDK instances; the label acts as an instance name
  const sdk = new DarwiniumSDK("signin")
  const collectFP = () => {
      // collect() passes the blob to the callback function
      sdk.collect(blob => {
        console.log('FP data blob: ' + blob);
        // TODO: Do an API call with the blob
      });
  };

  const collectFPAsync = () => {
      // collectAsync() passes the blob to the callback when the async native call finishes
      sdk.collectAsync(blob => {
        console.log('Async FP data blob: ' + blob);
        // TODO: Do an API call with the blob
      });
  };

  const passwordInputRef = useRef(null);

  useEffect(() => {
    sdk.start()

    // Three methods for detecting TextInput field biometrics
    // #1 Pass the TextInput placeholder to SDK
    sdk.addTextView('Enter Email', 'EMAIL')

	// #2 Pass useRef to wrapper; wrapper gets nativeId and passes it to SDK
    // Android only
    sdk.addTextViewByRef(passwordInputRef, 'PASSWORD')

    return () => {
      // Cleanup logic (optional)
      console.log('Sign In unload: ' + Platform.OS);
      sdk.stop()
    };
  }, []);

        <TextInput
          placeholder="Enter Email"
          style={styles.inputField}
          inputMode="text"
          autoCapitalize="none"
          //onChangeText={text => sdk.onTextChange(text, "EMAIL")}
          //onFocus={_ => sdk.onFocusChange(true, "EMAIL")}
          //onBlur={_ => sdk.onFocusChange(false, "EMAIL")}
        />

        <TextInput
          ref={passwordInputRef}
          placeholder="Enter Password"
          style={styles.inputField}
          inputMode="text"

          // #3 Pass events directly to SDK, supported on both Android and iOS
          onChangeText={text => sdk.onTextChange(text, "PASSWORD")}
          onFocus={_ => sdk.onFocusChange(true, "PASSWORD")}
          onBlur={_ => sdk.onFocusChange(false, "PASSWORD")}
        />
      </View>