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

Deep Linking Issue on iOS from "Not Launched" State #2076

Open
kirya355 opened this issue Oct 17, 2024 · 0 comments
Open

Deep Linking Issue on iOS from "Not Launched" State #2076

kirya355 opened this issue Oct 17, 2024 · 0 comments

Comments

@kirya355
Copy link

kirya355 commented Oct 17, 2024

I'm experiencing an issue with deep linking on iOS using auto_route. When the app is in the "not launched" state, deeplinks do not open correctly "/second" route, only "/" route.
However, if I reduce the delay in the Future.delayed during initialization to 1 second, everything works fine. The issue occurs when the delay is set to 3 seconds. Additionally, deep links work correctly when the app is already open or minimized.

Steps to Reproduce:

  1. Set up a Flutter app with auto_route
    Code Example:
main.dart
import 'dart:async';

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';

part 'main.gr.dart';

Future<void> main() async {
  final binding = WidgetsFlutterBinding.ensureInitialized();
  binding.deferFirstFrame();

  try {
    //? Simulating initialization
    await Future.delayed(const Duration(seconds: 3));

    runApp(const MyApp());
  } catch (e) {
    runApp(MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Error'),
        ),
      ),
    ));
  } finally {
    if (!binding.sendFramesToEngine) {
      binding.allowFirstFrame();
    }
  }
}

@AutoRouterConfig()
class AppRouter extends RootStackRouter {
  static GlobalKey<ScaffoldMessengerState> get getRootScaffoldMessengerKey =>
      _rootScaffoldMessengerKey;

  static final GlobalKey<ScaffoldMessengerState> _rootScaffoldMessengerKey =
      GlobalKey<ScaffoldMessengerState>();

  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          path: '/',
          page: MyHomeRoute.page,
        ),
        AutoRoute(
          path: '/second',
          page: MySecondRoute.page,
        ),
        RedirectRoute(
          path: '*',
          redirectTo: '/',
        ),
      ];
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _router = AppRouter();

  void showMessage(String text) {
    final ScaffoldMessengerState? s = AppRouter.getRootScaffoldMessengerKey.currentState;
    s?.showSnackBar(SnackBar(content: Text(text)));
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      scaffoldMessengerKey: AppRouter.getRootScaffoldMessengerKey,
      title: 'Flutter Demo',
      routerConfig: _router.config(
        deepLinkBuilder: (deepLink) async {
          final uri = deepLink.uri;
          final initial = deepLink.initial;

          unawaited(Future.delayed(const Duration(seconds: 2), () {
            showMessage('uri: $uri');
          }));

          return DeepLink.path(
            uri.path,
            includePrefixMatches: initial,
          );
        },
      ),
    );
  }
}

@RoutePage()
class MyHomePage extends StatefulWidget {
  const MyHomePage({
    super.key,
  });

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() => setState(() => _counter += 1);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

@RoutePage()
class MySecondPage extends StatelessWidget {
  const MySecondPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('MySecondPage'),
      ),
    );
  }
}
  1. Add new lines in Info.plist
<key>CFBundleURLTypes</key>
  <array>
   <dict>
    <key>CFBundleTypeRole</key>
    <string>Viewer</string>
    <key>CFBundleURLName</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleURLSchemes</key>
    <array>
     <string>example</string>
    </array>
   </dict>
 </array>
 <key>FlutterDeepLinkingEnabled</key>
 <true/>
  1. Run app with flutter run and close it

  2. Use the following command to open a deep link:

xcrun simctl openurl booted example://x.com/second

Additional Context:

Flutter version: 3.22.2
On Flutter 3.22.3, 3.24.3 same

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

1 participant