[TOC]
Integrating the Darwinium SDK into a React Native app
File: ~/.npmrc
@darwinium:registry=https://dwnedge.jfrog.io/artifactory/api/npm/dwn-npm
//dwnedge.jfrog.io/artifactory/api/npm/dwn-npm/:_authToken=
Run npm install @darwinium/native-module-sdk --save
Run yarn add @darwinium/native-module-sdk
Latest native module version: 2.4.1
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
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>
Two methods:
pod 'dwn_ios_sdk', :git => 'https://packages.darwinium.com/sdk/dwn_ios_sdk.git', :tag => '<version>'
In your Podfile:
source "https://packages.darwinium.com/artifactory/api/pods/dwn-pods"
target 'MyApp' do
pod 'dwn_ios_sdk', '<ios_sdk_version>'
end
pod install
# 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
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>