Skip to main content

React Native

Nuestro SDK de Workflows para React Native permite una experiencia rápida y fluida para tus usuarios, aprovechando las capacidades nativas de los dispositivos. Este SDK se instala como un paquete npm y te permite ejecutar workflows, obtener información detallada del proceso y recibir eventos en tiempo real durante su ejecución.


Requisitos

Para poder utilizar nuestro SDK de React Native, debes cumplir con los siguientes requisitos:

  • React Native 0.70+
  • Node.js 18+
  • Contar con un Workflow creado a través de nuestra API de Workflows.
  • Acceso al registro privado de npm (se te proporcionará un archivo .npmrc).

Instalación

Configuración del archivo .npmrc

En la raíz del proyecto React Native, agrega el archivo .npmrc para autorizar la instalación del paquete. Este archivo te será proporcionado por tu administrador de cuenta.

Instalación del paquete

Ejecuta el siguiente comando en la raíz del proyecto:

npm install @rem-tools/workflows-react-native@0.5.0

Nota: Verifica la versión actual en el registro de npm.

Configuración para Expo

Si utilizas Expo, puedes omitir la configuración nativa usando el comando:

npx expo prebuild

En tu archivo app.json o app.config.js, agrega la configuración del plugin:

{
"expo": {
"plugins": [
[
"@rem-tools/workflows-react-native",
{
"jsonKeyPath": "/ruta/a/tu/archivo-service-account.json",
"cameraDescription": "Se requiere acceso a la cámara para verificación de identidad",
"microphoneDescription": "Se requiere acceso al micrófono para grabar audio",
"locationDescription": "Se requiere acceso a la ubicación por motivos de seguridad"
}
]
]
}
}

Opciones de Configuración del Plugin

ParámetroRequeridoDescripción
jsonKeyPathRuta absoluta o relativa al archivo JSON de la cuenta de servicio de Google Cloud. Requerido para Android para autenticarse con el repositorio Maven privado.
cameraDescriptionNoDescripción personalizada para el permiso de cámara (iOS).
microphoneDescriptionNoDescripción personalizada para el permiso de micrófono (iOS).
locationDescriptionNoDescripción personalizada para el permiso de ubicación (iOS).

Ejecutar la aplicación

Para Android (dispositivo físico):

Asegúrate de que el proyecto Android haya completado el build de Gradle:

npm run android --device

Para iOS (dispositivo físico):

Asegúrate de haber ejecutado pod install en el directorio ios:

npx expo run:ios --device

Configuración Específica para Android

Requisitos de SDK de Android

  • Android API 24 - 36
  • Android Studio Hedgehog+

Configuración de Repositorios

En el archivo android/build.gradle, declara de dónde se obtendrán las dependencias:

allprojects {
repositories {
maven {
url "https://us-central1-maven.pkg.dev/gendra-services/workflows-mobile"
credentials {
username = "_json_key"
password = file("tu_archivo_credenciales.json").text
}
}
}
}
danger

El archivo de service account (JSON) es proporcionado por REM. Contacta a tu administrador de cuenta para obtenerlo.

Configuración de Release Build

En el archivo android/app/build.gradle, agrega a nivel de android los siguientes ajustes que permiten que Workflows pueda acceder a modelos, assets, y evitar errores en compilación de release:

android {
// ...

buildTypes {
release {
shrinkResources false
}
}

aaptOptions {
noCompress "tflite", "task"
}

sourceSets {
main {
assets.srcDirs += 'src/main/assets'
}
}
}

Configuración del AndroidManifest

Agrega esta línea para resolver conflictos del AndroidManifest cuando una librería (como Workflows) define los mismos atributos:

<application
...
tools:replace="android:theme, android:usesCleartextTraffic">
...
</application>

Reglas para ProGuard

Agrega las siguientes reglas al archivo proguard-rules.pro. Son necesarias para evitar la minificación de clases usadas por Workflows:

# Keep the io.flutter.plugin.** package provided by Flutter
-dontwarn io.flutter.plugin.**

# The android.** package is provided by the OS at runtime.
-dontwarn android.**

# Rules for the Workflows Flutter
-keep class tools.rem.workflows_flutter_plugin.** { *; }
-keep class com.digitalpersona.** { *; }

# Keep the mediapipe classes
-keep public class com.google.mediapipe.** { *; }
-keep public class com.google.mediapipe.framework.Graph.** { *; }
-keep public class com.google.common.** { *; }
-keep public interface com.google.common.** { *; }
-keep class * extends com.google.common.flogger.** {*;}
-keep class com.google.protobuf.** { *; }
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite.** { *; }
-dontwarn com.google.mediapipe.proto.CalculatorProfileProto$CalculatorProfile
-dontwarn com.google.mediapipe.proto.GraphTemplateProto$CalculatorGraphTemplate

Recursos Personalizados

Para usar recursos personalizados, agrega los assets en la carpeta res según su tipo:

CarpetaTipo de RecursoFormatos
drawableImágenes.png, .jpeg
fontTipografías.ttf, .otf
rawImágenes vectoriales.svg
xmlTextos localizados.xml

Configuración Específica para iOS

Requisitos de iOS

  • iOS 15.1 - 26.0
  • Xcode 14.0+

Configuración del Podfile

En el archivo ios/Podfile, establece la versión mínima en 15.1 y agrega el pod de WorkflowController:

platform :ios, '15.1'

target 'TuApp' do
# Otras configuraciones y pods
pod 'WorkflowController', :podspec => 'https://storage.googleapis.com/workflows-mobile-sdk-artifacts/WorkflowiOS/WorkflowController/WorkflowsController.podspec'
end

Nota: El target WorkflowsReactNative es generado automáticamente por CocoaPods al instalar este paquete. No es necesario modificar este nombre.

Agrega el siguiente bloque post_install en tu Podfile:

post_install do |installer|
system("mv Pods/WorkflowController/MediaPipeTasks*.xcframework Pods/")
installer.pods_project.targets.each do |target|
if target.name == 'WorkflowsReactNative'
puts "[WorkflowSDK] MATCHED Pod Target: WorkflowsReactNative"
group = target.project.main_group.find_subpath("Pods/WorkflowController", true)
%w(MediaPipeTasksVision.xcframework MediaPipeTasksCommon.xcframework).each do |fw|
file_path = File.join(Pod::Config.instance.installation_root, "Pods", "WorkflowController", fw)
puts "[WorkflowSDK] Adding #{fw} to #{target.name}"
ref = group.new_file(file_path)
ref.source_tree = 'SOURCE_ROOT'
target.frameworks_build_phase.add_file_reference(ref, true)
build_files = target.frameworks_build_phase.files.select { |f| f.file_ref == ref }
build_files.each { |bf| bf.settings = { 'ATTRIBUTES' => ['Required'] } }
end
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
installer.pods_project.save
end

Instalación de Dependencias

Desde la carpeta ios de tu proyecto, ejecuta:

pod install

Permisos en Info.plist

Agrega los permisos necesarios al archivo Info.plist o en el target properties seleccionando la pestaña Info:

<key>NSCameraUsageDescription</key>
<string>3D Liveness Detection by FaceTec.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone to record audio.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>The example App requires access to the devices location.</string>

Recursos Personalizados

Para usar recursos personalizados, agrégalos directamente a la carpeta del proyecto:

Tipo de RecursoFormatoUbicación
Textos.stringsCarpeta del proyecto
Imágenes SVG.svgCarpeta del proyecto
Tipografías.otf, .ttfCarpeta del proyecto
Imágenes PNG/JPG.png, .jpgAsset Catalog

Uso del SDK

Importación

Importa los componentes necesarios del SDK:

import type { WorkflowCustomization } from '@rem-tools/workflows-react-native';
import {
closeWorkflow,
useWorkflow,
useWorkflowEvents,
verifyWorkflowsLicense
} from '@rem-tools/workflows-react-native';

Verificación de Licencia

Antes de iniciar un workflow, debes verificar la licencia del SDK:

verifyWorkflowsLicense({
cert: "tu_certificado", // Base64-encoded PFX
passphrase: "tu_passphrase" // Base64-PFX passphrase
});
danger

Las credenciales de licencia (cert y passphrase) serán compartidas de forma privada por tu administrador de cuenta.

Inicialización del Workflow

Utiliza el hook useWorkflow para configurar y lanzar un workflow:

const launchWorkflow = useWorkflow({
baseUrl: 'https://api.rem.tools', // Your Workflows backend URL
apiKey: 'tu_api_key', // Your API key
workflowId: 'tu_workflow_id', // Workflow ID to execute
customization: getWorkflowCustomization() // null = default UI, or customize
});

Manejo de Eventos

Utiliza el hook useWorkflowEvents para escuchar los eventos del workflow:

const { workflowStart, workflowEvent, workflowStep } = useWorkflowEvents();

// Evento de inicio del workflow
useEffect(() => {
if (workflowStart) {
console.log("Workflow started success:", workflowStart.success);
if (workflowStart.error !== undefined) {
console.log("Workflow Id Error:", workflowStart.error);
}
}
}, [workflowStart]);

// Eventos del workflow
useEffect(() => {
if (workflowEvent) {
console.log("Workflow UUID:", workflowEvent.uuid, "Status:", workflowEvent.status);
if (workflowEvent.error) {
console.log("Workflow Error:", workflowEvent.error);
}
}
}, [workflowEvent]);

// Eventos de pasos
useEffect(() => {
if (workflowStep) {
console.log("Step:", workflowStep.step, "Status:", workflowStep.status);
const error = workflowStep.error;
if (error && (workflowStep.status === "error" || workflowStep.status === "failed")) {
console.log("Error - fatal:", error.fatal,
"errorId:", error.details?.errorId,
"reason:", error.details?.reason);

const extra = error.extra;
if (extra) {
if (extra.idScanStatus != null || extra.faceScanStatus != null) {
console.log("idScanStatus:", extra.idScanStatus,
"faceScanStatus:", extra.faceScanStatus);
}
if (extra.permission != null) {
console.log("Permission denied:", extra.permission);
// Cerrar la actividad/vista de workflows
closeWorkflow();
}
if (extra.secure != null) {
console.log("Is device secure:", extra.secure);
}
if (extra.isLicenseValid != null) {
console.log("Is license valid:", extra.isLicenseValid);
}
}
}
}
}, [workflowStep]);

Lanzar el Workflow

Para lanzar la pantalla de workflows, simplemente llama al hook:

<Button title="Iniciar Workflow" onPress={launchWorkflow} />

Cerrar el Workflow

Workflows se abre en una nueva activity/controller. Para cerrar, usa la función closeWorkflow():

closeWorkflow();

Personalización del SDK

Puedes personalizar la apariencia del SDK mediante la función de configuración:

import { Platform } from 'react-native';

function getWorkflowCustomization(): WorkflowCustomization {
return {
theme: {
primaryColor: '#61DBFB',
secondaryColor: '#20232A',
buttonPrimaryColor: '#61DBFB',
buttonSecondaryColor: '#20232A',
buttonTextPrimaryColor: '#FF6F61',
buttonTextSecondaryColor: '#F9A826',
backgroundColor: '#F5F5F5',
facetecOverlayColor: '#F5F5F5',
showHeaderLogo: true
},
textLocalization: {
localization: Platform.OS === 'android'
? 'localizable.xml'
: 'Localizable.strings'
},
textFont: {
headerFont: Platform.OS === 'android'
? 'montserrat_black.ttf'
: 'Montserrat-Black.ttf',
bodyFont: Platform.OS === 'android'
? 'montserrat_regular.ttf'
: 'Montserrat-Regular.ttf',
buttonFont: Platform.OS === 'android'
? 'playwrite_ar_regular.ttf'
: 'PlaywriteAR-Regular.ttf'
},
images: {
logo: 'logo.png',
cameraPermissions: 'cam.png',
uploadFaceScan: 'upload.png',
uploadFaceSuccess: 'exito_success.png',
uploadFaceError: 'error_image.png',
photoMathId: 'id.png',
cameraActiveTorch: 'on_flash.png',
cameraInactiveTorch: 'off_flash.png',
fingerPrint: 'fing.png',
successPage: 'success.svg',
errorPage: 'error.svg',
unavailablePage: 'error.svg',
locationPage: 'ubicacion.svg',
biometricSignPage: 'face_match.svg',
enrollFingerprintPage: 'face_match.svg',
enrollBasicPage: 'face_match.svg',
enrollFullPage: 'face_match.svg',
authPage: 'face_match.svg',
livenessPage: 'face_match.svg',
faceEnrollment3dPage: 'face_match.svg'
}
};
}

Ejemplo Completo

import React, { useEffect } from 'react';
import { View, Button, Platform } from 'react-native';
import type { WorkflowCustomization } from '@rem-tools/workflows-react-native';
import {
closeWorkflow,
useWorkflow,
useWorkflowEvents,
verifyWorkflowsLicense
} from '@rem-tools/workflows-react-native';

function getWorkflowCustomization(): WorkflowCustomization {
return {
theme: {
primaryColor: '#61DBFB',
secondaryColor: '#20232A',
buttonPrimaryColor: '#61DBFB',
buttonSecondaryColor: '#20232A',
buttonTextPrimaryColor: '#FFFFFF',
buttonTextSecondaryColor: '#FFFFFF',
backgroundColor: '#F5F5F5',
facetecOverlayColor: '#000000',
showHeaderLogo: true
},
textLocalization: {
localization: Platform.OS === 'android'
? 'localizable.xml'
: 'Localizable.strings'
},
textFont: {
headerFont: Platform.OS === 'android'
? 'montserrat_black.ttf'
: 'Montserrat-Black.ttf',
bodyFont: Platform.OS === 'android'
? 'montserrat_regular.ttf'
: 'Montserrat-Regular.ttf',
buttonFont: Platform.OS === 'android'
? 'montserrat_bold.ttf'
: 'Montserrat-Bold.ttf'
},
images: {
logo: 'logo.png',
cameraPermissions: 'camera.png',
uploadFaceScan: 'upload.png',
uploadFaceSuccess: 'success.png',
uploadFaceError: 'error.png',
photoMathId: 'id.png',
cameraActiveTorch: 'flash_on.png',
cameraInactiveTorch: 'flash_off.png',
fingerPrint: 'fingerprint.png',
successPage: 'success.svg',
errorPage: 'error.svg',
unavailablePage: 'unavailable.svg',
locationPage: 'location.svg',
biometricSignPage: 'biometric.svg',
enrollFingerprintPage: 'fingerprint.svg',
enrollBasicPage: 'enroll.svg',
enrollFullPage: 'enroll_full.svg',
authPage: 'auth.svg',
livenessPage: 'liveness.svg',
faceEnrollment3dPage: 'face_3d.svg'
}
};
}

export default function WorkflowScreen() {
// Verificar licencia al iniciar
useEffect(() => {
verifyWorkflowsLicense({
cert: "tu_certificado",
passphrase: "tu_passphrase"
});
}, []);

// Configurar el workflow
const launchWorkflow = useWorkflow({
baseUrl: 'https://api.rem.tools',
apiKey: 'tu_api_key',
workflowId: 'tu_workflow_id',
customization: getWorkflowCustomization()
});

// Escuchar eventos
const { workflowStart, workflowEvent, workflowStep } = useWorkflowEvents();

useEffect(() => {
if (workflowStart) {
console.log("Workflow started:", workflowStart.success);
}
}, [workflowStart]);

useEffect(() => {
if (workflowEvent) {
console.log("Workflow status:", workflowEvent.status);
}
}, [workflowEvent]);

useEffect(() => {
if (workflowStep) {
console.log("Step status:", workflowStep.status);
}
}, [workflowStep]);

return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title="Iniciar Workflow" onPress={launchWorkflow} />
</View>
);
}

FAQ

¿Cómo obtengo el workflowId?

El workflowId se obtiene al crear un Workflow mediante nuestra API de Workflows. La respuesta de la API te proporcionará este identificador.

¿Cómo consigo el apiKey y el baseUrl?

El apiKey es proporcionado de forma privada, y el baseUrl suele ser:

  • https://api.rem.tools para producción.
  • https://api.test.rem.tools para pruebas.

¿Cómo obtengo las credenciales de licencia?

Las credenciales de licencia (cert y passphrase) para la función verifyWorkflowsLicense serán compartidas de forma privada por tu administrador de cuenta.

¿Cómo cierro el workflow programáticamente?

Utiliza la función closeWorkflow() que se importa del SDK. Esto cerrará la activity/controller del workflow.

tip

Si tienes alguna duda o problema con la integración del SDK, por favor contacta a soporte.

rem

JOIN US ON

facebooktwitterLinkedIn
CONTACThello@rem.tools55-91-03-80-54
© Copyright rem 2022 All rights reserved.