Récemment, j'ai encore serré. J'habite en Europe, et ici, au lieu d'amendes pour mauvais stationnement et de remorqueurs «clamper», ils enchaînent la roue de votre voiture. Pour sortir, vous devez téléphoner, payer une somme ronde et attendre que le gars avec les clés lève la chaîne. Il est long, humiliant et parfois (selon la région) prédateur cher.
Ce jour-là, j'étais en retard partout. En attendant que le travailleur sonne avec les clés, je me suis demandé à quel point j'étais stupide. J'ai couru, j'ai laissé la voiture pendant une demi-heure au lieu du maximum de 20 minutes gratuites - exactement à la 21e minute et je me suis fait prendre. Malchanceux, la camionnette rayée du parking n'était pas loin et ils ont immédiatement réagi. Ils m'attrapaient avant, pour diverses raisons: j'ai oublié, le terme payé expirait, et parfois je n'arrivais pas à trouver ma voiture dans le dédale des rues.
«Il doit y avoir une application pour tout», ai-je pensé, et j'ai commencé à me plonger dans l'App Store. Après un tas de résultats douteux, ma confiance a diminué et j'ai décidé de clarifier: "il doit y avoir une application Android pour tout." Puis il a trouvé son huavei et est monté dans les entrailles du magasin de jeux. À partir de là, plus de débris se sont répandus sur moi et, noyé dans un artisanat maladroit, j'ai craché. Soit je me trompe, soit il n'y a pas de système de suivi de stationnement pratique et compréhensible. La conclusion est simple: si nous n’avons pas quelque chose, faisons-le nous-mêmes.
Dans ce contexte, je voyais déjà une
construction à long terme , ce qui me prenait presque tout mon temps libre. J'ai décidé de faire une pause et dans l'intervalle de collecter une autre projection. Ayant estimé la fonctionnalité souhaitée, j’ai imaginé une période d’un mois et demi et, pour l’avenir, je dirai que, en principe, cela s’est avéré encore plus rapide. Le résultat a été une
application compacte et propre sur les deux plates-formes, très pratique. Maintenant, je l'utilise moi-même et je vous suggère de l'essayer.

Idée
Alors qu'est-ce que je voudrais d'un tracker de stationnement? Qu'est-ce que je manque toujours quand je reçois une amende Après réflexion, j'ai formulé l'introduction suivante:
- C'est simple. Idéalement, un bouton. Un minimum de fonctions distrayantes: pas de profils, historique de stationnement, prise en charge de plusieurs voitures en même temps, etc.
- Avec notifications. Je n'oublierais pas la voiture, si l'application me le rappelait: frère, tu as un parking là-bas en passant, et il est sur le point d'expirer.
- Considérez le temps de marche. C'est la pensée la plus simple que je n'ai jamais vu incarnée. Je n'ai pas besoin de savoir que le parking expirera dans 5 minutes si je suis à une demi-heure de là. Je dois être rappelé afin que je puisse arriver à la voiture quelques minutes avant la fin et partir.
- Itinéraire et navigation vers le parking. Navigation, bien sûr, via Google ou Apple Maps, mais l'itinéraire peut être affiché dans votre application. Cela vous aidera si vous avez laissé la voiture dans une zone inconnue, que le chronomètre sonne et que vous courez en rond dans les mêmes rues.
J'ai choisi Flutter comme base technologique, car je travaille avec lui depuis un certain temps et le considère comme bon. Pour les itinéraires, j'ai décidé d'utiliser l'API HERE, non pas pour la première fois, mais pour la carte - Mapbox. J'ai esquissé plusieurs options pour l'interface, choisi la plus minimaliste et me suis impliqué dans le travail.
Développement
En principe, il n'y a pas grand-chose à dire sur le processus de développement lui-même. Il n'y a pas de partie serveur ici, le client le plus simple, qui consiste essentiellement en une grande vue dans différents états. Sur la première page, vous sélectionnez un préréglage - 1, 2, 4, 6 heures - ou utilisez le curseur pour régler votre période de stationnement. Après l'avoir essayé en direct, j'ai réalisé que le curseur était assez grossier et y ai ajouté les boutons "+" et "-". Une nuance amusante et plutôt non évidente ici était que pendant que vous choisissez, le temps passe. Vous devez donc mettre à jour cette vue en temps réel. Après avoir choisi le terme, cliquez sur le seul bouton ci-dessous et les données de lieu et d'heure sont enregistrées et le stationnement commence. Il est important de noter que je stocke essentiellement toutes les données à bord, rien n'est transféré sur aucun serveur. À l'avenir, cela me créera d'ailleurs des difficultés, mais j'y reviendrai plus tard.
La deuxième page est, en fait, la minuterie de stationnement. J'ai essayé un tas d'options ici: j'ai commencé avec des prototypes d'informations extrêmement surchargés, puis je me suis débarrassé itérativement et simplifié à la limite. Je voulais vraiment que l'état du stationnement soit affiché visuellement, plutôt que des chiffres secs, donc l'élément principal de cette page avec la carte était un graphique en anneau. Il montre le temps écoulé, le temps de marche et le temps restant. Si vous n'êtes pas près de la voiture et que le temps de marche n'est pas nul, un bouton de démarrage de la navigation apparaît et la carte indique un itinéraire approximatif vers le parking. En fait, c'est tout.
Malgré la simplicité visuelle, cet écran m'a presque ébouriffé les nerfs. Il faut comprendre que pendant que le stationnement est actif, un certain nombre de processus se produisent simultanément:
- le temps passe et la minuterie s'épuise
- vous vous déplacez et changez de temps
Tout cela se passe en temps réel et devrait être affiché instantanément sur l'interface. La carte doit être reconstruite en douceur, la carte doit se déplacer et redessiner l'itinéraire, s'il y a un risque de retard ou d'expiration du stationnement, l'avertissement correspondant devrait également apparaître. De plus: lorsque vous fermez et ouvrez l'application, vous devez restaurer tout cela correctement. Et enfin, l'effrayant: toutes les fonctionnalités devraient pouvoir fonctionner en arrière-plan, car l'application passera la majeure partie de sa vie en arrière-plan. De telles choses.
Je ne décrirai pas la mise en œuvre en détail, je peux seulement dire que le travail de flottement avec les états est très digne. Alors que dans un pur androïde, un design orienté objet surchargé se révélerait, il s'est avéré simple et élégant. Des états compréhensibles normaux, une liaison sensible des vues aux modèles - dans des tâches comme celle-ci, le scintillement brille. Cependant, ce n'était pas sans jambages typiques: par exemple, la bibliothèque locale de travail avec des cartes n'a pas de transition animée vers de nouvelles coordonnées. J'ai dû entrer dans son code, sortir quelques méthodes privées et ajouter ma béquille. Il est possible que cette fonctionnalité soit ajoutée bientôt, mais c'est tout le flottement - avec toute son attractivité, préparez-vous à de telles découvertes.
Tout le reste semblait fonctionner sans problème. En fait, il n'y avait pas grand-chose d'autre: quelques dialogues et une page d'introduction pour laquelle ma copine (elle était
artiste ) a dessiné de belles animations. Enfin, j'ai traduit l'intégralité de l'application en russe, y compris la carte. Mais la douleur a commencé: les notifications.
Notifications
Pour moi, la possibilité d'envoyer des notifications intelligentes était la clé de l'application - sans elle, il n'y a rien à faire. Cependant, quand j'ai commencé à travailler sur cette fonctionnalité, j'ai réalisé que j'avais marché sur mon propre pied. Il y avait en fait deux problèmes. Le premier est le flutter, qui ne sait pas comment travailler avec les appareils api de bas niveau: vous devez écrire un joint sous la forme d'un plug-in qui contient deux codes natifs et une abstraction sur la fléchette. Le deuxième problème est ma position fondamentale selon laquelle tout doit être effectué à bord. Donc, nous résumons ce qui est nécessaire. Il est nécessaire que l'application
en arrière-plan :
- Surveiller en permanence votre géolocalisation,
- Vérifié combien de minutes à pied du parking
- Vérifié avec expiration du minuteur
- S'il y a un risque de ne pas avoir le temps de revenir, un coup de notification
Ressentez-vous l'ampleur de la tragédie? Il est clair qu'il n'y a aucune capacité technique à le faire si l'application est complètement supprimée. Mais supposons qu'il soit simplement minimisé et que l'écran soit éteint. ICI api me donne l'itinéraire et l'estimation du temps de marche, cela signifie-t-il que l'application spammera les requêtes en arrière-plan? Quelle quantité de code sera exécutée? Comment en sommes-nous avec la mémoire et la consommation d'énergie?
Je me suis assis pour réfléchir. Commencé par un petit: techniquement, flutter a récemment eu la possibilité d'exécuter du code en arrière-plan, il s'appelle isoler. Si tout est écrit correctement, vous pouvez créer une logique d'une manière spécifique afin que tout ne s'exécute pas en arrière-plan, mais certaines fonctionnalités spécifiques. En effet, en mode minimisé, nous n'avons pas besoin de dessiner d'interfaces ou de mettre à jour des états - nous nous intéressons à la logique du calcul du temps, et cette logique est assez compacte et bon marché. En même temps, cela ne devrait pas être déclenché par un changement de géolocalisation, comme je l'avais fait dans la version d'origine, mais par un minuteur interne. Parce que la notification devrait voler, même si vous ne bougez pas, mais restez assis.
Eh bien, nous avons écrit un code léger qui peut s'exécuter en arrière-plan et est contrôlé par une minuterie. Comment le déclencher dans le cadre d'applications natives et y transmettre des données de géolocalisation? Cela s'est avéré différemment.
La logique de l'androïde et de l'iPhone en matière d'exécution de code en arrière-plan est radicalement différente. Pour un iPhone, il est absent en tant que tel: le code d'arrière-plan ne peut déclencher qu'un événement système d'un certain type, par exemple, la lecture de streaming audio ou, heureusement pour moi, la mise à jour de l'emplacement. Pour ce faire, il suffit de demander des autorisations et, dans la partie native du plug-in Flater, de vous abonner à l'événement. De là, via un canal de communication spécifique (MethodChannel), nous appelons le rappel dans une fléchette, lui transmettons les géodonnées et commençons l'arrière-plan avec la logique dont nous avons besoin. La beauté
Android fonctionne différemment. Techniquement, il a la possibilité d'exécuter du code en arrière-plan sans être lié aux événements système - pour cela, vous devez décrire le service. Il se bloque séparément de l'application, soit complètement en arrière-plan, soit sur le pardon (là, il se fait sentir par un message joint en aveugle). Il semblerait que le problème soit résolu: dans la partie native du plugin, nous décrivons un service en arrière-plan qui suit l'emplacement et extrait le code Dark. Cependant, il y a une nuance. Depuis Android version 8.0, l'attitude envers de tels services a changé: maintenant, si l'application est minimisée pour le moment, ses services d'arrière-plan sont terriblement coupés par l'axe afin d'économiser de l'énergie. Et, si votre code effectue, par exemple, la sauvegarde de données, alors en principe, vous ne vous souciez pas du moment exact où l'axe le laissera fonctionner - l'essentiel est qu'il fonctionne. Mais dans mon cas, nous devons suivre le changement de lieu en temps quasi réel, et le timing est essentiel ici. Par conséquent, la seule solution consiste à démarrer le service par erreur. Nous décrivons une petite notification attachée dans le rideau, abonnez-vous à l'emplacement, envoyez-la à la fléchette via le MethodChannel. Tout semble fonctionner.
Soit dit en passant, revenons aux problèmes de mémoire, de consommation d'énergie et de nombre de demandes - le code est exécuté lorsque l'emplacement est décalé de 50 mètres ou par minuterie. De plus, il est lui-même très léger, et les demandes ne me traversent pas, mais vont directement à l'api ICI. Je ne reçois pas moi-même de données et je ne les enregistre nulle part. En général, une telle implémentation est très bien décrite
ici , c'est le blog de l'un des ingénieurs de flutter - le code y est joint. Son exemple est quelque peu différent, mais l'approche générale est claire, je recommande donc de le lire.
Résultat
En fait, c'est tout. Pendant un mois de temps libre, j'ai obtenu une application qui résout parfaitement un problème spécifique. J'espère que cet article sera intéressant pour quelqu'un, et l'application vous évitera des amendes et du stress. Vous pouvez regarder et gronder ici:
Android ,
iOS .
Merci à tous pour votre attention.