There’s a lot to be said for tools that make it easy to target multiple platforms from a single codebase, reducing the load on developers and increasing the reach of your applications. Microsoft’s Xamarin is an excellent example of this, extending .NET to iOS and Android. But what of the other direction, where an established mobile development tool adds Windows as a new platform?
It doesn’t happen often, but surprisingly Google’s Flutter mobile development environment is adding a new build target in Windows, alongside its existing support for Android, iOS, macOS, Linux, and the web. With the latest development releases, you can now build Flutter apps for Win32, using the same controls and design tools to deliver desktop code at the same time as you build mobile apps.
Targeting Windows makes sense for Google, as the release blog post notes more than half of Flutter developers use Windows development tools. Flutter’s UI-tooling is native code and as it works with standard Windows API calls, you can use it with new or existing code.
Using Flutter on Windows
Flutter’s Windows support is experimental, so you have to make some changes to a standard installation from the command line. First switch to the dev channel and then upgrade to ensure you’re running the latest dev channel build. Finally, use the command line Flutter tools to enable Windows desktop support. Once that’s done, restart any open editors. You can check that Windows support is enabled by checking for connected devices; Windows will show up here. It’s a good idea to run the Flutter doctor utility to check that all the appropriate dependencies are installed, as this will install any missing features as necessary.
Unlike the mobile device versions of Flutter, the desktop version needs Visual Studio 2019, with its C++ desktop development tools. You can still work in Visual Studio Code if you’ve got any existing mobile Flutter apps that you want to bring to the desktop, but desktop Flutter needs to use the Windows C++ compiler to create Windows apps with all the required supporting libraries.
Writing Flutter applications on Windows
Even though you need Visual Studio’s C++ tools, you still edit and build much of your Flutter desktop applications in Visual Studio Code with the Flutter plug-in, switching out for Visual Studio when you need to edit C++ or use the Windows SDKs. Creating a new project will automatically generate the scaffolding needed to build a Windows desktop application alongside the default Android and iOS versions. You can then edit your application code in the common main.dart file, which will be compiled into the appropriate versions at build time.
Common Dart code remains in the lib folder. The Windows folder is where you write your platform-specific code, keeping it separate from any cross-platform functions. This approach allows you to build on your existing investments in Windows code and APIs using Flutter’s Platform Channels to deliver interoperability between Windows C++ code and Flutter’s Dart.
The Visual Studio Code Flutter and Dart tools still need Android Studio to be installed, as they’re needed to build Android versions of your applications. If you’re working on a cross-platform app, it’s best to write any Android code in Android Studio, saving the Kotlin code into your Flutter app’s Android code tree. Sharing a code structure in this way makes sense; while you have the option of using Visual Studio Code to edit Windows C++ code, the full Visual Studio IDE has many more affordances and better library support, making it a preferable development environment for code that needs to use the Win32 SDK and libraries.
Using Windows SDKs, APIs, and libraries with Flutter
Flutter is designed to work across development stacks and offers two different routes to working with Windows-native APIs. The first, platform channels, provides a way of passing messages from a Flutter UI to a native API using a platform plug-in as a wrapper for the API. Although this is the approved method of working across stack boundaries, it’s message-based and asynchronous, so not suitable for all the Windows APIs.
Alternatively, you can use its Foreign Function Interface to link directly to a native library and use its API calls. This approach is likely to be the best way to deliver Windows functionality to a Flutter app, as you can link to existing or new code directly, with either static or dynamic links. Native code needs to have available C symbols so your Flutter code can link to them; any C++ code will need to export them in C format via the
Most Windows SDK libraries are already compiled, so you need to use dynamic linking to bring them into your Flutter applications. Use the Flutter
DynamicLibrary.open function to add them to your application, and then treat them much as you would a Flutter plug-in. In fact the Flutter team is already working on a Win32 plug-in that will provide access to most of the Windows APIs, ready for use in your code.
A tool for rapid, collaborative UI development
One of the advantages of Flutter’s development tooling is its hot reload option. You can have a copy of your code running and attached to a debugger, make a change to the code, and hit the hot reload key in the Visual Studio Code terminal to reload the application without changing its state. There’s a hot restart option if you prefer to start with a fresh state.
Being able to quickly change UI or business logic without restarting an app is a really useful feature for Flutter. Programming becomes more interactive, especially if you’re working beside a designer or an end-user. You can ask what works, make suggested changes quickly, and get an instant response from your development partners. Once you’re ready to publish and deploy your code, you run a build to generate an exe file with all the appropriate support DLLs, ready for packaging with your choice of installer.
You’re not limited to Win32 either, as a UWP Flutter shell is currently under development (and has already been used for Store apps). The result is a flexible and powerful cross-platform UI layer that will work with native code across a range of platforms, that scales to the larger screens of PCs, works with both modern and legacy Windows SDKs, and should be ready to work with Project Reunion as it rolls out.