Pular para o conteúdo principal

Integração Android

🤖 Integração Android

Este guia mostra como invocar o GuardianKey Mobile SDK na etapa de login do seu próprio app Android — a mesma ligação usada pelo app de exemplo de referência. O SDK é escrito em Kotlin Multiplatform, mas no Android é um AAR/biblioteca normal que você consome a partir de Kotlin ou Java.

Requisitos: minSdk 26+, Kotlin, uma Activity sua para a tela de login. O tier biométrico exige que a Activity de login seja uma FragmentActivity.


1. Adicione a dependência do SDK

O módulo do SDK é :sdk (namespace do artefato io.guardiankey.gkas). Escolha uma:

Opção A — incluir o módulo (monorepo / código‑fonte):

// settings.gradle.kts
include(":sdk")
// app/build.gradle.kts
dependencies {
implementation(project(":sdk"))
}

Opção B — consumir o AAR. Gere‑o e publique no mavenLocal() (ou coloque o .aar em um repositório flat):

./gradlew :sdk:assembleRelease           # gera sdk/build/outputs/aar/sdk-release.aar
# ou, se o SDK estiver configurado para publicar:
./gradlew :sdk:publishToMavenLocal

Como o SDK depende de Ktor, coroutines e AndroidX Biometric, declare essas dependências transitivas no seu app ao consumir um AAR “puro”:

dependencies {
implementation("io.ktor:ktor-client-okhttp:<versão>")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:<versão>")
implementation("androidx.biometric:biometric:<versão>")
}

2. Declare as permissões

Adicione as permissões usadas pelos coletores amplos. Todas são opcionais em runtime — se negadas, o sinal correspondente apenas reporta available:false e o login continua.

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />

Se o seu backend usar http em texto claro durante o desenvolvimento, defina também android:usesCleartextTraffic="true" no <application>.


3. Hospede a tela de login em uma FragmentActivity

O tier de identidade biométrico exibe um BiometricPrompt, que precisa de uma FragmentActivity. Faça sua Activity de login ser uma FragmentActivity e exponha ao SDK a que está em primeiro plano, via um pequeno holder.

// ActivityHolder.kt
object ActivityHolder {
private var ref = java.lang.ref.WeakReference<FragmentActivity>(null)
var current: FragmentActivity?
get() = ref.get()
set(value) { ref = java.lang.ref.WeakReference(value) }
}
class LoginActivity : FragmentActivity() {

override fun onResume() {
super.onResume()
ActivityHolder.current = this
}

override fun onPause() {
super.onPause()
if (ActivityHolder.current === this) ActivityHolder.current = null
}

// 4. Encaminhe eventos de toque ao coletor comportamental (só tempo/geometria).
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (ev != null) GkasTouchTracker.feed(ev)
return super.dispatchTouchEvent(ev)
}
}

4. Encaminhe eventos de toque (sinal comportamental)

O SDK não consegue observar toques globalmente, então o app encaminha os eventos brutos para GkasTouchTracker.feed(...) — tipicamente a partir de Activity.dispatchTouchEvent, como acima. O tracker guarda apenas características comportamentais dos toques e nunca captura o conteúdo digitado. Isso alimenta o sinal comportamental do SDK. Se você pular este passo, esse sinal apenas fica vazio e o login continua funcionando.


5. Solicite permissões em runtime (best‑effort)

Peça as permissões perigosas antes/na tela de login. Não bloqueie o login pelo resultado — permissões negadas apenas degradam os sinais correspondentes.

private val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { /* best-effort */ }

private fun requestCollectorPermissions() {
val perms = mutableListOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
perms += Manifest.permission.BLUETOOTH_CONNECT
perms += Manifest.permission.BLUETOOTH_SCAN
}
permissionLauncher.launch(perms.toTypedArray())
}

6. Crie a instância do SDK

Construa um GuardianKeyGkas com a URL base do seu backend e um PlatformContext. O activityProvider permite ao tier biométrico encontrar a activity em primeiro plano.

import io.guardiankey.gkas.GkasSdkConfig
import io.guardiankey.gkas.GuardianKeyGkas
import io.guardiankey.gkas.PlatformContext

val gkas = GuardianKeyGkas.create(
config = GkasSdkConfig(
backendBaseUrl = "https://seu-backend.exemplo.com/api", // sem barra no final
httpTimeoutMs = 8000,
debug = BuildConfig.DEBUG,
),
platform = PlatformContext(
context = applicationContext,
activityProvider = { ActivityHolder.current },
),
)

Para o emulador Android alcançar um backend na máquina host, use http://10.0.2.2:8080.


7. Conduza o login

Chame os três passos em ordem dentro de uma coroutine (ex.: em um ViewModel). Mapeie o LoginResult para a sua navegação.

import io.guardiankey.gkas.LoginRequest
import io.guardiankey.gkas.LoginResult

fun login(username: String, password: String) = viewModelScope.launch {
try {
val config = gkas.fetchConfig() // 1) GET /config
val solution = gkas.buildSolution(config, username) // 2) coleta + assina
val result = gkas.login( // 3) POST /login
LoginRequest(
username = username,
password = password,
gkasSolution = solution,
config = config,
)
)

when (result) {
is LoginResult.Allowed -> goToHome()
is LoginResult.Blocked -> showBlocked(result.reason) // permanece no login
is LoginResult.Error -> showError(result.message)
}
} catch (e: Throwable) {
showError("Falha de comunicação: ${e.message}")
}
}

Essa é a integração inteira: fetchConfig → buildSolution → login, e então reagir a Allowed / Blocked / Error.


✅ Checklist

  • Dependência do SDK adicionada (módulo :sdk ou AAR + deps transitivas).
  • Permissões no manifest; solicitação em runtime ligada (best‑effort).
  • Activity de login é uma FragmentActivity; activity em foco exposta via holder.
  • dispatchTouchEvent encaminha para GkasTouchTracker.feed(...).
  • GuardianKeyGkas.create(...) construído com URL do backend + PlatformContext.
  • Login chama fetchConfig → buildSolution → login e trata a decisão.

Veja a referência de API para a API pública completa e o contrato /config e /login do backend.