Windows remains a popular choice for desktop and laptop devices, with Microsoft reporting over one billion active devices running Windows 10. Our own statistics show that over half of all Flutter developers use Windows, so it’s a natural target for Flutter. Native desktop support opens up a variety of exciting possibilities for Flutter, including improved developer tooling, reduced friction for new users, and of course apps that can reach any device a user might have from a single codebase.
Adding Windows to Flutter
As described in our architectural overview, Flutter is a cross-platform UI toolkit that is designed to allow code reuse across operating systems such as iOS and Android, while also allowing applications to interface directly with underlying platform services. The goal is to enable developers to deliver high-performance apps that feel natural on different platforms, embracing differences where they exist while sharing as much code as possible. At the core of Flutter is the engine, which supports the primitives necessary to support all Flutter applications. The engine is responsible for rasterizing composited scenes whenever a new frame needs to be painted. It provides the low-level implementation of Flutter’s core API, including graphics, text layout, file and network I/O, accessibility support, plugin architecture, and a Dart runtime and compile toolchain.
Each new platform we add to Flutter expands the core framework with new services to enable it to shine on that platform. We started on Android and iOS with Material Design as well as a touch-based, mobile-centric user interface that is designed to be pixel-perfect on both mobile platforms. Adding support for desktop form factors with web, Windows, macOS, and Linux brings a whole new set of services, including robust support for keyboards, mice, mouse wheels and controllers on the input side as well as widgets that adapt or even work best at the larger screen sizes that come with web and desktop apps.
Furthermore, each new platform doesn’t just influence the Flutter framework and engine, but a lot of other things as well:
- Toolchain updates: adding a new target to the CLI and IDE tools (in this case Windows)
- Shell: support for handling input from Windows via WM_* messages and output via ANGLE, which uses Skia to render at native speed to an underlying DirectX surface
- Runner: every project gets a shell application for the supported targets. For Windows, it’s a Win32/C++ program that loads your Flutter code and executes it at runtime. It’s a good place to add native code to your app if you need it.
- Plugins: A plugin is a mixture of Dart code and native code for each of the platforms that the plugin supports. That native code needs to be added for each plugin that is compiled into your Flutter app on Windows.
This alpha release offers a solid foundation that we’ll stabilize over the coming months. With support for Windows 7 and above, we hope this gives adventurous developers something to get started with.
Getting started with Flutter for Windows
Get started by installing the Flutter SDK according to the Windows install instructions. To target Windows desktop, you first need to install the tooling described in the desktop docs. By default, Flutter assumes that you’re building production software and isn’t configured to develop Windows apps. However, that’s easily fixed from the command line:
$ flutter channel dev $ flutter upgrade $ flutter config --enable-windows-desktop
The first command sets Flutter to use the experimental-quality “dev” channel (instead of the “stable” channel, which is the default). This allows you to use platform support that’s still in alpha, like Windows. The second command pulls down the latest bits on that channel. The third command enables Windows app development on your PC.
Once you’ve set it up, every time you create a new Flutter app, using the extension support for either Android Studio or Visual Studio Code, or from the command line, it creates a windows subfolder.
If you’re curious, running the default app on Windows looks like the following:
And finally, once you’ve created your app, building it creates a release-mode, native EXE file as well as the necessary supporting DLLs. At that point, if you want to experiment with running your new Windows app on any Windows 10 machine, even those that don’t have Flutter installed, you can follow the steps to zip up the necessary files and go.
Plugins for Windows
Even though we’ve just reached the alpha release, the Flutter community has already been working on plugins for Windows. Here are a few:
- url_launcher: launch URLs in the browser from your app
- path_provider: find the path to special directions on the user’s machine like Documents or temp
- shared_preferences: keep user preferences serialized on disk between sessions of your app
- biometric_storage: storage encrypted by biometrics
- flutter_audio_desktop: play audio from your desktop apps
The benefit of using these plugins is that most of them also support other Flutter platforms, which enables you to target your apps at Android, iOS, web, etc. as well as Windows. Furthermore, while about one-third of the available packages on pub.dev (the package manager for Dart and Flutter) are plugins with platform-specific code, most are not. For instance, many of the highest quality and most used packages are part of the Flutter Favorite program and most of them work on Windows. If you’d like to see the full list of packages that run on Windows, you can run this query on pub.dev.
Interop with Windows
If you’d like to build your own plugins for Windows, you can. Once you’re on the dev channel and you have Windows enabled for your machine, you can get started with the following command:
$ flutter create --template plugin --platforms windows hello_plugin
At that point, you’ll be able to add your Flutter code to the lib subfolder and your Windows code to the windows subfolder in your plugin project. You’ll communicate between the two stacks using Platform Channels, which is essentially message passing between your Dart and C++ code. For a well crafted example of this, see the url_launcher implementation.
However, Platform Channels are not your only option for interop with Windows. If you like, you can use the Dart FFI (Foreign Function Interface) to load libraries and call into C-style APIs, such as the Win32 API. Unlike url_launcher, which uses Platform Channels, the path_provider plugin was implemented using FFI, as you can see in the GitHub repo. Instead of going back and forth between Dart and C++, FFI allows you to write code to import the API that you want directly. For example, here’s the code for calling the MessageBox API:
typedef MessageBoxNative = Int32 Function( IntPtr hWnd, Pointer<Utf16> lpText, Pointer<Utf16> lpCaption, Int32 uType ); typedef MessageBoxDart = int Function( int hWnd, Pointer<Utf16> lpText, Pointer<Utf16> lpCaption, int uType ); final user32 = DynamicLibrary.open('user32.dll'); final win32MessageBox = user32.lookupFunction<MessageBoxNative, MessageBoxDart>('MessageBoxW'); void showMessageBox(String message, String caption) => win32MessageBox( 0, // No owner window Utf16.toUtf16(message), // Message Utf16.toUtf16(caption), // Window title 0 // OK button only ); ... // call just like any other Dart function showMessageBox('Test Message', 'Window Caption');
This code doesn’t incur the overhead of transitioning between two threads like Platform Channels. FFI includes support for many different kinds of APIs, including Win32, WinRT, and COM. But before you run off and wrap the entire C-based Windows API, please check out the win32 plugin, which is already well on its way to doing just that. In fact, the path_provider plugin was itself implemented using the win32 plugin.
For more information and to develop mobile apps using Flutter, Hire Flutter Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – email@example.com or Skype us: “hkinfosoft”. To develop Mobile Apps using Flutter, please visit our technology page.