Harsh Mittal
Back to blog
2025-12-01·3 min read

🔗 Deep Linking in Flutter (2025): How It Works, What Breaks, and How to Fix It (Especially After Flutter 3.35)

Deep Linking in Flutter (2025)

Deep linking has always been one of those features that sounds simple… until your app suddenly refuses to open the right screen, or worse — opens with a black screen.

Recently, this happened to me right after upgrading one of my production apps from Flutter 3.24 → 3.35.

Everything was perfect on 3.24. Everything broke on 3.35.

Incoming links were ignored, getInitialLink() always returned null, the app opened the home screen instead of the target page, and some Android intents never reached Flutter.

After a few hours of debugging (and going through multiple GitHub issues), I finally found the real reason.

And trust me — if you use deep links with app_links, uni_links, firebase_dynamic_links, or Branch.io… this will save you hours.

What Changed in Deep Linking With Flutter 3.35?

Flutter silently introduced a brand-new built-in deep linking system. This system intercepts Android intents before your usual plugins get them.

Meaning: getInitialLink() stopped working, uriLinkStream stopped getting events, terminated-state deep links failed, and foreground links behaved unpredictably.

This is why most apps broke after upgrading. Flutter now tries to process deep links internally, and this conflicts with existing plugins that were already handling them.

How to Fix Deep Linking (and Restore Old Behavior)

To make your deep links work again, you need to do two simple things.

1. Disable Flutter's new deep linking engine.

Go to android/app/src/main/AndroidManifest.xml and add this meta-data tag inside <application>:

<meta-data
    android:name="flutter_deeplinking_enabled"
    android:value="false" />

This tells Flutter: "Don't handle deep links internally. Leave it to the plugins."

2. Forward Android intents to the Flutter engine.

Flutter 3.35 changed how intents are delivered to the Flutter engine. To ensure plugins like uni_links get the new intent, add this code in android/app/src/main/kotlin/.../MainActivity.kt:

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    flutterEngine?.activityControlSurface?.onNewIntent(intent)
}

This ensures foreground, background, and terminated-state deep links are all delivered.

After Applying These Fixes, Deep Linking Works Perfectly In:

Foreground, background, terminated state, when the app is already open, when the app is killed, and when clicking links from WhatsApp, SMS, email, or a browser.

Complete Working Example (Flutter 3.35)

Here's the minimum setup for a functional deep link system.

Flutter side:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final initialLink = await AppLinks().getInitialLink();
  runApp(MyApp(initialLink));
}

And for incoming links:

final _subscription = AppLinks().uriLinkStream.listen((uri) {
  // Navigate based on uri
});

Why Did Flutter Add a Deep Linking System?

The built-in handler was introduced to make deep linking uniform across iOS and Android, support the new Router API, improve web and mobile link consistency, and reduce plugin dependency.

But most existing apps weren't prepared for this change. So if you rely on classic plugins, you must opt out using the fix above.

When Should You Keep Flutter's New Built-in Deep Linking?

Keep it enabled if you're using go_router with declarative routing, you want auto-navigation based on URLs, you want unified behavior across platforms, or you don't need app_links, uni_links, or Firebase Dynamic Links.

Disable it (our solution) if you upgraded an existing app, you depend on plugins, you have complex deep link rules, or you use intent-based navigation logic.

My Take (as a Flutter Dev)

Deep linking is one of those features you set up once and forget — until a framework update quietly kills it.

After debugging multiple apps, the core lesson is: always check the AndroidManifest changes after a major Flutter upgrade.

Flutter's new deep linking system is great for new apps, but for existing apps with plugins, it creates conflicts.

The fix is simple once you know it. But finding the reason… that's the hard part.

Final Thoughts

If your deep links suddenly stopped working after moving to Flutter 3.35, just add this:

<meta-data
    android:name="flutter_deeplinking_enabled"
    android:value="false" />

And this:

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    flutterEngine?.activityControlSurface?.onNewIntent(intent)
}

That's all. Your deep links will be back to life — in all app states.

Get new posts by email

No spam, no schedule — just an email when a new post goes up.