> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/docs.facephi-pt-br/sdks/sdk-mobile/android-sdk/ajustes-avanzados.md).

# Configurações avançadas

## Introdução <a href="#id-1-introduccion" id="id-1-introduccion"></a>

Nesta seção, amplia-se a informação geral sobre o lançamento do SDK.

***

## Informações avançadas do lançamento do SDK <a href="#id-2-informacion-avanzada-del-lanzamiento-del-sdk" id="id-2-informacion-avanzada-del-lanzamiento-del-sdk"></a>

Nesta seção, será ampliada a informação da seção "Lançamento simplificado do SDK".

### Adicionar repositório privado <a href="#id-21-anadir-repositorio-privado" id="id-21-anadir-repositorio-privado"></a>

Por questões de segurança e manutenção, os novos componentes da ***SDKMobile*** são armazenados em repositórios privados que exigem credenciais específicas para acessá-los. Essas credenciais deverão ser obtidas por meio da *equipe de suporte* de **Facephi**.

Uma vez obtidas as credenciais, deverá ser incluído o seguinte trecho de código para configurar o repositório Maven no **Gradle** do seu projeto, ou no arquivo **settings.gradle** do mesmo. Recomenda-se incluí-lo após *mavenCentral()*

```kotlin
maven {
    Properties props = new Properties()
    def propsFile = new File('local.properties')
    if(propsFile.exists()){
        props.load(new FileInputStream(propsFile))
    }
    name="external"
    url = uri("https://facephicorp.jfrog.io/artifactory/maven-pro-fphi")
    credentials {
        username = props["artifactory.user"] ?: System.getenv("USERNAME_ARTIFACTORY")
        password = props["artifactory.token"] ?: System.getenv("TOKEN_ARTIFACTORY")
    }
}
```

Para que o projeto recupere corretamente as dependências, as credenciais (Usuário e Token) deverão estar configuradas corretamente

Há várias formas de configurar as credenciais de acesso ao repositório:

* Como variáveis de ambiente com o seguinte nome. Por exemplo:

  ```
  export USERNAME_ARTIFACTORY=YOUR_CREDENTIALS_USERNAME
  export TOKEN_ARTIFACTORY=YOUR_CREDENTIALS_TOKEN
  ```

  **Se as dependências não forem reconhecidas ao sincronizar**, elas devem ser incluídas por meio de variáveis de ambiente no arquivo:

`~/.zshrc`

* Incluídos no arquivo *local.properties* com a seguinte estrutura:

  ```
  artifactory.user=YOUR_CREDENTIALS_USERNAME
  artifactory.token=YOUR_CREDENTIALS_TOKEN
  ```

### Inicialização do SDK <a href="#id-22-inicializacion-del-sdk" id="id-22-inicializacion-del-sdk"></a>

**Deve-se evitar inicializar um controlador que não será usado**.

O SDK funciona por meio de um controlador principal (SDKController) que deve ser inicializado corretamente para que se possa usar o restante da funcionalidade. Os passos a seguir na inicialização são:

1. Incluir o objeto Application por meio da classe SdkApplication.
2. Decidir se a licença será incluída por meio de um *String* ou com um *serviço de licenciamento remoto* (consultar **seção 3.1**).
3. O controlador *TrackingController* caso se queira conectar com a plataforma.

O **ponto 3** é opcional e exigiria o uso do componente de Tracking (mais informações sobre este módulo em sua própria documentação).

Um exemplo de inicialização sem *TrackingController* seria o seguinte:

```kotlin
val sdkConfig = SdkConfigurationData(
    sdkApplication = SdkApplication(application),
    licensing = LicensingOffline("LICENSE")
)

val result = SDKController.initSdk(sdkConfig)

when (result) {
  is SdkResult.Success -> Napier.d("APP: INIT SDK: OK")
  is SdkResult.Error -> Napier.d(
          "APP: INIT SDK: KO - ${result.error.name}"
        )
}
```

Um exemplo de inicialização com *TrackingController* seria o seguinte:

```kotlin
val sdkConfig = SdkConfigurationData(
    sdkApplication = SdkApplication(application),
    licensing = LicensingOffline("LICENSE"),
    trackingController = TrackingController(),
)

val result = SDKController.initSdk(sdkConfig)

when (result) {
  is SdkResult.Success -> Napier.d("APP: INIT SDK: OK")
  is SdkResult.Error -> Napier.d(
          "APP: INIT SDK: KO - ${result.error.name}"
        )
}
```

#### **Injeção de licenças**

Como mencionado anteriormente, atualmente existem duas formas de injetar a licença:

**a. Obtendo a licença por meio de um serviço**

Por meio de um serviço que simplesmente exigirá uma URL e um API-KEY como identificador. Isso evitaria problemas ao manipular a licença, assim como a constante substituição dessas licenças quando surgisse algum problema com ela (malformação ou modificação indevida, expiração da licença...)

Exemplo de implementação em Kotlin:

```kotlin
val sdkConfig = SdkConfigurationData(
    sdkApplication = SdkApplication(application),
    licensing = LicensingOnline(EnvironmentLicensingData(
            apiKey = "...")
      )),
)

val result = SDKController.initSdk(sdkConfig)

when (result) {
  is SdkResult.Success -> Napier.d("APP: INIT SDK: OK")
  is SdkResult.Error -> Napier.d(
          "APP: INIT SDK: KO - ${result.error.name}"
        )
}
```

Exemplo de implementação em Java:

```kotlin
SDKController.INSTANCE.initSdk(
    new SdkApplication(activity.getApplication()),
    new LicensingOnline(new EnvironmentLicensingData(
      apiKey = "...")),
    sdkResult ->
    {
      if (sdkResult instanceof SdkResult.Success) {
        Napier.d("APP: INIT SDK: OK")
      } else if (sdkResult instanceof SdkResult.Error) {
        Napier.d("APP: INIT SDK: KO - ${it.error}")
      }
    }
  );
```

**b. Injetando a licença como String**

A licença pode ser atribuída diretamente como uma String, da seguinte maneira:

Exemplo de implementação em Kotlin:

```kotlin
val sdkConfig = SdkConfigurationData(
    sdkApplication = SdkApplication(application),
    licensing = LicensingOffline("LICENSE"),
)

val result = SDKController.initSdk(sdkConfig)

when (result) {
  is SdkResult.Success -> Napier.d("APP: INIT SDK: OK")
  is SdkResult.Error -> Napier.d(
          "APP: INIT SDK: KO - ${result.error.name}"
        )
}
```

Exemplo de implementação em Java:

```kotlin
SDKController.INSTANCE.initSdk(
  new SdkApplication(activity.getApplication()),
  new LicensingOffline("LICENSE"),
  sdkResult ->
  {
    if (sdkResult instanceof SdkResult.Success) {
      Timber.d("APP: INIT SDK: OK")
    } else if (sdkResult instanceof SdkResult.Error) {
      Timber.d("APP: INIT SDK: KO - ${it.error}")
    }
  }
);
```

#### **Recebimento de erros**

Na parte do erro, teremos a classe SdkError.

Lista de erros:

* EMPTY\_LICENSE: Licença vazia
* INIT\_AI\_MODELS(error: String): Erro obtido no serviço de download de modelos
* INIT\_FLOW (error: String): Erro obtido no serviço de download de flow
* LICENSE\_CHECKER\_ERROR (error: String): Erro obtido ao verificar se a licença está correta
* LICENSING\_ERROR (error: String): Erro obtido no serviço de download de licenças
* NETWORK\_CONNECTION\_ERROR: Erro de conexão com a internet
* TRACKING\_ERROR (error: String): Erro obtido ao iniciar o controlador de Tracking

***

## Iniciar nova operação <a href="#id-3-iniciar-nueva-operacion" id="id-3-iniciar-nueva-operacion"></a>

Sempre que se desejar iniciar o fluxo de uma nova operação (exemplos de operações seriam: *Onboarding, Authentication, VideoCall*,...) é essencial indicar ao **SDKController** que ela vai começar, e assim o SDK saberá que as próximas chamadas de **Componentes** (também chamados **Steps**) farão parte dessa operação.

Ao iniciar um processo ou fluxo, **sempre** deverá ser realizada a chamada ao método **newOperation**

Este método tem os seguintes parâmetros de entrada:

1. **operationType**: Indica se será feito um processo de ONBOARDING ou de AUTHENTICATION.
2. **customerId**: ID único do usuário, se houver (controlado no nível da aplicação)
   1. Este parâmetro aparecerá refletido para cada operação na plataforma.
3. **steps**: Lista de passos da operação, se tiverem sido definidos previamente
4. **enableTracking**: Permite ativar ou desativar o envio de eventos de Tracking para esta operação. Se não for informado, considera-se `true`.

Há 2 maneiras de realizar este início de operação, dependendo de se **são conhecidos os passos** que formarão o fluxo do processo de registro ou autenticação (caso os componentes sejam executados de forma sequencial e sempre da mesma maneira) ou, em caso contrário, de que o fluxo **não esteja definido** e seja desconhecido (por exemplo, o cliente final é quem decide a ordem de execução dos componentes).

* Fluxo **conhecido** (a operação aparecerá *rastreada* na plataforma com todos os passos da lista).

  Exemplo de implementação Kotlin:

```kotlin
val result = SDKController.newOperation(
        operationType = OperationType.ONBOARDING,
        customerId = "customer_id",
        steps = listOf(Step.SELPHI_COMPONENT, Step.SELPHID_COMPONENT),
        enableTracking = true)
when (result) {
    is SdkResult.Success -> {
        Timber.d("APP: NEW OPERATION OK")
        Timber.d("Session ID: ${result.data.sessionId}")
        Timber.d("Operation ID: ${result.data.operationId}")
    }
    is SdkResult.Error -> {
        Timber.d("APP: NEW OPERATION ERROR: ${result.error.name}")
    }
}
```

Exemplo de implementação Java:

```kotlin
 SDKController.INSTANCE.newOperation(
        OperationType.ONBOARDING,
        "customer_id",
        [Step.SELPHI_COMPONENT, Step.SELPHID_COMPONENT]
        ){
          if (sdkResult instanceof SdkResult.Success) {
            Napier.d("APP: NEW OPERATION: OK")
          } else if (sdkResult instanceof SdkResult.Error) {
            Napier.d("APP: NEW OPERATION: KO - ${it.error}")
          }
        }
  );
```

* Fluxo **desconhecido** (a operação aparecerá *rastreada* na plataforma com reticências). Exemplo de implementação Kotlin:

```kotlin
val result = SDKController.newOperation(
        operationType = OperationType.ONBOARDING,
        customerId = "customer_id",
        enableTracking = true)
when (result) {
    is SdkResult.Success -> {
        Timber.d("APP: NEW OPERATION OK")
    }
    is SdkResult.Error -> {
        Timber.d("APP: NEW OPERATION ERROR: ${result.error.name}")
    }
}
```

Exemplo de implementação Java:

```kotlin
 SDKController.INSTANCE.newOperation(
        OperationType.ONBOARDING,
        "customer_id"
        ){
          if (sdkResult instanceof SdkResult.Success) {
            Napier.d("APP: NEW OPERATION: OK")
          } else if (sdkResult instanceof SdkResult.Error) {
            Napier.d("APP: NEW OPERATION: KO - ${it.error}")
          }
        }
  );
```

`sdkResult` → Contém em `data` as informações da operação criada.

Quando o resultado é correto, `data` é um `OperationResult` com:

| Campo         | Descrição                                                     |
| ------------- | ------------------------------------------------------------- |
| `sessionId`   | Identificador da sessão criada ou recuperada pelo SDK.        |
| `operationId` | Identificador da operação ativa.                              |
| `type`        | Tipo de operação iniciado (`ONBOARDING` ou `AUTHENTICATION`). |
| `customerId`  | Identificador do usuário associado à operação.                |

**Uma vez criada a operação** os componentes do SDK associados a esta operação poderão ser executados. Consulte a documentação específica de cada componente para saber como fazer isso.

### **Tipos de operação existentes** <a href="#id-31-tipos-de-operacion-existentes" id="id-31-tipos-de-operacion-existentes"></a>

Atualmente, existem as seguintes operações, durante as quais são usados determinados **Componentes (STEPS).**

A seguir, é apresentada uma tabela com a relação entre *operações* e *steps*:

| **Operação (OperationType)** | **Componente (Step)**                 | Descrição                                                                                                                 |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| ONBOARDING                   | SELPHI\_COMPONENT\nSELPHID\_COMPONENT | - Validação facial de uma selfie contra o rosto de um documento\n- Extração do OCR do documento\n- Detecção de vivacidade |
| AUTHENTICATION               | SELPHI\_COMPONENT                     | - Validação facial por meio de templates\n- Detecção de vivacidade                                                        |

Esta lista será ampliada em próximas atualizações do SDK, à medida que novos componentes e casos de uso forem surgindo.

{% hint style="info" %}
Se a criação de uma nova operação devolver um erro do tipo **INTERNAL\_ERROR** isso se deve principalmente a um problema de **segurança**. Para investigar a causa, é possível recuperar o Token associado ao erro, o qual fornece informações adicionais para sua análise.

```
if (result.error is SdkError.INTERNAL_ERROR){
    val token = (result.error as SdkError.INTERNAL_ERROR).error
}
```

{% endhint %}

***

## Segurança <a href="#id-24-lanzamiento-de-los-componentes" id="id-24-lanzamiento-de-los-componentes"></a>

O SDK de Android incorpora um sistema de segurança destinado a detectar e bloquear ambientes potencialmente pouco confiáveis ou que possam indicar tentativas de ataque.<br>

Este mecanismo está habilitado por padrão, permite identificar situações que poderiam comprometer a segurança e evita a execução do SDK em contextos que não são considerados seguros:

```
SDKController.securityMode(enable: Boolean) 
```

***

## Lançamento de componentes <a href="#id-4-lanzamiento-de-componentes" id="id-4-lanzamiento-de-componentes"></a>

A funcionalidade do SDK é dividida em diferentes componentes com controladores específicos. Esses controladores serão “lançados” a partir do controlador geral.

Uma vez criada a **nova operação** (**seção 3**), poderão ser lançados os diferentes controladores do SDK. Para consultar essas informações, deverá-se acessar a **documentação de cada um dos componentes específicos**.

Exemplo de lançamento em Kotlin:

```kotlin
val result = SDKController.launch(ExampleController(ConfigurationData()))
when (result) {
    is SdkResult.Success -> {
        //Result OK
        result.data
    }
    is SdkResult.Error -> {
        //Result KO
        result.error.name
    }
}
```

Exemplo de lançamento em Java:

```kotlin
SDKController.INSTANCE.launch(
    new ExampleController(new ConfigurationData()) {
        if (sdkResult instanceof SdkResult.Success) {
            //Result OK
            it.data
          } else if (sdkResult instanceof SdkResult.Error) {
            //Result KO
            it.error.name
          }
    }
)
```

### Opções para o lançamento do componente <a href="#id-41-opciones-para-el-lanzamiento-del-componente" id="id-41-opciones-para-el-lanzamiento-del-componente"></a>

Uma vez iniciado o SDK e criada uma nova operação, o componente poderá ser lançado. Há duas formas de lançá-lo:

* **\[COM Tracking]** Esta chamada permite lançar a funcionalidade do componente normalmente, mas os eventos internos serão enviados ao servidor de *tracking*:

```
val response = SDKController.launch(
    ExampleController(SConfigurationData(...))
)
when (response) {
    is SdkResult.Error -> Napier.d("ERROR - ${response.error.name}")
    is SdkResult.Success -> response.data
}
```

* **\[SEM Tracking]** Esta chamada permite lançar a funcionalidade do componente normalmente, mas **nenhum evento será enviado** ao servidor de *tracking*:

```
val response = SDKController.launchMethod(
    ExampleController(ConfigurationData(...))
)
when (response) {
    is SdkResult.Error -> Napier.d("ERROR - ${response.error.name}")
    is SdkResult.Success -> response.data
}
```

O método **launch** deve ser usado **por padrão**. Este método permite utilizar ***tracking*** caso o componente esteja ativado, e não o usará quando estiver desativado (ou quando o componente não estiver instalado).

Por outro lado, o método **launchMethod** cobre um caso especial, no qual o integrador tem o Tracking instalado e ativado, mas em um Fluxo determinado dentro da aplicação não deseja rastrear informações. Nesse caso, usa-se este método para evitar que essas informações sejam enviadas à plataforma.

***

## Retorno do resultado <a href="#id-5-retorno-de-resultado" id="id-5-retorno-de-resultado"></a>

O resultado de cada componente será retornado por meio do SDK, mantendo sempre a mesma estrutura por meio da classe ***SdkResult*** cuja classe é uma Sealed Class que pode ter 2 estados possíveis:

* SdkResult.Success: Indica que a operação foi finalizada corretamente e contém internamente:
  * ***data:*** Contém o tipo de dado necessário de acordo com o processo/componente lançado.
* SdkResult.Error
  * ***error:*** Contém o tipo de erro necessário de acordo com o processo/componente lançado.

Na documentação de cada componente específico, serão detalhados os diferentes campos que este objeto pode retornar

Exemplo de uso:

```kotlin
when (result) {
    is SdkResult.Success -> {
        Napier.d("Selphi: OK")
        // SelphiResult:
        // result.data.bestImage
    }

    is SdkResult.Error -> Napier.d("Selphi: KO - ${result.error.name}")
}
```

***

## Controladores auxiliares <a href="#id-6-controladores-auxiliares" id="id-6-controladores-auxiliares"></a>

Nesta seção, incluem-se outros controladores e operações auxiliares, alguns deles opcionais, e que podem ser necessários para a correta finalização do Fluxo.

Esses campos são necessários para a comunicação com o serviço de **Facephi**, caso se queira realizar qualquer **verificação** e desejar realizar o *tracking* de uma operação determinada.

### Obtenção do OperationId <a href="#id-61-obtencion-del-operationid" id="id-61-obtencion-del-operationid"></a>

```
val result = SDKController.launch(GetOperationIdController())
Napier.d("Operation ID ${result}")
```

### Obtenção do OperationType <a href="#id-62-obtencion-del-operationtype" id="id-62-obtencion-del-operationtype"></a>

```
val result = SDKController.launch(GetOperationTypeController())
Napier.d("Operation type ${result}")
```

### Obtenção do SessionId <a href="#id-63-obtencion-del-sessionid" id="id-63-obtencion-del-sessionid"></a>

```
val result = SDKController.launch(GetSessionIdController())
Napier.d("Session ID ${result}")
```

### Obtenção do CustomerID <a href="#id-64-obtencion-del-customerid" id="id-64-obtencion-del-customerid"></a>

```
val result = SDKController.launch(GetCustomerIdController())
Napier.d("Customer ID ${result}")
```

### Atribuição do CustomerID <a href="#id-65-asignacion-del-customerid" id="id-65-asignacion-del-customerid"></a>

```
SDKController.launch(CustomerIdController("CustomerId"))
```

***

## Opções de depuração e controle de erros <a href="#id-7-opciones-de-depuracion-y-control-de-errores" id="id-7-opciones-de-depuracion-y-control-de-errores"></a>

Há certas opções no SDK que permitem um aumento nos logs de depuração para verificar se tudo funciona corretamente.

### Controle de erros nas conexões de Tracking com a plataforma <a href="#id-71-control-de-errores-en-las-conexiones-de-tracking-con-la-plataforma" id="id-71-control-de-errores-en-las-conexiones-de-tracking-con-la-plataforma"></a>

Uma vez que o SDK tenha sido iniciado corretamente, podem ser aplicados certos ajustes para obter mais informações sobre possíveis erros em Tracking; é possível fazer um acompanhamento por meio deste lançamento de controlador:

```kotlin
SDKController.launch(TrackingErrorController {
    Napier.d("Tracking Error: ${it.name}")
})
```

### Ativação de logs gerais de depuração <a href="#id-72-activacion-de-logs-de-depuracion-general" id="id-72-activacion-de-logs-de-depuracion-general"></a>

```kotlin
 if (BuildConfig.DEBUG) {
  SDKController.enableDebugMode()
 }
```

***

## Acompanhamento e análise de eventos na aplicação <a href="#id-8-seguimiento-y-analisis-de-eventos-en-la-aplicacion" id="id-8-seguimiento-y-analisis-de-eventos-en-la-aplicacion"></a>

A funcionalidade de eventos permite registrar e interpretar interações-chave dentro da aplicação, como mudanças de tela e ações do usuário, facilitando a análise do comportamento em tempo real.

Cada evento é enviado com um carimbo de data e hora, tipo e detalhe específico, proporcionando um acompanhamento estruturado e otimizando a experiência do usuário com dados precisos e acionáveis.

```kotlin
 SDKController.getAnalyticsEvents { time, componentName, eventType, info ->
            Log.i { "EVENTS", "*** $time - ${componentName.name} -" +
                " ${eventType.name} -  ${info ?: \"\"} " }
        }
```
