React Native
O React Native usa um sistema flexível que permite chamar APIs específicas da plataforma, estejam elas disponíveis em código Kotlin ou Java no Android ou em código Swift ou Objective-C no iOS.
Este guia ensina como integrar o AllowMeSDK ao seu aplicativo React Native utilizando o mecanismo de NativeModule.
Importante!
O tutorial abaixo possui simplificações por se tratar do código de um app de exemplo. Os resultados das chamadas são mostrados na tela para facilitar o entendimento. Você deverá fazer as modificações necessárias para a sua implementação real. Além disso, o código completo de exemplo está disponível. Entre em contato com [email protected] para ter acesso.
1. Implementação Nativa Android
Antes de prosseguir nessa seção é recomendado a leitura da integração nativa para Android.
Antes de tudo, abra o projeto Android do seu aplicativo React Native no Android Studio:

1.1 Adicionando o AllowMeSDK como dependência
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Primeiros Passos - Adicionando AllowMeSDK como dependência da documentação nativa.Com o projeto aberto, você deve adicionar o SDK e suas dependências nos arquivos build.gradle.
O AllowMeSDK está hospedado em um repositório privado Maven, acessível via Gradle. Por isso, você deve adicionar ao build.gradle do seu projeto as seguintes linhas, contendo o username, password e URL:
allprojects {
repositories {
mavenLocal()
google()
maven { url 'https://jitpack.io' }
mavenCentral()
maven {
authentication {
basic(BasicAuthentication)
}
credentials {
username 'SEU_USERNAME_AQUI'
password 'SEU_PASSWORD_AQUI'
}
url "https://android.allowmecloud.com/sdk"
}
}
}
Em seguida, você deve adicionar essas dependências ao build.gradle do seu módulo:
Build Types
Se você estiver usando builds com nomes diferentes de stage e/ou release, acrescente o campo a seguir:
buildTypes { buildParaHomolog { matchingFallbacks = ['stage'] } buildParaRelease { matchingFallbacks = ['release'] } }
1.2 Criando uma Bridge
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Primeiros Passos - Inicializar o SDK da documentação nativa.O primeiro passo é criar o arquivo do módulo nativo, que neste exemplo chamaremos de AllowMeBridge. Nesse módulo, faremos também a implementação básica do AllowMe com o método setup, responsável pela troca de chaves da criptografia.
import {...};
class AllowMeBridge(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
private val mReactContext: ReactApplicationContext = context
private var mAllowme: AllowMe? = null
{...}
override fun getName() = "AllowMeBridge"
@ReactMethod
fun initSetup(promise: Promise) {
val currentActivity: Activity? = currentActivity
if (currentActivity != null) {
ActivityCompat.requestPermissions(
currentActivity,
arrayOf(Manifest.permission.CAMERA),
1
)
}
runAllowMeCommand(object : AllowMeCommand {
override fun exec() {
mAllowme?.setup({
promise.resolve("setup success!")
}) {
promise.reject(it)
}
}
})
}
private fun lazyAllowMeInit() {
if (mAllowme == null) {
mAllowme = AllowMe.getInstance(mReactContext, BuildConfig.API_KEY)
}
}
private fun runAllowMeCommand(command: AllowMeCommand) {
mReactContext.runOnUiQueueThread {
lazyAllowMeInit()
command.exec()
}
}
private interface AllowMeCommand {
fun exec()
}
}
Como você pode ver, a classe AllowMeBridge herda da classe ReactContextBaseJavaModule e implementa as funcionalidades exigidas pelo React Native. Todos os métodos de módulo nativo destinados a serem chamados no TypeScript devem ser anotados com @ReactMethod.
Além disso, a função lazyAllowMeInit inicializa a variável mAllowme sempre que for necessário.
Também é necessário implementar o método getName(), que retorna uma String com o nome do módulo nativo, podendo assim ser acessado em seu TypeScript desse modo:
import { NativeModules } from 'react-native';
const {AllowMeBridge} = NativeModules;
1.3. Implementando o Device Intelligence (Contextual)
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Device Intelligence (Contextual) da documentação nativa.Com base no exemplo mostrado na seção anterior, podemos adicionar o código de exemplo abaixo para adicionar o produto Device Intelligence (Contextual) do AllowMeSDK com uma chamada ao método collect.
{...}
@ReactMethod
fun collect(promise: Promise) {
runAllowMeCommand(object : AllowMeCommand {
override fun exec() {
mAllowme?.collect({
promise.resolve(it)
}) {
promise.reject(it)
}
}
})
}
{...}
1.4. Implementando Validação de Endereço
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Validação de Endereço da documentação nativa.Com base no exemplo mostrado na seção anterior, podemos adicionar o código de exemplo abaixo para adicionar a função Validação de Endereço do AllowMeSDK. Observe que o método start tem como objetivo realizar o agendamento das coletas periódicas enquando o addPerson faz o envio das informações do usuário para o backend AllowMe para realização da validação de endereço.
{...}
@ReactMethod
fun start(promise: Promise) {
runAllowMeCommand(object : AllowMeCommand {
override fun exec() {
mAllowme?.start({
promise.resolve("start onboarding finished!")
}) {
promise.reject(it)
}
}
})
}
@ReactMethod
fun addPerson(promise: Promise) {
runAllowMeCommand(object : AllowMeCommand {
val address: Address = Address(
"Nome da Rua",
"Cidade",
"XX",
0,
"Bairro",
"0000-000",
"",
"",
null
)
val person: Person = Person(
"Nome da pessoa",
"00000000000",
address,
"[email protected]",
"000000000"
)
override fun exec() {
mAllowme?.addPerson(person, {
promise.resolve("addPerson onboarding finished!")
}) {
promise.reject(it)
}
}
})
}
{...}
Neste exemplo, o método addPerson que criamos instancia as classes Person e Address com valores pré-definidos. Esses valores, porém, devem ser fornecidos pela sua aplicação React Native. Mais informações sobre os parâmetros aceitos pelo método podem ser encontradas em Cadastrando uma pessoa.
1.5. Implementando a Biometria Facial
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Biometria Facial da documentação nativa.Antes de tudo, é necessário adicionar a permissão da câmera como dito na documentação nativa do Android. Na nossa implementação tomamos a decisão de adicioná-la junto ao método setup, mas fique livre para adequar ao seu aplicativo.
val currentActivity: Activity? = currentActivity
if (currentActivity != null) {
ActivityCompat.requestPermissions(
currentActivity,
arrayOf(Manifest.permission.CAMERA),
1
)
}
O próximo passo será chamar a Activity responsável pela captura das fotos como mostra o código abaixo:
private var mPromise: Promise? = null
{...}
@ReactMethod
fun showBiometrics(promise: Promise) {
runAllowMeCommand(object : AllowMeCommand {
override fun exec() {
val currentActivity = currentActivity as? AppCompatActivity
mPromise = promise
if (currentActivity != null) {
mAllowme?.startBiometrics(currentActivity) { biometricsResult ->
if (biometricsResult.errorType == null) {
//REQUEST TO SERVER
var result = ("payload: " + biometricsResult.payload) + " | "
for (path in biometricsResult.paths) {
result += "$path & "
}
mPromise?.resolve(result)
} else {
// biometricsResult.errorType
mPromise?.reject("Biometrics Error", biometricsResult.errorType?.message)
}
}
}
})
}
{...}
Observe que criamos uma variável chamada mPromise na classe para receber o resultado da biometria.
O resultado acima é transformado em String para ser mostrado na tela a partir do código em dart. Faça as modificações necessárias para a sua implementação!
TIP
Para informações de como implementar a Biometria Facial com provider Facetec, veja as seções 2.1. Iniciando a Biometria Facial da Facetec, 3.1 Tratando erros gerados pelo provedor (Facetec) e 5. Customização de Layout - Facetec.
1.6. Registrando a Bridge e o Package
Depois da criação da bridge, adicione-a a um ReactPackage criando uma nova classe Java chamada AllowMeReactPackage.kt que implementa ReactPackage.
import {...}
class AllowMeReactPackage : ReactPackage {
override fun createViewManagers(
reactContext: ReactApplicationContext
): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()
override fun createNativeModules(
reactContext: ReactApplicationContext
): MutableList<NativeModule> = listOf(AllowMeBridge(reactContext)).toMutableList()
}
Após a implementação do AllowMeReactPackage, adicione-o à lista de pacotes retornados no método getPackages() de ReactNativeHost. Esse arquivo se encontra na classe MainApplication.kt
import {...};
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(AllowMeReactPackage())
}
{...}
}
{...}
}
2. Implementação Nativa iOS
Antes de prosseguir nessa seção é recomendado a leitura da integração nativa para iOS v2.
Para começar, abra o projeto iOS em seu aplicativo React Native no Xcode:

2.1. Adicionando o AllowMeSDK como dependência
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Primeiros Passos - Adicionando AllowMeSDK como dependência da documentação nativa.Antes de começar, certifique-se de que esteja de posse das credenciais de acesso aos nossos repositórios!
WARNING
Caso não faça ideia de onde estejam essas credenciais, entre em contato com o nosso suporte em [email protected].
Você terá duas opções de SDK: o AllowMeSDK de homologação e o de produção. A versão de homologação deve ser usada para testes e debug, enquanto a de produção deve ser enviada para a AppStore junto ao seu aplicativo. Você deve adicionar o AllowMeSDKHomolog ao seu target de Debug!
O nosso SDK tem suporte para Swift Package Manager e Cocoapods. Escolha o que for melhor para o seu projeto, acesse o arquivo xcworkspace no Xcode os passos descritos na documentação nativa:
Swift Package ManagerCocoapods
2.2. Criando uma Bridge
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Primeiros Passos - Importar e Inicializar o SDK da documentação nativa.Antes de tudo, importe o AllowMe de acordo com a configuração usada. Lembre-se que você deve adicionar o AllowMeSDKHomolog ao seu target de debug/homologação e o AllowMeSDK ao target de release/produção.
#if DEBUG
import AllowMeSDKHomolog
let ALLOWE_API_KEY = "your-homolog-api-key-here"
#else
import AllowMeSDK
let ALLOWE_API_KEY = "your-prod-api-key-here"
#endif
Após isso, o primeiro passo é criar o arquivo do módulo nativo, que neste exemplo chamaremos de AllowMeBridge. Faremos a implementação em Objective-C, o que significa que criaremos inicialmente o AllowMeBridge.h como mostrado abaixo:
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#if DEBUG
import AllowMeSDKHomolog
let ALLOWE_API_KEY = "your-homolog-api-key-here"
#else
import AllowMeSDK
let ALLOWE_API_KEY = "your-prod-api-key-here"
#endif
@interface AllowMeBridge : NSObject <RCTBridgeModule>
@property (nonatomic, weak) AllowMe *allowMe;
@end
E, em seguida, criaremos o arquivo de implementação correspondente AllowMeBridge.m na mesma pasta. Por enquanto, o nosso módulo nativo AllowMeBridge.m inclui apenas uma macro RCT_EXPORT_MODULE, que exporta e registra a classe do módulo nativo para o React Native. A macro RCT_EXPORT_MODULE também aceita um argumento opcional que especifica o nome pelo qual o módulo estará acessível em seu código TypeScript. Para esse exemplo vamos manter com o valor default.
Vale ressaltar que o React Native não exportará nenhum método em um módulo nativo para o TypeScript a menos que seja explicitamente informado com a utilização da macro RCT_EXPORT_METHOD.
#import "AllowMeBridge.h"
@implementation AllowMeBridge
// Exporta um módulo chamado AllowMeBridge
RCT_EXPORT_MODULE();
@end
Nesse arquivo implementaremos a primeira função do AllowMe: o setup, que é usado para realizar a troca de chaves que garante a segurança de todos os nossos produtos. Marcaremos ele como RCT_EXPORT_METHOD.
@implementation AllowMeBridge
AllowMe* mAllowMe;
RCTPromiseRejectBlock mReject;
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(initSetup:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
mReject = reject;
[self getAllowMeInstance];
[mAllowMe setupWithCompletion:^(NSError * setupError) {
if(setupError == nil) {
resolve(@"setup success");
} else {
reject(@"Setup Error",
[setupError localizedDescription],
setupError);
}
}];
};
- (void) getAllowMeInstance {
if (mAllowMe == nil) {
NSError* error = nil;
mAllowMe = [AllowMe getInstanceWithApiKey:ALLOWME_API_KEY error: &error];
if(error != nil) {
mReject(@"AllowMe Instance Error",
[error localizedDescription],
error);
}
}
}
Note que implementamos tmabém a função getAllowMeInstance, que inicializa a variável mAllowme sempre que for necessário. Além disso,a fim de retornar possíveis erros na inicialização para o app React Native, escolhemos criar uma nova variável para armazenar o reject.
Agora, verifique os produtos contratados para seguir na implementação mostrada nas próximas seções!
2.3. Implementando o Device Intelligence (Contextual)
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Device Intelligence (Contextual) da documentação nativa.Tomando o código anterior como base, vamos adicionar um novo método para realizar a chamada ao método collect que retorna uma string criptografada contendo o fingerprint gerado pelo AllowMe. Observe o exemplo com o código abaixo:
RCT_REMAP_METHOD(collect, withResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
mReject = reject;
[self getAllowMeInstance];
[mAllowMe collectOnSuccess:^(NSString * collect) {
resolve(collect);
} onError:^(NSError * collectError) {
reject(@"Collect Error", [collectError localizedDescription], collectError);
}];
};
2.4. Implementando Validação de Endereço
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Validação de Endereço da documentação nativa.Ao contrário dos métodos mencionados anteriormente, o método start de agendamento de coletas para a função de Validação de Endereço deve apenas ser chamado durante a inicialização do app iOS no arquivo AppDelegate.mm
{...}
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
{...}
NSError* error = nil;
AllowMe* allowMe = [AllowMe getInstanceWithApiKey:ALLOWME_API_KEY error: &error];
if(error == nil) {
NSError* startError = [allowMe start];
if(startError != nil) {
NSLog(@"Start Error: %@", [startError localizedDescription]);
}
} else {
NSLog(@"AllowMe Instance Error: %@",[error localizedDescription]);
}
{...}
}
IMPORTANTE!!!
Verifique a documentação nativa para entender porque o start deve ser chamado sempre durante a inicialização e realizar a configuração necessária de Background Modes. Observe também na documentação nativa a necessidade de chamar, ou não, o método abaixo conforme fizemos com o método application
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
NSError* error = nil;
AllowMe* allowMe = [AllowMe getInstanceWithApiKey:ALLOWME_API_KEY error: &error];
if(error == nil) {
[allowMe application:application performFetchWithCompletionHandler:completionHandler];
}
}
Após isso, de volta ao AllowMeBridge.m implementaremos a função addPerson:
RCT_EXPORT_METHOD(addPerson:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
PersonModel* person = [self getPerson];
mReject = reject;
[self getAllowMeInstance];
[mAllowMe addPersonWithPerson:person completion:^(NSError * error) {
if(error == nil) {
resolve(@"Pessoa adicionada com sucesso");
} else {
reject(@"Onboarding Error", [error localizedDescription], error);
}
}];
};
- (PersonModel*)getPerson {
AddressModel *address = [
[AddressModel alloc] initWithStreet:@"Rua"
number:@"000"
neighbourhood:@"Bairro"
city: @"Cidade"
state: @"AA"
zipCode: @"00000000"
];
PersonModel *person = [
[PersonModel alloc] initWithName:@"Nome"
nationalId:@"00000000000"
address:address
];
return person;
};
Veja a documentação nativa da Validação de Endereço para ver todos os dados que podem ser passados para o método addPerson a partir de sua aplicação React Native.
2.5. Implementando a Biometria Facial
Essa seção se refere à implementação em React Native do que é mostrado com mais detalhes em Biometria Facial da documentação nativa.Do mesmo modo, vamos criar uma função para inicializar a tela da Biometria Facial a partir da nossa implementação nativa
@implementation AllowMeBridge
AllowMe* mAllowMe;
RCTPromiseRejectBlock mReject;
RCTPromiseResolveBlock mPromise;
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(showBiometrics:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
dispatch_async(dispatch_get_main_queue(), ^{
mResolve = resolve;
mReject = reject;
[self getAllowMeInstance];
AllowMeBiometricsConfig* config = [[AllowMeBiometricsConfig alloc] init];
UIWindow *window = (UIWindow*)[[UIApplication sharedApplication] windows][0];
UIViewController* vc = window.rootViewController;
[mAllowMe startBiometricsWithViewController:vc delegate:self config:config];
});
}
TIP
Observe a documentação nativa da Biometria Facial para verificar todas as possibilidades de customização disponíveis com a AllowMeBiometricsConfig.
Observe que o código da chamada da Biometria Facial é feito dentro de um dispatch_async para garantir que ele será feito na Main Thread. Por se tratar de uma interação visual, o iOS nos obriga a realizar esse tipo de operação na thread Main ou o app pode crashar.
Para receber o resultado das capturas, precisamos implementar o delegate que foi passado para o startBiometricsWithViewController. Você pode passar qualquer classe que implemente o AllowMeBiometricsDelegate. No nosso caso, passamos a própria AllowMeBridge e atualizamos o protocolo em AllowMeBridge.h
@interface AllowMeBridge : NSObject <RCTBridgeModule, AllowMeBiometricsDelegate>
{...}
@end
De volta ao AllowMeBridge.m devemos implementar a função do protocolo:
- (void) biometricsDidFinishWithBiometricsObject:(AllowMeBiometricsResult *)biometricsObject error:(NSError *)error {
if(biometricsObject != nil) {
NSString *result = [NSString stringWithFormat:@"Biometrics object payload: %@ | images: %@", [biometricsObject payload], [biometricsObject images]];
mResolve(result);
} else {
mReject(@"Biometrics Error", [error localizedDescription], error);
}
}
Para retornar o resultado para o app React Native, escolhemos criar uma nova variável para armazenar o promise e chamamos essa variável no retorno do delegate.
TIP
Para informações de como implementar a Biometria Facial com provider Facetec, veja as seções 4.3. Telas de Captura FaceTec e providerError na seção 5. Implementação do AllowMeBiometricsDelegate.
3. Integrando com o código TypeScript
Agora que criamos os canais de comunicação no Android e iOS precisamos chamá-los através da nossa aplicação React Native em TypeScript. Para isso vamos acessar o módulo nativo invocando seu método exportado em TypeScript. Fazemos isso da seguinte maneira:
import { NativeModules } from 'react-native';
const {AllowMeBridge} = NativeModules;
export default AllowMeBridge;
Por questões de organização de código, nós colocamos esse trecho isolado em um arquivo chamado AllowMeBridgeNativeModule.tx. Agora basta escolher onde você deseja utilizar o AllowMeSDK e importar o módulo:
import AllowMeBridge from './AllowMeBridgeNativeModule';
Para cada botão do nosso aplicativo React Native, vamos chamar cada uma das funções abaixo conforme a necessidade dos produtos contratados e implementados anteriormente
import {...};
import AllowMeBridge from './AllowMeBridgeNativeModule';
type State = {
result: any;
}
export default class App extends React.Component<{}, State> {
constructor(props: {}) {
super(props);
this.state = { result: '' };
}
// AllowMe Geral - Primeiros Passos
async onSetupClick() {
try {
var result = await AllowMeBridge.initSetup();
this.setState({ result: result });
} catch (e) {
console.error(e);
}
}
// AllowMe Device Intelligence (Contextual)
async onCollectClick() {
try {
var result = await AllowMeBridge.collect();
this.setState({ result: 'Coleta: ' + result });
} catch (e) {
console.error(e);
}
}
// AllowMe Validação de Endereço
async onAddPersonClick() {
try {
var result = await AllowMeBridge.addPerson();
this.setState({ result: result });
} catch (e) {
console.error(e);
}
}
async onStartClick() {
try {
var result = await AllowMeBridge.start();
this.setState({ result: result });
} catch (e) {
console.error(e);
}
}
// AllowMe Biometria Facial
onBiometricsClick() {
AllowMeBridge.showBiometrics()
.then((data: any) => {
this.setState({ result: data });
})
.catch((e: any) => {
console.error(e);
});
}
}
TIP
Em caso dúvidas ou para ter acesso ao código fonte desse exemplo entre em contato com [email protected].
Updated 1 day ago