Skip to main content

Nativo

Nuestro SDK Nativo de Workflows para Android e iOS permite una experiencia más eficiente y segura para el usuario final. El SDK de Workflows de Nativo permite a los desarrolladores de aplicaciones móviles integrar la funcionalidad de Workflows en sus aplicaciones nativas de Android e iOS.

iOS

La integración del SDK de Workflows en tu aplicación iOS es un proceso sencillo que consta de los siguientes pasos:

Requisitos

  • iOS 15.1 - 26.0
  • Xcode 14.0+

Configuración

Instalación de CocoaPods

Para integrar el SDK de Workflows, primero asegúrate de que tu Podfile esté configurado para soportar la versión mínima de iOS requerida:

platform :ios, '15.1'
target 'TuApp' do
use_frameworks!
pod 'WorkflowControllerDebug',
:podspec => 'https://storage.googleapis.com/workflows-mobile-sdk-artifacts/WorkflowiOS/WorkflowController/WorkflowsControllerDebug.podspec',
:configurations => ['Debug']
pod 'WorkflowControllerRelease',
:podspec => 'https://storage.googleapis.com/workflows-mobile-sdk-artifacts/WorkflowiOS/WorkflowController/WorkflowsControllerRelease.podspec',
:configurations => ['Release']
end
danger

Si no tienes acceso al repositorio del SDK, por favor contacta a tu administrador de cuenta o a soporte, ya que necesitarás acceso al repositorio privado del SDK.

Agrega el siguiente bloque post_install en tu Podfile. Asegúrate de modificar Pods-TuApp por el target de tu aplicación (debe conservar el prefijo Pods- antes del nombre del proyecto):

post_install do |installer|
['WorkflowControllerDebug', 'WorkflowControllerRelease'].each do |pod_name|
Dir.glob("Pods/#{pod_name}/MediaPipeTasks*.xcframework").each do |path|
system("mv '#{path}' Pods/")
end
end
installer.pods_project.targets.each do |target|
if target.name == 'Pods-TuApp' # Reemplaza TuApp con el nombre de tu proyecto
['WorkflowControllerDebug', 'WorkflowControllerRelease'].each do |pod_name|
group = target.project.main_group.find_subpath("Pods/#{pod_name}", false)
next unless group
%w(MediaPipeTasksVision.xcframework MediaPipeTasksCommon.xcframework).each do |fw|
ref = group.new_file(fw)
ref.source_tree = 'SOURCE_ROOT'
target.frameworks_build_phase.add_file_reference(ref)
end
end
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = "arm64"
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
installer.pods_project.save
end

Abre una terminal, navega al directorio de tu proyecto y ejecuta el siguiente comando para instalar el SDK:

pod install

Importante: Recomendamos limpiar las dependencias de CocoaPods antes de volver a instalar.

Desde la carpeta ios, ejecuta:

rm -rf Pods
rm Podfile.lock
pod install

Esto asegura que las dependencias nativas se reinstalen correctamente y evita conflictos con versiones previamente instaladas.


Configuración de Build Settings

En los Build Settings del proyecto, en la sección Build Options, establece User Script Sandboxing en NO.

Configuración de Permisos en Info.plist

Es necesario declarar los permisos que tu aplicación requiere. Añade las siguientes claves en tu archivo Info.plist con descripciones adecuadas sobre cómo tu app usa estos recursos:

<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 en tu aplicación, 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

Importación del SDK

Para usar el SDK en tu código, primero debes importarlo:

import WorkflowSDK

Verificación de Licencia

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

WorkflowController.verifyWorkflowsLicense(cert: "tu_certificado", passphrase: "tu_passphrase")
danger

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

Configuración de Personalización

Puedes personalizar la apariencia del SDK mediante WorkflowCustomization:

let workflowCustomization = WorkflowCustomization(
textLocalization: WorkflowCustomization.TextLocalization(
localization: "Localizable.strings"
),
textFont: WorkflowCustomization.TextFont(
headerFont: "Oswald-Bold.ttf",
bodyFont: "Oswald-Regular.ttf",
buttonFont: "Merriweather-Bold.ttf"
),
theme: WorkflowCustomization.Theme(
primaryColor: "#ec2d01",
secondaryColor: "#f59680",
buttonPrimaryColor: "#ec2d01",
buttonSecondaryColor: "#f59680",
buttonTextPrimaryColor: "#fbd5cc",
buttonTextSecondaryColor: "#f9c0b2",
backgroundColor: "#460d00",
facetecOverlayColor: "#761600",
showHeaderLogo: true
),
images: WorkflowCustomization.Images(
logo: "logo.png",
cameraPermissions: "camera_permissions.png",
uploadFaceScan: "upload_face.png",
uploadFaceSuccess: "success.png",
uploadFaceError: "error.png",
photoMathId: "id.png",
photoMathIdBack: "id_back.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_sign.svg",
enrollFingerprintPage: "enroll_fingerprint.svg",
enrollBasicPage: "enroll_basic.svg",
enrollFullPage: "enroll_full.svg",
authPage: "auth.svg",
livenessPage: "liveness.svg",
faceEnrollment3dPage: "face_enrollment_3d.svg"
)
)

Inicialización del WorkflowController

Inicializa el WorkflowController con la URL base, las API keys y la personalización:

let workflowController = WorkflowController(
baseUrl: "https://api.rem.tools",
remApiKey: "tu_rem_api_key",
publicKey: "tu_public_api_key",
workflowCustomization: workflowCustomization
)

Iniciar un Workflow

Para iniciar un workflow, usa el método start con el ID del workflow que deseas iniciar:

workflowController.start(workflowId: "workflow_id") { (success: Bool, error: WorkflowError?) in
if success {
print("Workflow iniciado")
} else {
print("Error al iniciar el workflow: \(String(describing: error))")
}
}

Manejo de Eventos de Workflow

Puedes escuchar eventos de workflow mediante closures:

workflowController.onStepEvent() { (step: Step) in
print("Evento de paso: \(step.status)")
}

workflowController.onWorkflowEvent() { (workflow: Workflow) in
print("Workflow UUID: \(workflow.uuid)")
}
tip

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


Android

La integración del SDK de Workflows en tu aplicación Android es un proceso sencillo que consta de los siguientes pasos:

Requisitos

  • Android API 29 - 36
  • Android Studio Hedgehog+

Configuración

Configuración de settings.gradle

En el archivo settings.gradle (Project Settings), cambia el modo de repositorios a PREFER_PROJECT:

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
}

Configuración de Repositorios

En el archivo build.gradle (app), declara de dónde se obtendrán las dependencias:

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

Si no tienes acceso al repositorio o al archivo de credenciales, por favor contacta a tu administrador de cuenta o a soporte, ya que necesitarás acceso al repositorio privado del SDK.

Implementación de Dependencias

Agrega las dependencias de Workflows en el archivo build.gradle de tu módulo:

dependencies {
// SDK Implementation
implementation ('tools.rem.workflows:sdk:1.22.2@aar') { transitive = true }

// Required dependencies
implementation 'com.getkeepsafe.relinker:relinker:1.4.5'
implementation "androidx.window:window:1.0.0"
implementation 'com.google.android.gms:play-services-location:21.3.0'
implementation 'com.squareup.okhttp3:okhttp:5.1.0'
implementation 'com.squareup.okio:okio:3.16.0'
implementation 'com.google.code.gson:gson:2.13.1'
implementation "com.bugsnag:bugsnag-android:6.17.0"
implementation 'com.google.mediapipe:tasks-vision:0.10.32'

// Media3 dependencies
implementation "androidx.media3:media3-exoplayer:1.4.1"
implementation "androidx.media3:media3-exoplayer-hls:1.4.1"
implementation "androidx.media3:media3-exoplayer-dash:1.4.1"
implementation "androidx.media3:media3-exoplayer-rtsp:1.4.1"
implementation "androidx.media3:media3-exoplayer-smoothstreaming:1.4.1"

// Camera dependencies
implementation "com.otaliastudios:cameraview:2.7.2"
implementation "androidx.camera:camera-core:1.5.3"
implementation "androidx.camera:camera-camera2:1.5.3"
implementation "androidx.camera:camera-lifecycle:1.5.3"
implementation "androidx.camera:camera-video:1.5.3"
implementation "androidx.camera:camera-view:1.5.3"
implementation "androidx.camera:camera-extensions:1.5.3"

// Other dependencies
implementation 'com.google.guava:guava:27.1-android'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2'
}

Compatibilidad con el tema de la aplicación

Para evitar conflictos con el tema de la aplicación, agrega el siguiente atributo en el archivo AndroidManifest.xml:

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

Configuración de Release Build

Para ejecutar en modo release, agrega lo siguiente en el archivo build.gradle a nivel de android:

android {
// ...

buildTypes {
release {
shrinkResources false
// otras configuraciones...
}
}

aaptOptions {
noCompress "tflite", "task"
}

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

No excluyas librerías .so requeridas por el SDK usando packagingOptions o packaging.jniLibs.

Por ejemplo, NO debes usar:

packagingOptions {
exclude 'lib/arm64-v8a/libPhoenixAndroid.so'
}

El SDK depende de librerías nativas como:

lib/arm64-v8a/libPhoenixAndroid.so

Si se excluyen, la aplicación puede compilar pero fallará en ejecución, especialmente en la inicialización de biometría.

Configuración de ProGuard

Agrega las siguientes reglas al archivo proguard-rules.pro:

# 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 tools.rem.workflows_flutter_plugin.Models.Step.Step { *; }
-keep class tools.rem.workflows_flutter_plugin.Models.Workflow.Workflow { *; }
-keep class tools.rem.workflows_flutter_plugin.Models.WorkflowError { *; }
-keep class tools.rem.workflows_flutter_plugin.WorkflowsFlutterPlugin { *; }
-keepclassmembers class tools.rem.workflows_flutter_plugin.Models.Workflow.Workflow {
public <init>(...);
}
-keep class tools.rem.workflows_flutter_plugin.Models.ConfigFacetec { *; }
-keepclassmembers class tools.rem.workflows_flutter_plugin.Models.ConfigFacetec {
public <init>(...);
}

#Keep the mediapipe classes
-keep public class com.google.mediapipe.framework.Graph.** { *; }
-keep interface com.google.common.** { *; }
-keep class * extends com.google.common.flogger.** {*;}
-keep class com.google.common.** { *; }
-keep class com.google.common.flogger.** { *; }
-keep class com.google.mediapipe.tasks.** { *; }
-keep class com.google.mediapipe.tasks.vision.** { *; }
-keep class com.google.mediapipe.tasks.core.** { *; }
-keep class com.google.mediapipe.framework.ProtoUtil$* { *; }
-keep class com.google.mediapipe.framework.** { *; }
-keep class com.google.mediapipe.framework.image.** { *; }
-keep class com.google.mediapipe.** { *; }
-keep class com.google.mediapipe.proto.** { *; }
-keep class javax.lang.model.** { *; }
-keep class com.google.mediapipe.solutioncore.** { *; }
-keep class com.google.protobuf.** { *; }
-keep class org.tensorflow.lite.** { *; }
-dontwarn com.google.mediapipe.proto.CalculatorProfileProto$CalculatorProfile
-dontwarn com.google.mediapipe.proto.GraphTemplateProto$CalculatorGraphTemplate
-dontwarn org.tensorflow.lite.**
-dontwarn javax.annotation.**
-dontwarn javax.lang.model.**
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite.** { *; }
-keepclassmembers class com.google.mediapipe.**$$ExternalSyntheticLambda* { *; }
-keepattributes InnerClasses,EnclosingMethod,Signature,*Annotation*

#Keep the okhttp3 classes
-keep class okhttp3.** { *; }
-keep class okio.** { *; }

#Keep the gson classes
-keep class com.google.gson.** { *; }

#Keep the facetec classes
-dontwarn javax.annotation.Nullable
-dontwarn com.facetec.sdk.**
-keep,includecode,includedescriptorclasses class com.facetec.sdk.** { *; }

#Keep the cameraview classes
-keep class com.otaliastudios.cameraview.** { *; }
-dontwarn com.otaliastudios.cameraview.**

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

Uso

Importación del SDK

Para usar el SDK en tu código Kotlin, primero debes importarlo:

import tools.rem.workflows.WorkflowsActivity
import tools.rem.workflows.model.WorkflowCustomization
import tools.rem.workflows_flutter_plugin.Models.Step.Step
import tools.rem.workflows_flutter_plugin.Models.Workflow.Workflow
import tools.rem.workflows_flutter_plugin.Models.WorkflowError

Verificación de Licencia

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

WorkflowsActivity.verifyWorkflowsLicense("tu_certificado", "tu_passphrase")
danger

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

Configuración de Personalización

Puedes personalizar la apariencia del SDK mediante WorkflowCustomization:

val workflowCustomization = WorkflowCustomization(
textLocalization = WorkflowCustomization.TextLocalization(
localization = R.xml.localizable
),
textFont = WorkflowCustomization.TextFont(
headerFont = R.font.oswald_bold,
bodyFont = R.font.oswald_regular,
buttonFont = R.font.merriweather_bold
),
theme = WorkflowCustomization.Theme(
primaryColor = "#ec2d01",
secondaryColor = "#f59680",
buttonPrimaryColor = "#ec2d01",
buttonSecondaryColor = "#f59680",
buttonTextPrimaryColor = "#fbd5cc",
buttonTextSecondaryColor = "#f9c0b2",
backgroundColor = "#460d00",
facetecOverlayColor = "#761600",
showHeaderLogo = true
),
images = WorkflowCustomization.Images(
logo = R.drawable.logo,
cameraPermissions = R.drawable.camera_permissions,
uploadFaceScan = R.drawable.upload_face,
uploadFaceSuccess = R.drawable.success,
uploadFaceError = R.drawable.error,
photoMathId = R.drawable.id,
photoMathIdBack = R.drawable.id_back,
cameraActiveTorch = R.drawable.flash_on,
cameraInactiveTorch = R.drawable.flash_off,
fingerPrint = R.drawable.fingerprint,
successPage = R.raw.success,
errorPage = R.raw.error,
unavailablePage = R.raw.unavailable,
locationPage = R.raw.location,
biometricSignPage = R.raw.biometric_sign,
enrollFingerprintPage = R.raw.enroll_fingerprint,
enrollBasicPage = R.raw.enroll_basic,
enrollFullPage = R.raw.enroll_full,
authPage = R.raw.auth,
livenessPage = R.raw.liveness,
faceEnrollment3dPage = R.raw.face_enrollment_3d
)
)

Inicialización del WorkflowController

Inicializa el WorkflowsActivity con la URL base, las API keys y la personalización:

val workflowController = WorkflowsActivity(
"https://api.rem.tools", // Base URL
"tu_rem_api_key", // REM API Key
"tu_public_api_key", // Public API Key
workflowCustomization // Personalización
)

Iniciar un Workflow

Para iniciar un workflow, usa el método start con el ID del workflow y el contexto de la actividad:

workflowController.start(
"workflow_id",
this
) { success: Boolean, error: WorkflowError? ->
if (success) {
Log.d("Workflow", "Workflow iniciado exitosamente")
} else {
Log.e("Workflow", "Error al iniciar el workflow: $error")
}
}

Manejo de Eventos de Workflow

Puedes escuchar eventos de workflow mediante callbacks:

workflowController.onStepEvent { step: Step ->
Log.d("Workflow", "Evento de paso: ${step}")
}

workflowController.onWorkflowEvent { workflow: Workflow ->
Log.d("Workflow", "Evento de workflow: ${workflow}")
}

Ejemplo Completo

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// Verificar licencia
WorkflowsActivity.verifyWorkflowsLicense("tu_certificado", "tu_passphrase")

// Configurar personalización
val workflowCustomization = WorkflowCustomization(
// ... configuración de personalización
)

// Inicializar controller
val workflowController = WorkflowsActivity(
"https://api.rem.tools",
"tu_rem_api_key",
"tu_public_api_key",
workflowCustomization
)

// Iniciar workflow
workflowController.start("workflow_id", this) { success, error ->
Log.i("Workflows", "Start result: $success, error: $error")
}

// Escuchar eventos de pasos
workflowController.onStepEvent { step ->
Log.d("Workflows", "Step event: $step")
}

// Escuchar eventos de workflow
workflowController.onWorkflowEvent { workflow ->
Log.d("Workflows", "Workflow event: $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.