01 · THE PIECES
Five separate things, one of which everyone forgets.
Flutter on Windows is not one download. Understanding what each piece does turns most setup errors into obvious ones.
| Component | What it is | Needed for |
|---|---|---|
| Flutter SDK | The framework, the Dart SDK and the flutter tool | Everything |
| Android SDK platform | The API level your app compiles against | Any Android build |
| Android build tools and platform tools | The packaging tools, plus adb | Building and installing to devices |
| A JDK | Java runtime and compiler that Gradle runs on | Every Gradle build. This is the piece people forget. |
| Command line tools | sdkmanager and the licence machinery | Accepting licences, installing SDK packages without the IDE |
Android Studio bundles most of this, which is why it remains the easiest route even if you intend to work in another editor. The alternative — the standalone command line tools — is leaner and better for CI, but you install and wire each piece yourself.
02 · INSTALLATION
Install in this order, and check after each step.
Extract to a short path with no spaces, such as C:\src\flutter. Never under Program Files: the tool writes into its own directory and will hit permission errors there.
Add C:\src\flutter\bin to the user PATH, then open a new terminal. flutter --version should answer.
Install Android Studio and, in the SDK Manager, add a platform, the build tools and — on the SDK Tools tab — the Android SDK Command-line Tools. That last checkbox is the most commonly missed item in the entire setup.
Install a JDK that matches the Gradle version your projects use, and set JAVA_HOME. Section three explains how to pick the number.
Run flutter doctor --android-licenses and accept them all. Builds fail with an unhelpful message until you do.
Run flutter doctor -v. Resolve everything that is not a tick before writing any code — a warning here becomes a confusing build error later.
flutter --version
flutter doctor -v
# Tell Flutter which JDK to use for Gradle builds
flutter config --jdk-dir "C:\Program Files\Eclipse Adoptium\jdk-21"
# Tell Flutter where the Android SDK lives, if it did not find it
flutter config --android-sdk "C:\Users\you\AppData\Local\Android\Sdk"
# Accept every Android licence
flutter doctor --android-licenses
03 · THE JDK
Match the JDK to Gradle, not to the newest release.
More Flutter build failures trace back to a JDK and Gradle mismatch than to anything in Dart. The rule is simple: Gradle decides, not you.
Each Gradle release supports a bounded range of Java versions, and the Android Gradle Plugin adds its own minimum on top. Installing the newest JDK because it is newest produces the error people paste into search engines most often: Unsupported class file major version.
| Situation | Do this |
|---|---|
| New project, current Flutter | Use the JDK bundled with your Android Studio version, or a current LTS release, and let the template pick Gradle |
| Older project that will not build | Read the Gradle version in gradle-wrapper.properties, then install the JDK that release supports |
| Unsupported class file major version | Your JDK is newer than Gradle supports. Point at an older JDK or upgrade Gradle and the Android Gradle Plugin together. |
| Several projects on different Gradle versions | Install more than one JDK and switch JAVA_HOME per project rather than upgrading everything at once |
# The Gradle version the project pins
Get-Content android\gradle\wrapper\gradle-wrapper.properties
# Which JDK Gradle is currently running on
cd android; .\gradlew --version; cd ..
# Which JDK is on PATH right now
java -version
echo $env:JAVA_HOME
Do not upgrade Gradle to fix a JDK error on a project that ships. Raising Gradle usually forces an Android Gradle Plugin upgrade, which can force plugin and dependency updates across the project. Install the older JDK, get a green build, and schedule the upgrade as its own piece of work.
04 · VERSION MANAGEMENT
Pin the Flutter SDK per project once you have two.
Flutter upgrades occasionally change behaviour that a shipped app depends on. Pinning the SDK per project makes that a scheduled decision rather than a surprise.
The built-in route
flutter channel stable
flutter upgrade
# Pin the global SDK to a specific release
flutter downgrade 3.24.0
The per-project route
FVM (Flutter Version Management) installs SDK versions side by side and selects one per repository, in the same spirit as a Node version manager:
dart pub global activate fvm
# In the project directory: pin and use a version
fvm use 3.24.0
# Run commands against the pinned SDK
fvm flutter pub get
fvm flutter build appbundle --release
Commit the FVM configuration file. Point your editor’s Flutter SDK path at the project’s .fvm directory so analysis and the command line agree — a mismatch there produces analyser errors that do not reproduce in a build, which is a genuinely irritating way to lose an afternoon.
Pin the SDK before your first release, not after. Reproducing a build from six months ago is only possible if you wrote down which SDK made it.
05 · RUNNING IT
Emulator, physical device, or both.
The emulator
- Enable hardware acceleration. On Windows this means the Windows Hypervisor Platform feature. Without it the emulator is slow enough to be useless.
- Use an x86_64 system image. ARM images run under translation and are dramatically slower.
- Give it a realistic device profile. A phone-sized window catches layout problems that a large emulator hides.
- Cold boot when something is stuck. A corrupted snapshot explains a surprising share of “the emulator will not start” reports.
A physical device
# Enable developer options and USB debugging on the phone first
adb devices
flutter devices
flutter run
# Wireless, on Android 11 and later
adb pair 192.168.1.50:41234
adb connect 192.168.1.50:5555
Always test on real hardware before release. Emulators do not reproduce actual performance, real notification behaviour, aggressive vendor battery optimisation, or how the app behaves when the system reclaims memory. The ADB guide covers the device side in more detail.
06 · FAILURES
Seven errors, and what each one actually means.
| Message | Meaning | Fix |
|---|---|---|
| cmdline-tools component is missing | The command line tools package was not installed | SDK Manager, SDK Tools tab, tick Android SDK Command-line Tools |
| Android licence status unknown | Licences not accepted for this SDK installation | flutter doctor --android-licenses, then accept each one |
| Unsupported class file major version | JDK newer than the project Gradle supports | Install a matching JDK and set JAVA_HOME and the Flutter jdk-dir |
| Gradle task assembleDebug failed | A generic wrapper around the real error | Run gradlew assembleDebug --stacktrace inside android for the actual cause |
| Filename too long | Windows path limit inside a deep build tree | Move the project near the drive root, or enable long paths |
| Waiting for another flutter command to release the startup lock | A stale lock file from a killed process | Close every editor, then delete the lockfile in the Flutter SDK bin cache |
| Builds are extremely slow | Antivirus scanning the build output | Exclude the project, the Flutter SDK and the Gradle cache from real-time scanning |
When a build fails, read the Gradle error, not the Flutter one. Change into the android directory and run the Gradle task directly with --stacktrace. Flutter summarises; Gradle tells you which dependency, which plugin and which line.
07 · QUICK ANSWERS
Flutter on Windows, briefly.
You need the Android SDK, and Android Studio is the simplest way to get it along with the emulator and SDK manager. You can install the standalone command line tools instead and work entirely in another editor, which is leaner and better suited to CI, but you then wire up each component yourself.
The one your project Gradle version supports, not necessarily the newest. Check the Gradle version in android/gradle/wrapper/gradle-wrapper.properties, install a JDK in its supported range, set JAVA_HOME, and point Flutter at it with flutter config --jdk-dir. Installing the newest JDK is the usual cause of the unsupported class file major version error.
The Android SDK Command-line Tools package is not installed. Open the SDK Manager in Android Studio, go to the SDK Tools tab, tick Android SDK Command-line Tools and apply. This package provides sdkmanager and the licence machinery, so licence acceptance also fails without it.
Once you maintain more than one app, yes. FVM installs Flutter SDK versions side by side and pins one per repository, so upgrading the SDK becomes a deliberate per-project decision instead of a global change. Commit the configuration and point your editor at the project SDK path so the analyser and the build agree.
Usually antivirus real-time scanning over the build output, the Gradle cache and the Flutter SDK, which are all directories full of thousands of small files. Add exclusions for the project directory, the Flutter SDK and the Gradle home directory. A deep path near the Windows path length limit is the second most common cause.