-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Description
Steps to reproduce
It looks like in 3.32.x there has been a regression with deep links handling with the app closed in iOS. We did some git bisect and it looks to be related to this commit #164247 @hellohuanlin .
Steps:
- Install an app with https deep links managed by Flutter.
- Kill the app.
- Trigger the deep link (for example with xcrun simctl openurl booted )
- App is started but instead of opening the link in the app it opens in Safari.
Our app takes a couple seconds to load and deep links can only be handled after that. So what we do when onGenerateRoute is called and the app didn't load yet we save the link for later handling.
In the example we do a mock of this behavior that can trigger the error. This only seems to happen with https links because they are handled by the phone browser. After some debugging it looks like it has this behavior because we return null in generateRoute when the app didn't load. This didn't happen before the linked commit.
Expected results
Link is handled in app.
Actual results
Link is opened in Safari.
Code sample
import 'dart:async';
import 'package:flutter/material.dart';
// When a deep link is triggered while the app is closed we first need to load the app so we save it here to handle later.
String? globalPendingDeepLink;
Future<void> main() async {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool loading = true;
@override
void initState() {
super.initState();
// Mock initial app loading. Deep links would be handled after the app loads.
Future.delayed(Duration(seconds: 3)).then((_) {
if (!mounted) return;
setState(() {
loading = false;
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
onGenerateRoute: createOnGenerateRoute(),
onGenerateInitialRoutes: (route) {
print("FLUTTER: onGenerateInitialRoutes: $route");
return [
MaterialPageRoute(
builder: (context) {
return HomeWidget(appLoading: loading);
},
),
];
},
);
}
RouteFactory createOnGenerateRoute() {
return (RouteSettings settings) {
final pathOrUri = settings.name;
print("FLUTTER: onGenerateRoute: $pathOrUri initial app loading: $loading");
if (loading) {
// Save link until the app is loaded to handle later.
globalPendingDeepLink = pathOrUri;
return null;
}
final route = _handleRouteSettings(pathOrUri);
if (route != null) {
return route;
}
return null;
};
}
}
class HomeWidget extends StatefulWidget {
final bool appLoading;
const HomeWidget({super.key, required this.appLoading});
@override
State<HomeWidget> createState() => HomeWidgetState();
}
class HomeWidgetState extends State<HomeWidget> {
@override
void didUpdateWidget(covariant HomeWidget oldWidget) {
if (widget.appLoading != oldWidget.appLoading && !widget.appLoading) {
print("FLUTTER: app has been loaded. Pending link $globalPendingDeepLink");
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (globalPendingDeepLink != null) {
final route = _handleRouteSettings(globalPendingDeepLink);
if (route != null) {
globalPendingDeepLink = null;
Navigator.of(context, rootNavigator: true).push<void>(route);
}
}
});
}
;
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Home")),
body: Center(child: widget.appLoading ? CircularProgressIndicator() : Text("Home")),
);
}
}
Route<Object?>? _handleRouteSettings(String? pathOrUri) {
print("HANDLE ROUTE SETTINGS: $pathOrUri");
if (pathOrUri == null || pathOrUri == "/") {
return null;
}
return MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(),
body: Center(child: Text("Deep link: $pathOrUri")),
),
);
}
Screenshots or Video
No response
Logs
Since the app needs to be closed when opening through the deep link we don't have logs.
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.32.4, on macOS 15.5 24F74 darwin-arm64, locale es-ES) [387ms]
• Flutter version 3.32.4 on channel stable at /Users/jorge/.local/share/mise/installs/flutter/3.32.4-stable
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 6fba2447e9 (hace 3 días), 2025-06-12 19:03:56 -0700
• Engine revision 8cd19e509d
• Dart version 3.8.1
• DevTools version 2.45.1
[✗] Android toolchain - develop for Android devices [368ms]
• Android SDK at /opt/homebrew/Caskroom/android-platform-tools/36.0.0
✗ cmdline-tools component is missing.
Try installing or updating Android Studio.
Alternatively, download the tools from https://developer.android.com/studio#command-line-tools-only and make sure to set the ANDROID_HOME environment variable.
See https://developer.android.com/studio/command-line for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 16.2) [835ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16C5032a
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [11ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2022.3) [10ms]
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)
[✓] VS Code (version 1.101.0) [9ms]
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.112.0
[✓] Connected device (4 available) [6,2s]
• iphone J (wireless) (mobile) • 00008130-00016C4A0E90001C • ios • iOS 18.4.1 22E252
• iPhone 15 Pro (mobile) • 52288C1D-7C4B-4E41-8F79-FC26DEEF0EC3 • ios • com.apple.CoreSimulator.SimRuntime.iOS-18-3 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 15.5 24F74 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 137.0.7151.104
! Error: Browsing on the local area network for iPad J. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac.
The device must be opted into Developer Mode to connect wirelessly. (code -27)
[✓] Network resources [287ms]
• All expected network resources are available.
! Doctor found issues in 1 category.