Flutter 3.50 and Dart 3.14 shipped on November 11, 2026, and this is not a release you can upgrade blindly on a Friday afternoon. It deprecates the Material and Cupertino libraries inside the SDK, makes direct native interop stable, tightens how Android release builds treat incoming Intents, and starts the countdown on CocoaPods and Intel Macs. Below is what changed, what can break, and the order we would do the upgrade in for an app that is already live in the stores.
▶ Watch the video version (about 4 minutes):
What shipped, in one paragraph
According to the official What's new in Flutter 3.50 post, the release combines more than 1,200 commits from 188 contributors (69 of them first-timers). The headline items are: the bundled package:flutter/material.dart and package:flutter/cupertino.dart are now formally deprecated in favour of the standalone material_ui and cupertino_ui packages; FFIgen for Objective-C and JNIgen for Java and Kotlin are stable; Android release builds verify Intent senders before honouring routing and engine extras; iOS gets one frame less touch latency; and Flutter web can run WebAssembly on Safari and Firefox as an opt-in. The companion Dart 3.14 announcement adds a new dart migrate command for stepping packages across SDK versions.
None of this forces an emergency rewrite. But several items change behaviour silently in release builds, which is exactly where you do not want surprises.
Material and Cupertino move out of the SDK
This is the change every Flutter app will touch. Since Flutter 3.44 the in-SDK Material and Cupertino code has been frozen, and version 1.0 of the standalone packages arrived on pub.dev with Flutter 3.47. In 3.50 the old libraries are deprecated and flutter create now generates projects that import package:material_ui by default (migration guide).
Why the Flutter team did it:
- The design packages can ship fixes and new components on their own schedule (the guide says weekly releases are planned) instead of waiting for a quarterly SDK release.
- The packages follow semantic versioning, so you can pin and upgrade them like any other dependency.
- Localization delegates for Material and Cupertino widgets now live in the packages, not in
flutter_localizations.
The migration itself is mostly automated:
flutter upgrade
dart fix --apply --code=migrate_design_widgets
flutter analyze
The dart fix code rewrites imports and localization delegates. Deprecated does not mean removed, so your app still compiles without migrating, but you will see warnings and you will miss fixes that only land in the packages. One example is already here: DropdownButtonFormField gained an explicit enabled parameter in material_ui 1.8.0, so you no longer have to pass null to onChanged to disable it (breaking changes list).
If you maintain a package or plugin, the guide is explicit: switching your own imports to material_ui is a breaking change for consumers, so ship it as a major version bump.
Direct native interop is stable
For years, calling native code from Flutter meant platform channels: serialize arguments, cross the bridge asynchronously, deserialize, run the API, and do it all again for the result. Pigeon removed the string typos but still generated channel code underneath.
The Flutter team's native interop announcement (November 12) changes the default answer:
- FFIgen generates Dart bindings for C and, now stably, Objective-C APIs.
- JNIgen generates bindings for Java and Kotlin, from Android system APIs to your own AARs and JARs. It is now stable.
- Pigeon v30+ can use both generators under the hood, as a preview. You keep one Pigeon contract and get direct FFI/JNI calls, synchronous calls when needed, and calls from background isolates.
Turning it on in an existing Pigeon file is a configuration change: set appDirectory, SwiftOptions(useFfi: true) and KotlinOptions(useJni: true) in @ConfigurePigeon. The team migrated shared_preferences this way and published a migration guide based on that work.
Two cautions. First, Pigeon's native interop mode is a preview and only covers Android, iOS and macOS; Windows and Linux keep platform channels. Second, raw FFIgen and JNIgen bindings are low-level: the announcement notes that memory management and thread handling can become your responsibility. For most app teams, the practical move is to try it on one hot path (for example a sensor, crypto or image-processing call that runs every frame) rather than rewriting every plugin.
Android: stricter Intents, new toolchain defaults
Intent verification in release builds
This is the change most likely to surprise a production app. Previously the Flutter Android embedder accepted extras such as route, dart_entrypoint and cached_engine_id from any app that launched your activity. In 3.50, release builds verify the sender first (Intent verification guide):
- Activities with
android:exported="false"are trusted. - On Android 14+ (API 34), the launching UID must match your app's UID; on Android 13 and lower, the calling package must match, which requires
startActivityForResult()orstartActivityIfNeeded(). - Deep links (
ACTION_VIEW) still work, but the URI must match an intent filter declared inAndroidManifest.xml.
If verification fails, the extras are ignored and the app falls back to manifest metadata or defaults. In practice: if a widget, notification or partner app opens a specific Flutter route through Intent extras, test it on a release build before you ship.
A related change restricts engine flags in release mode: flags passed through adb shell am start extras are ignored, and flutter run --release --use-application-binary with engine flags is now a fatal error. Standard flutter build appbundle workflows are not affected.
Toolchain and platform views
New Android projects use AGP 9.3.1, Gradle 9.5.0, Kotlin Gradle Plugin 2.4.20 and Java 17, with compileSdk and targetSdk 36 and minSdk 24. Target 36 matches Google Play's target API requirement in force since August 31, 2026, so new projects start compliant. Existing projects keep their own values; check them.
Hybrid Composition++ (for maps and web views) gets more fixes. It needs Android 14+ and Impeller on Vulkan, and falls back automatically elsewhere; you can opt in with flutter config --enable-hcpp.
iOS and macOS: faster touch, CocoaPods sunset
- Touch latency: touch events now reach the framework in the same display refresh, cutting one frame of input latency: 16 ms on 60 Hz devices and 8 ms on 120 Hz ProMotion screens, per the release post.
- iOS 27 debugging: a freshly paired or upgraded iPhone no longer stalls on a white screen until you open Xcode once, and
flutter screenshotworks on physical devices again when built with Xcode 27. - Swift Package Manager: the CocoaPods trunk becomes read-only in December 2026. If you disabled Swift Package Manager to work around a build issue, every Flutter CLI command now warns you, and a future release removes the opt-out.
- Intel Macs: Flutter no longer tests on Intel Mac hardware and the CLI warns once when you build on one. A future release will require Apple Silicon to build for iOS, macOS or Android.
If a CI runner or a team laptop is still Intel, now is the time to budget for replacing it.
Web: WebAssembly beyond Chrome
flutter build web --wasm compiles to WebAssembly with a JavaScript fallback. Chrome and Edge already ran Wasm by default; in 3.50, Safari 26.2+ and Firefox 147+ deliver over 2x the frame rate of JavaScript on heavy widget benchmarks, and you can opt in through wasmAllowList in web/flutter_bootstrap.js before it becomes the default.
Two flags are worth adding to CI today:
--web-content-hashputs content hashes in JS, Wasm and asset filenames, so you can cache them for a year and avoid users loading stale bundles after a deploy.--no-deprecated-js-interopfails the build if your code or a dependency still usesdart:html,dart:js,dart:js_utilorpackage:js, which are now deprecated.
The upgrade checklist
| Area | What changed | Who is affected | Action |
|---|---|---|---|
| UI libraries | material.dart deprecated | Every app | Run dart fix migration |
| Plugins | material_ui import | Package authors | Major version bump |
| Android Intents | Release builds verify sender | Apps routed by extras | Test release builds |
| Engine flags | Ignored in release | CI/test scripts | Use debug or profile |
| iOS deps | CocoaPods read-only (Dec) | SPM opt-outs | Re-enable SPM |
| Build machines | Intel Mac warning | Intel CI/laptops | Plan Apple Silicon |
| Web | Wasm opt-in, JS interop | Web builds | Add the two flags |
A safe order for a live app:
- Upgrade on a branch, run
flutter analyzeand your test suite before touching anything else. - Run the
migrate_design_widgetsfix and review the diff; check localization still loads. - Build an Android release APK and test every entry point: launcher, deep links, notifications, widgets.
- Re-enable Swift Package Manager if you had turned it off and do a clean iOS archive.
- Update plugins (
flutter pub outdated) and read their changelogs for thematerial_uimajor bump. - Ship to internal testing or TestFlight first, then a staged rollout.
For packages, dart migrate from Dart 3.14 can step the SDK constraint forward one version at a time, applying the needed dart fix changes along the way.
Our take
At Lightning Studio we build and maintain mobile apps for clients, so our rule is simple: upgrade the toolchain within a few weeks of a stable release, but never in the same sprint as a feature launch. For 3.50 we would do the material_ui migration early, because the warnings are noisy and future widget fixes land only in the packages. The Android Intent change is the one we would test hardest, since it changes behaviour only in release builds and only on certain launch paths.
Direct native interop is the most interesting part long term. Removing the async round trip makes Flutter a better fit for apps that talk to hardware or run native SDKs constantly. We would still wait for Pigeon's interop mode to leave preview before moving client plugins, and use raw JNIgen or FFIgen only where profiling shows platform channels are the bottleneck.
Sources
- What's new in Flutter 3.50 (Flutter blog, November 11, 2026)
- Announcing stable direct native interoperability (Flutter blog, November 12, 2026)
- Announcing Dart 3.14 (Dart blog, November 11, 2026)
- Migrate to standalone material_ui and cupertino_ui packages (Flutter docs)
- Stricter Android Intent verification for app entrypoints (Flutter docs)
- Restrict Android engine flags in release mode (Flutter docs)
- Breaking changes and migration guides (Flutter docs)
- Meet Google Play's target API level requirement (Android Developers)
Planning a Flutter upgrade or a new cross-platform app? Lightning Studio builds and maintains iOS and Android apps from Da Nang. Write to support@lightning-studio.org or see what we do at https://lightning-studio.org/studio/.
Cover photo: Apple iPhone 15 Pro by IPHONE 15, CC BY-SA 4.0, via Wikimedia Commons (cropped).



