Criar uma aplicação básica para Android
Criar MainActivity.kt
Abrir MainActivity.kt e adicione o seguinte conteúdo. Isso corresponde a uma Activity mínima.
package com.vonage.verify2.test
import android.os.Bundle
import androidx.activity.ComponentActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
Em seguida, defina a constante da URL do backend usando BuildConfig:
private const val BACKEND_URL = BuildConfig.BACKEND_URL
Criação da interface do usuário com o Jetpack Compose
Nesta seção, vamos criar o interface do usuário para nosso fluxo de verificação. Há ainda não há conexão em rede porque o objetivo é criar uma interface de usuário simples que possamos conectar posteriormente aos endpoints do backend.
A nova MainActivity ficará assim:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { VerifyApp() }
}
}
Vamos implementar a função VerifyApp()
@Composable
fun VerifyApp() {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
VerificationScreen()
}
}
}
Nossa interface do usuário possui um pequeno número de “momentos” (telas) que dependem da etapa de verificação atual:
- Digite o número de telefone
- Carregando
- Digite o código do SMS (alternativa)
- Verificado
- Erro
O Jetpack Compose facilita isso se modelarmos a tela como um máquina de estados.
Criar uma máquina de estados de interface do usuário
Definimos uma classe selada para representar todos os estados possíveis da interface do usuário:
private sealed class VerifyUiState {
data object EnterPhone : VerifyUiState()
data object Loading : VerifyUiState()
data class EnterSms(val requestId: String) : VerifyUiState()
data class Verified(val method: String) : VerifyUiState()
data class Error(val message: String) : VerifyUiState()
}
Embora ainda não tenhamos feito a integração com o backend, já incluímos um requestId no estado SMS, pois isso será necessário mais tarde.
Criar a tela e seu estado local da interface do usuário
Interior VerificationScreen() armazenamos as entradas do usuário e o estado atual da interface do usuário com remember { mutableStateOf(...) }:
var phone by remember { mutableStateOf(DEFAULT_PHONE) }
var smsCode by remember { mutableStateOf("") }
var uiState by remember { mutableStateOf<VerifyUiState>(VerifyUiState.EnterPhone) }
var statusMessage by remember { mutableStateOf("") }
Crie o layout com uma coluna simples
Criamos um layout centralizado usando Column, Spacer, e Modifier:
Column(
modifier = Modifier.fillMaxSize().padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) { ... }
Nele, apresentamos:
- Um título
- Entrada por telefone
- Entrada opcional por SMS
- Botões baseados no estado atual da interface do usuário
- Uma mensagem de status na parte inferior
Entrada por telefone
OutlinedTextField(
value = phone,
onValueChange = { phone = it },
enabled = uiState !is VerifyUiState.Loading,
label = { Text("Phone number") },
placeholder = { Text("+34600000000") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone),
modifier = Modifier.fillMaxWidth()
)
Notas:
- Desativamos o preenchimento de campos durante o carregamento para evitar envios duplicados.
- Nós usamos
KeyboardType.Phonepara exibir um teclado otimizado para celular.
Entrada por SMS
A entrada de SMS será implementada com uma renderização condicional. O Compose facilita muito a criação de interfaces de usuário condicionais.
Mostramos a entrada de SMS somente se estivermos em EnterSms:
val requestIdForSms = (uiState as? VerifyUiState.EnterSms)?.requestId
if (requestIdForSms != null) {
OutlinedTextField(
value = smsCode,
onValueChange = { smsCode = it },
enabled = uiState !is VerifyUiState.Loading,
label = { Text("SMS code") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.fillMaxWidth()
)
}
Mais tarde, quando fizermos a integração com o backend, isso requestId virá de /verification.
Exibir o botão de ação correto com base no estado da interface do usuário
Nós usamos when (uiState):
- Carregando → exibir um indicador de carregamento
- EnterPhone / Erro → exibir “Iniciar verificação”
- EnterSms → exibir “Enviar código”
- Verificado → exibir mensagem de sucesso + “Verify outro número”
Este é o padrão básico do Compose utilizado em aplicativos reais: UI = função(estado).
Introdução à autenticação silenciosa
A autenticação silenciosa leva um bom tempo para ser compreendida. Este tutorial mostra como criar uma integração do zero usando Node.js e Kotlin