In 2015, the Dart Developer Summit saw the introduction of Sky, an experimental UI framework for writing Android apps using Dart. It started out with Android, but the technology was architectured in such a way that it could run on any device – web, desktop, car, refrigerator, anything with a screen.
Sky was eventually renamed to Flutter, and the list of supported platforms gradually expanded to include iOS, web, and desktop. However, this is hardly the end of the road for Flutter, so the question that comes to mind is: what’s next? My guess is embedded devices.
I will try to illustrate that by running Flutter on a Raspberry Pi to show some interesting use cases.
The embedded way
The Flutter team started out with just Android, but they were able to add support for other platforms by writing the embedder. An embedder is not one program, but rather a whole system consisting of various tasks such as:
- Creating the rendering surface. The Flutter canvas needs to map to the platform canvas, which usually uses some low-level graphical interface like OpenGl, Vulkan, or Metal
- Creating/setting up threads and providing event loop interop since Dart is a single-threaded language
- Communicating user inputs such as touch, pointer, or button press to Flutter
- Communicating system events to Flutter
- Producing binaries that can be used on the platform
These tasks require extensive knowledge of the platform we are embedding into. It’s mostly low-level code, not suitable for beginners. Full-fledged embedders have 15-30k lines of source code. More information can be found on Flutter’s web page.
Currently, there are three default embedders written by the Flutter team: Android, iOS, and web, while desktop embedders for Mac, Linux, and Windows are in beta. Anyone can write an embedder, for example desktops started with the unofficial embedder go-flutter and the official support was added later.
An embedded refrigerator?
Embedded devices is a very broad term, but not every device is suitable for Flutter. First off, a device is not an application, it has both hardware and software. This means that it requires an embedded engineer and someone to design the circuit board.
When you find an appropriate device and the hardware is ready, you need to build the software to power the UI. With the current state of technology, this is a challenging task. The hardware has limited performance, and the current tools you can use to build UI interfaces have their own drawbacks. This is where Flutter provides a solution.
Flutter + Raspberry Pi
I’ve chosen Raspberry Pi for demonstration purposes, although any similar device can be used. Raspberry Pi is a small single-board low-cost computer and running Flutter on it can make for some very interesting use cases.
We could run Flutter on Raspberry Pi using the default Linux embedder that comes with Flutter because Raspberry Pi can run Linux, but I chose not to do that. The main reason is that the Linux embedder is more suitable for a real desktop experience with multiple windows and different apps, like Windows or Mac. We are going to use flutter-pi which is a light-weight embedder for Raspberry Pi. It doesn’t require a window system or a desktop at all, it will run on no-desktop Raspberry Pi OS Lite.
Use case #1: Ordering burgers with a real embedded feel
We build a simple Flutter app and follow the flutter-pi instructions to run it on Raspberry Pi. Here is a preview of the app with the whole setup running:
With Flutter we are able to create a great-looking app that runs smoothly with all the animations on Raspberry Pi. Flutter-pi gives it a real embedded feel because the user is unable to exit the app, interact with the Linux OS or turn the whole system off.
Use case #2: Flipping the switch with GPIO
The real power of this setup with Raspberry Pi is that you can connect external devices and communicate with them. They can connect with Raspberry Pi over WiFi, Bluetooth, USB or wires (GPIO). To demonstrate, we are going to control a small LED light using Flutter over GPIO.
There are few ways to control GPIO pins. For this example, I skipped the Python programs and used the simplest way, which is echoing value (0 or 1) into a designated file. There’s one file for each GPIO pin on location with a path like /sys/class/gpio/gpio27/. If we echo 1, it means it will let the power through the pin so the light will turn on, and 0 will cut the power off.
With that info, we can build an app that will invoke the process command to turn the LED light on or off:
We could listen to button presses in the same way, or interact with various sensors, for example a temperature or a distance sensor. We could run a servo motor, printer or whatever, since there is almost no limit with GPIO, it’s just a matter of effort.
Of course, there are other ways to build a product that satisfies the use cases above. Let’s see how they compare with the embedded Flutter solution.
iOS or Android tablet
Since we’re using a touchscreen, it might seem a good idea to simply use an Android or an iOS tablet. However, it’s not. Here’s why:
- The users could exit the app. We would need to add workarounds to make the OS and our app behave like a kiosk.
- Tablets don’t have a GPIO interface so we couldn’t easily connect to low-level devices.
- We don’t control the hardware. For the setup I’ve described we can buy a Raspberry Pi 3 and whatever touchscreen we need separately, for example a big 15″ touchscreen.
- It’s expensive in comparison to buying a chip and a screen.
Chromium Kiosk mode or the Electron app
There are other alternatives that can run on Raspberry Pi, for example the Chromium Kiosk mode or the Electron app. Although the setup is different, both solutions allow you to use popular web technologies (HTML, JS) to build the app. However, the downside is that there’s a lot of overhead when running these, which might impact the performance. For example, in Chromium Kiosk mode you need to run full desktop Linux with the Chromium browser on top. The browser then runs your app, while with flutter-pi your app runs on “bare metal” Linux.
Qt works similar to Flutter, although it’s more focused on desktop and embedded devices. You write Qt apps in C++, which is a less popular and lower level language.
Qt is better integrated with the platform so it’s somewhat easier to communicate with the native platform and the external devices.
Other than language, Qt’s downside is that it’s not completely free. Also, it’s much older than Flutter, and Flutter brings some improvements in terms of performance and UI building.
The future of Flutter
When Flutter was first introduced, it could only run on iOS and Android. The first time I tried Flutter for desktop, I used a third-party embedder in a similar way as with Raspberry Pi. Today, Flutter desktop has an official beta release, so we can only expect it to continue to evolve and support embedded platforms in the same way.