Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deepLinkTransformer and deepLinkBuilder called twice in iOS cold start #2093

Open
jv-soares opened this issue Nov 20, 2024 · 4 comments
Open

Comments

@jv-soares
Copy link

jv-soares commented Nov 20, 2024

Hey guys it seems that deepLinkTransformer and deepLinkBuilder are being called twice whenever i launch the app on iOS by tapping on a deep link in any notes app. No problem on Android. Anyone knows why?

Version: 9.2.0

main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Environment.setup();
  await Firebase.initializeApp();
  await CrashReporter.runApp(() async {
    _setTransparentStatusBar();
    _setPreferredOrientations();
    await SharedPreferencesWrapper.instance.initialise();
    GetItManager.setup();
    await FirebaseRemoteConfigWrapper.fetch();
    runApp(const ProviderScope(child: App()));
  });
}

void _setPreferredOrientations() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
}

void _setTransparentStatusBar() {
  SystemChrome.setSystemUIOverlayStyle(
    const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: Brightness.dark,
      statusBarBrightness: Brightness.light,
    ),
  );
}
app.dart
class App extends StatefulWidget {
  const App({super.key});

  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  final _appRouter = getIt<AppRouter>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      title: 'Aparkado',
      debugShowCheckedModeBanner: false,
      routerConfig: _appRouter.config(
        deepLinkTransformer: DeepLinkHandler.deepLinkTransformer,
        deepLinkBuilder: DeepLinkHandler.deepLinkBuilder,
      ),
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
      theme: buildThemeData(),
    );
  }
}
flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on macOS 14.6.1 23G93 darwin-arm64, locale en-DE)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.2)
[✓] VS Code (version 1.95.3)
[✓] Connected device (3 available)
[✓] Network resources

• No issues found!

@mrverdant13
Copy link

Hey, @jv-soares 👋🏼

That is the expected behaviour for deep links in iOS

You can find more details about the different scenarios in the official Flutter docs page for deep links

@jv-soares
Copy link
Author

Hi @mrverdant13 thx for the reply!

I've read about these scenarios but i think the connection between these details and the behavior with deepLinkBuilder and deepLinkTransformer is still not clear enough, since the docs mostly mention implementation details such as RouteInformationParser and RouterDelegate.setNewRoutePath. I'd say its important to point out this behavior in the auto_route docs.

Another problem i faced and that might be related is that PlatformDeepLink.initial also has different values on Android vs iOS. I was using it to check whether the deep link triggered an app cold start or not.

Do you know how i could detect a cold start from the deep link?

@mrverdant13
Copy link

mrverdant13 commented Dec 5, 2024

@jv-soares
deepLinkBuilder and deepLinkTransformer are mere interceptor for what the platform provides.

Under the hood, any routing package uses the Pages API, which works by orchestrating the different data flows with a RouteInformationParser, a RouteInformationProvider, and a RouterDelegate.

image

Therefore, on iOS, your app receives a two-stages deep link report as it is the expected behaviour on that particular platform.

However, I agree on the need to include these details on the docs. It may be quite frustrating and time-consuming for us to try to face an issue that we cannot actually overcome.

As a side note, it looks like event he Flutter team is not always aware about this limitation even when it is detailed in the docs: flutter/flutter#142988 lol
EDIT: Actually, flutter/flutter#142988 is an open discussion on how to prevent this undesired behaviour.


Do you know how i could detect a cold start from the deep link?

I am not quite sure about how the initial flag gets resolved for a given deep link. I will have a look.

Besides that utility, I am afraid I do not know of a reliable method to identify a deep link used to launch an app from the terminated state.

A potential alternative would be creating a custom set of Uris pushed to the app by identifying them with the WidgetsBindingObserver.didPushRouteInformation method, and compare that collection of Uris against what you receive through the deepLinkBuilder and deepLinkTransformer helpers.

@jv-soares
Copy link
Author

@mrverdant13 many thx for the elaborate response! It was very helpful!

I'll take a look into the other issue you've linked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants