Recentemente, apertei novamente. Eu moro na Europa, e aqui, em vez de multas por estacionamento inadequado e caminhões de reboque "prensadores", eles amarram a roda do seu carro. Para sair, você precisa fazer uma ligação, pagar uma quantia redonda e esperar o cara com as chaves levantar a corrente. É longo, humilhante e às vezes (dependendo da área) caro predatório.
Naquele dia eu estava atrasado em todos os lugares. Esperando o trabalhador tocar com as chaves, me perguntei o quão estupidamente fiquei. Corri, deixei o carro por meia hora, em vez dos 20 minutos grátis máximos - exatamente no 21º minuto e fui pego. Infelizmente, a van listrada do estacionamento não estava longe e eles reagiram instantaneamente. Eles costumavam me pegar antes, por várias razões: eu esqueci, o prazo pago expirou e, às vezes, simplesmente não conseguia encontrar meu carro no labirinto de ruas.
"Deve haver um aplicativo para tudo", pensei, e comecei a me aprofundar na loja de aplicativos. Depois de um monte de resultados duvidosos, minha confiança diminuiu e decidi esclarecer: "deve haver um aplicativo Android para tudo". Então ele encontrou seu huavei e subiu nas entranhas da loja de brinquedos. A partir daí, mais detritos se derramaram sobre mim e, afogando-me em artesanato desajeitado, cuspi. Ou estou parecendo errado, ou não há um rastreador de estacionamento conveniente e compreensível. A conclusão é simples: se não temos algo, vamos fazer isso sozinhos.
No contexto, eu já estava vendo uma
construção de longo prazo , tirando quase todo o meu tempo livre. Eu decidi fazer uma pausa e no intervalo para coletar outra projeção. Tendo estimado a funcionalidade desejada, imaginei um período de um mês e meio e, olhando para o futuro, direi que, em princípio, ficou ainda mais rápido. O resultado foi uma
aplicação compacta e limpa nas duas plataformas, muito conveniente. Agora eu mesmo uso e sugiro que você experimente.

Idéia
Então, o que eu gostaria de um rastreador de estacionamento? Do que sempre sinto falta quando recebo uma multa? Depois de pensar, formulei o seguinte introdutório:
- Simples. Idealmente, um botão. Um mínimo de funções perturbadoras: sem perfis, histórico de estacionamento, suporte para vários carros ao mesmo tempo, etc.
- Com notificações. Eu não esqueceria o carro, se o aplicativo me lembrasse: mano, você tem um estacionamento ali por sinal, e ele está prestes a expirar.
- Considere o tempo de caminhada. Este é o pensamento mais simples que eu não vi incorporado em lugar algum. Não preciso saber que o estacionamento expirará em 5 minutos se estiver a meia hora dele. Preciso ser lembrado para que eu possa chegar ao carro alguns minutos antes do final e sair.
- Rota e navegação para o estacionamento. Navegação, é claro, pelo Google ou Apple Maps, mas a rota pode ser mostrada no seu aplicativo. Isso ajudará se você deixar o carro em uma área desconhecida, o timer marcar e você andar em círculos pelas mesmas ruas.
Eu escolhi o Flutter como base tecnológica, pois trabalho com ele há algum tempo e o considero bom. Para rotas, decidi usar a API HERE, também não pela primeira vez, mas para o mapa - Mapbox. Esbocei várias opções para a interface, escolhi a mais minimalista e me envolvi no trabalho.
Desenvolvimento
Em princípio, não há muito a dizer sobre o próprio processo de desenvolvimento. Não há parte do servidor aqui, o cliente mais simples, que consiste basicamente de uma visão ampla em diferentes estados. Na primeira página, você seleciona uma predefinição - 1, 2, 4, 6 horas - ou usa o controle deslizante para ajustar o período de estacionamento. Depois de experimentar ao vivo, percebi que o controle deslizante era rude o suficiente e adicionei os botões "+" e "-" a ele. Uma nuance engraçada e bastante óbvia aqui foi que, enquanto você escolhe, o tempo passa. Portanto, você precisa atualizar essa visualização em tempo real. Depois de escolher o termo, clique no único botão abaixo e os dados de localização e hora são salvos e o estacionamento é iniciado. É importante notar que eu basicamente armazeno todos os dados a bordo, nada é transferido para nenhum servidor. No futuro, isso, a propósito, criará dificuldades para mim, mas mais sobre isso mais tarde.
A segunda página é, de fato, o cronômetro de estacionamento. Tentei várias opções aqui: comecei com protótipos de informações extremamente sobrecarregados, depois me livrei e simplifiquei até o limite. Eu realmente queria que o status do estacionamento fosse exibido visualmente, em vez de números secos, então o elemento principal desta página, juntamente com o mapa, era um gráfico de rosca. Mostra o tempo decorrido, o tempo de caminhada e o tempo restante. Se você não estiver perto do carro e o tempo de caminhada não for zero, um botão de navegação será exibido e o mapa mostrará uma rota aproximada para o estacionamento. Isso, de fato, é tudo.
Apesar da simplicidade visual, essa tela praticamente irritou meus nervos. Deve-se entender que, enquanto o estacionamento está ativo, vários processos ocorrem simultaneamente:
- o tempo passa e o temporizador acaba
- você se move e muda o tempo de viagem
Tudo isso acontece em tempo real e deve ser exibido instantaneamente na interface. O gráfico deve ser reconstruído sem problemas, o mapa deve se mover e redesenhar a rota; se houver o risco de chegar atrasado ou o estacionamento expirar, o aviso correspondente também deverá aparecer. Além disso: quando você fecha e abre o aplicativo, você precisa restaurar tudo isso corretamente. E, finalmente, o assustador: toda a funcionalidade deve poder funcionar em segundo plano, porque o aplicativo passará a maior parte de sua vida em segundo plano. Essas coisas.
Não vou descrever a implementação em detalhes, só posso dizer que o trabalho de vibração com os estados é muito digno. Onde, em um andróide puro, um design orientado a objetos sobrecarregado acabaria, ele era simples e elegante. Estados compreensíveis normais, ligação sensata de visualizações a modelos - em tarefas como essa vibração brilha. No entanto, não foi sem batentes típicos: por exemplo, a biblioteca local de trabalhar com mapas não possui uma transição animada para novas coordenadas. Eu tive que entrar no código dela, usar alguns métodos particulares e adicionar minha muleta. É possível que essa funcionalidade seja adicionada em breve, mas essa é a vibração completa - com toda a sua atratividade, esteja preparado para essas descobertas.
Tudo o resto parecia funcionar sem problemas. Na verdade, não havia muito mais: alguns diálogos e uma página de introdução para a qual minha namorada (ela era
artista ) desenhou boas animações. Por fim, traduzi o aplicativo inteiro para o russo, incluindo o mapa. Mas então a dor começou: notificações.
Notificações
Para mim, a capacidade de enviar notificações inteligentes foi essencial para o aplicativo - sem ele, não há nada para se preocupar. No entanto, quando comecei a trabalhar nesse recurso, percebi que havia pisado no meu próprio pé. Na verdade, havia dois problemas. O primeiro é o flutter, que não sabe como trabalhar com dispositivos API de baixo nível fora da caixa: você precisa escrever uma junta na forma de um plug-in que contenha dois códigos nativos e uma abstração no dardo. O segundo problema é minha posição fundamental de que tudo deve ser realizado a bordo. Então, resumimos o que é necessário. É necessário que o aplicativo
em segundo plano :
- Monitorando constantemente sua geolocalização,
- Verificou quantos minutos a pé do estacionamento
- Verificado com o tempo de expiração
- Se houver o risco de não ter tempo para retornar, uma notificação
Sinta a escala da tragédia? É claro que não há capacidade técnica para fazer isso se o aplicativo for completamente eliminado. Mas suponha que seja simplesmente minimizado e a tela esteja desligada. AQUI, a API fornece o caminho e a estimativa do tempo de caminhada. Isso significa que o aplicativo enviará solicitações de spam em segundo plano? Quanto código será executado? Como estamos com o consumo de memória e energia?
Sentei-me para pensar. Começando com um pequeno: tecnicamente, o flutter teve recentemente a capacidade de executar código em segundo plano, chamado de isolate. Se tudo estiver escrito corretamente, você poderá construir a lógica de uma maneira específica para que nem tudo seja executado em segundo plano, mas algumas funcionalidades específicas. De fato, no modo minimizado, não precisamos desenhar interfaces ou atualizar estados - estamos interessados na lógica simples de calcular o tempo, e essa lógica é bastante compacta e barata. Ao mesmo tempo, não deve ser acionado por uma alteração na geolocalização, como eu fiz na versão original, mas por um temporizador interno. Porque a notificação deve voar, mesmo que você não se mova, mas fique quieto.
Bem, escrevemos um código leve que pode ser executado em segundo plano e controlado por um timer. Como podemos acioná-lo dentro da estrutura de aplicativos nativos e transmitir dados de geolocalização para lá? Acabou diferente.
A lógica do Android e do iPhone em questões de execução de código em segundo plano é radicalmente diferente. Para um iPhone, ele está ausente como tal: o código de plano de fundo só pode acionar um evento do sistema de um determinado tipo, por exemplo, reproduzindo streaming de áudio ou, felizmente para mim, atualizando o local. Para fazer isso, basta solicitar permissões e, na parte nativa do plug-in Flater, assine o evento. A partir daí, através de um canal de comunicação específico (MethodChannel), chamamos o retorno de chamada em um dardo, passamos os geodados para ele e iniciamos o plano de fundo com a lógica de que precisamos. Beleza
O Android funciona de maneira diferente. Tecnicamente, ele tem a capacidade de executar código em segundo plano sem estar vinculado a eventos do sistema - para isso, é necessário descrever o serviço. Ele fica pendurado separadamente do aplicativo, seja completamente em segundo plano ou no plano de fundo falso (lá se faz sentir por uma mensagem anexada às cegas). Parece que o problema foi resolvido: na parte nativa do plug-in, descrevemos um serviço em segundo plano que rastreia a localização e extrai o código Darth. No entanto, há uma nuance. A partir da versão 8.0 do Android, a atitude em relação a esses serviços mudou: agora, se o aplicativo é minimizado no momento, seus serviços em segundo plano são infernalmente cortados pelo eixo para economizar energia. E, se o seu código executa, por exemplo, backup de dados, basicamente você não se importa em que momento exato o eixo o deixará funcionar - o principal é que ele funciona. Mas, no meu caso, precisamos rastrear a mudança de local quase em tempo real, e o tempo é crítico aqui. Portanto, a única saída é iniciar o serviço com perdão. Descrevemos uma pequena notificação anexada na cortina, assinamos o local, enviamos para o dardo através do MethodChannel. Tudo parece funcionar.
A propósito, voltando aos problemas de memória, consumo de energia e número de solicitações - o código é executado quando o local é deslocado para 50 metros ou por temporizador. Além disso, ele próprio é muito leve, e os pedidos não passam por mim, mas vão diretamente para a API do HERE. Eu próprio não recebo nenhum dado e não o salvo em nenhum lugar. Em geral, essa implementação é muito bem descrita
aqui , este é o blog de um dos engenheiros do flutter - o código também está anexado lá. Seu exemplo é um pouco diferente, mas a abordagem geral é clara, então eu recomendo a leitura.
Resultado
Isso, de fato, é tudo. Por um mês de tempo livre, recebi um aplicativo que resolve perfeitamente um problema específico. Espero que este artigo seja interessante para alguém, e o aplicativo o poupe de multas e estresse. Você pode procurar e repreender aqui:
Android ,
iOS .
Obrigado a todos pela atenção.