KasyKasy

Localização em segundo plano

GPS continua publicando a posição do usuário mesmo com o app minimizado. Módulo independente, plugável automaticamente no Drive.

Localização em segundo plano é um módulo independente: capta e publica o GPS do usuário mesmo quando o app está minimizado, algo que o rastreamento normal do kit (usado pelo Drive) não faz sozinho. Funciona com ou sem o Drive no projeto, é nativo apenas (iOS/Android) e não usa nenhuma lib paga, roda em cima do geolocator que já vem no kit.

Rastreamento em background só existe no app nativo. Na web o navegador não mantém GPS rodando com a aba minimizada, isso é limitação do próprio browser, não do kit. A web continua vendo a posição normalmente (Drive já mostra a localização do motorista pra quem acompanha pela web), só não consegue publicar a própria localização em background.

Implementação

Pelo MCP: peça ao assistente "adiciona localização em segundo plano no meu projeto". Ele roda add_feature por você. Veja MCP do Kasy.

  1. Ative o módulo (não vem no modo Rápido por padrão, igual o Drive):

    kasy add background_location        # adiciona
    kasy remove background_location     # remove
    kasy add --list                     # mostra o que está ligado

    O kasy add background_location insere as permissões nativas nos dois lados: ACCESS_BACKGROUND_LOCATION + FOREGROUND_SERVICE_LOCATION no AndroidManifest.xml, e NSLocationAlwaysAndWhenInUseUsageDescription + location no UIBackgroundModes do Info.plist. O template não vem com isso por padrão, é opt-in mesmo, pedir localização "sempre" sem necessidade real derruba a revisão da App Store/Play Store.

  2. Se o projeto já tem Drive, o módulo se conecta sozinho: DriveLocationGateway passa a usar o rastreamento em background automaticamente, sem precisar editar nada. Se você remover o módulo depois, o Drive volta a rastrear só em foreground, sem quebrar.

  3. Sem Drive, o módulo funciona do mesmo jeito, só que ninguém chama ele por padrão. Use BackgroundLocationController (core/background_location/) no seu próprio código: start() pra começar a rastrear, positions pra ouvir o stream, stop() pra parar.

  4. Antes de publicar, revise o texto da tela de aviso (exigência do Google Play: "prominent disclosure", mostrar o motivo antes do pedido nativo de permissão). O texto padrão fica em lib/i18n/*.i18n.json, chave background_location.disclosure_message: ajuste pro seu caso de uso real.

  5. Teste em dispositivo físico, não dá pra confirmar isso em simulador nem na web:

    • Android: flutter run num aparelho ou emulador, conceda "Permitir o tempo todo", minimize o app (sem matar) e confirme que a notificação persistente aparece e a posição continua chegando no backend.
    • iOS: precisa ser aparelho físico (o simulador não segura execução em background de forma confiável). Instale via Xcode com sua conta de desenvolvedor, não precisa de TestFlight só pra testar você mesma.

Informações

Como funciona

O motor é o BackgroundLocationController (core/background_location/background_location_provider.dart), construído em cima do geolocator, a mesma lib que o resto do kit já usa pra localização, só que configurada com AndroidSettings.foregroundNotificationConfig (Android) e AppleSettings.allowBackgroundLocationUpdates (iOS), que são as duas peças que fazem o GPS continuar entregando posição com o app minimizado.

A permissão é pedida em duas etapas, porque os dois sistemas operacionais exigem isso:

  • Android: primeiro pede localização normal (ACCESS_FINE_LOCATION), depois, numa segunda chamada, pede ACCESS_BACKGROUND_LOCATION. O Android não deixa pedir as duas juntas desde a versão 11.
  • iOS: primeiro concede "Ao usar o app", depois o sistema oferece o upgrade pra "Sempre". Só aparece depois de um tempo de uso real, não é imediato.

Integração com o Drive

O ponto de entrada é só um arquivo: features/drive/providers/drive_location_gateway.dart. Quando withBackgroundLocation está ligado, watchPosition() usa o BackgroundLocationController em vez do KasyLocation padrão; quando não está, cai no comportamento de sempre. Nenhuma outra parte do Drive (rota, câmera, ETA, telas) muda, porque tudo isso já consumia a posição por um stream comum, não direto do GPS.

Instalar as duas features numa ordem ou na outra dá no mesmo, o CLI cuida da integração nos dois sentidos.

Hoje só o motorista. Quem chama watchPosition() é o driver_mode_notifier.dart, disparado quando o motorista fica online, é o único fluxo do Drive que precisa de posição contínua (o passageiro acompanha o carro do motorista se movendo no mapa). O passageiro não roda esse motor: a posição dele é capturada uma única vez, no momento do pedido da corrida, e nunca mais atualizada, mesmo com o app em primeiro plano, porque hoje nenhuma tela ou dado do Drive depende de acompanhar o passageiro se movendo. Estender pro passageiro é possível (o motor é genérico, ver Drive), mas só vale a pena com uma feature real por trás (ex: mostrar o passageiro andando até o ponto de encontro), pedir permissão "sempre" sem uso real pesa contra na revisão da loja.

Se a pessoa negar a permissão "sempre"

O app continua funcionando normalmente com localização só em foreground, exatamente como seria sem o módulo instalado. Não tem tela bloqueante nem trava o uso, o rastreamento em background só fica indisponível até a pessoa liberar (Configurações do sistema).

Nos 3 backends

Esse módulo é só do lado do dispositivo, não muda schema nem endpoint em nenhum dos 3 backends (Firebase, Supabase, API). O dado publicado continua o mesmo (lat, lng, status), só passa a chegar mesmo com o app minimizado.

Atualizado em 03/11/2026