Developing for hybrid solutions with Flutter
This is a three part article sharing how we developed a mobile app with Google’s Flutter. Please read part one, detailing our design sprint and user experience process, here: Part One and part two, explaining the design system we chose, here: Part Two
With the challenge came a short delivery deadline of around 4 months only for the task at hand, which was to develop native iOS and Android apps as well as the apps server that would serve as a connection point to the EMBERS API. That’s when we decided to go with Flutter.
Flutter is Google’s mobile app SDK for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source.
The strong points of Flutter that helped us make this decision were:
- fast front-end reactive development with flexible and fully customizable components (can be rewritten easily) which translates into reduced UI and Business Logic development time;
- allows cross-platform mobile app development, using about 80% of shared code for both iOS and Android platforms (Dart language);
- native performance (which was very important) and access to native features and SDKs.
But after we began researching more about it, performing some “test runs” and running into some issues, we realized that it could be a little too soon to start with Flutter.
Flutter’s issues that have worried us:
- A big lack of information (easily accessible) regarding more specific problems;
- Flutter is a very recent technology (May 2017; 1 year and 6 months ago) and is still in Beta, meaning constant updates, with some of them being breaking changes;
- Complex integration with native external libraries.
The first two issues are closely related, as Flutter doesn't have a big community yet, which leads to a shortage of solutions when we are faced with a certain problem. With respect to the complex native integrations, we were lucky enough to always have available the right package for our needs and only had to implement a minor method for the iOS map view.
All in all we were able to produce everything that we had planed for the apps, even if we needed to use some of the workarounds suggested by members of the community to solve some issues until those are resolved by the Flutter team.
As we needed to have a secure and fully functional app because there are payments involved without the need to log in, we implemented three different types of communication between the client and the server:
- The Authentication was implemented based on a Challenge-Handshake mechanism, that starts by a register process which generates a RSA key pair (one public and one private) for the connecting device and registers the public key in association with a generated device UUID on the server (this registration only happens in the first launch of the App).
- Then the authentication itself takes place by the client identifying himself with the respective device UUID, the server takes that UUID and, using it’s public key, generates an encrypted secret which is sent back to the client. The client decrypts the secret with it’s private key and encrypts it back with the server’s public key, sending it again over to the server. The server then decrypts the encrypted secret with it’s private key and compares the result to the secret sent initially, if it matches then an access token is sent to the client. This mechanism ensures that the server always knows which device is making the communications and sending requests;
- The REST requests, which are used to communicate with the server API. The server also functions as an access proxy to the EMBERS API therefore making accesses more secure;
- The on-event push based on Phoenix Websockets, which creates and maintains a connection with the server as soon as the user makes a booking or requests to get in, until he leaves the park. This communication is used to synchronize all the information regarding the user’s current parking usage with the server. This happens when the server pushes an event through the channel of the websocket that, in this case, occurs every time the current state suffers any changes.
The final product
In conclusion, we were very happy with the results as we were able to make everything work as expected and according with the client expectations.
This being a pilot meant that some features weren’t yet implemented but that are ready to roll in the future, such as the user account area and push notifications.
Have a look at how everything came up in the end:
On our point of view, Flutter is great asset in terms of mobile development and we can’t wait to see it flourish to, maybe, become one of the biggest in a near future.