Atualização Obrigatória / Opcional
Controle de versão mínima do app via Firebase Remote Config, sem depender da API e sem novo deploy. Permite bloquear (hard block) versões antigas demais ou apenas sugerir atualização. O update em si continua sendo feito pela loja via In-App Update (Google Play).
AppUpdateHelper (In-App Update do Play) executa a atualização. Um nunca substitui o outro.
Chaves no Firebase Remote Config
Uma fonte por plataforma — configuradas no console do Firebase, em Remote Config:
| Chave | Exemplo | Significado |
|---|---|---|
min_required_version_android | 1.0.39 | Menor versionName aceito. Abaixo disso → bloqueio total. |
latest_version_android | 1.0.41 | Última versão publicada. Abaixo disso (mas ≥ mínima) → sugestão dispensável. |
update_message | Nova versão disponível… | Mensagem opcional exibida no diálogo. Se vazia, usa string local (R.string.update_*). |
UP_TO_DATE e nunca bloqueia por engano. O fetch retorna false silenciosamente em falha.
Estados de Versão
O RemoteConfigHelper.versionStatus() compara BuildConfig.VERSION_NAME com as chaves remotas (comparação numérica segmento a segmento, ex. 1.0.39):
| Estado | Condição | Comportamento |
|---|---|---|
MANDATORY_UPDATE | versão < min_required_version_android | Hard block. In-App Update IMMEDIATE (tela cheia, sem dispensar). |
OPTIONAL_UPDATE | versão < latest_version_android | Sugestão dispensável, exibida uma vez por sessão. |
UP_TO_DATE | versão ≥ última publicada | Nada a fazer. |
Fluxo em MainActivity.enforceAppUpdate()
Retoma update interrompido
Se um update IMMEDIATE ficou pela metade (app morto durante o download), o AppUpdateHelper retoma antes de qualquer outra checagem.
Fetch do Remote Config
remoteConfigHelper.fetch() — intervalo de 1h em produção (FETCH_INTERVAL_SECONDS = 3600), imediato em debug. Em erro, segue sem bloquear.
Decisão por estado
MANDATORY_UPDATE → startMandatoryUpdate() (In-App Update IMMEDIATE, com fallback para AlertDialog que leva à Play Store). OPTIONAL_UPDATE → promptOptionalUpdate() (diálogo dispensável, "Atualizar" / "Depois"). UP_TO_DATE → segue normalmente.
Cancelamento do update obrigatório
Se o usuário cancela o fluxo IMMEDIATE (resultCode != RESULT_OK em REQUEST_CODE_UPDATE), o app re-aciona enforceAppUpdate() — não há saída sem atualizar.
Comparação de versões
O helper compara versões no formato "1.0.39" numericamente por segmento (compareVersions(a, b)). Segmentos não numéricos viram 0. Isso evita o bug clássico de comparação lexicográfica onde "1.0.9" > "1.0.10".
// MANDATORY se a versão instalada é menor que a mínima
if (minVersion.isNotEmpty() && compareVersions(currentVersion, minVersion) < 0)
return VersionStatus.MANDATORY_UPDATE
min_required_version_ios / latest_version_ios. A obrigatoriedade é decidida da mesma forma; o update aponta para a App Store.