MarcS82
MarcS82

Reputation: 2517

Where to handle Firebase Dynamic Links in Flutter?

I use Firebase dynamic links and also named routes. What I want is to install a global listener for the dynamic link events and forward to register page if a token is provided. In the code below I got the exception The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget. which means I have to put navigation code below the home: property of MaterialApp. But when doing this I had to implement the dynamic links event handler for earch route.

class MyApp extends StatelessWidget {
  String title = "Framr";

  @override
  Widget build(BuildContext context) {

    FirebaseDynamicLinks.instance.onLink(
      onSuccess: (linkData) {
        if (linkData != null) {
          try {
            Navigator.pushNamed(context, '/register', arguments: linkData);
            // throws: The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
          } catch(e) {
            print(e);
          }
        }
        return null;
      }
    );

    return MaterialApp(
      title: "...",
      home: LoginPage(),
      routes: {
        '/createEvent': (context) => CreateEventPage(),
        '/showEvent': (context) => ShowEventPage(),
        '/register': (context) => RegisterPage(),
      },
    );
  }
}

Upvotes: 3

Views: 1955

Answers (1)

user1611357
user1611357

Reputation: 86

I was able to get this work by following the example provided from the dynamic link README with the use of the no_context_navigation package or GlobalKey to workaround around the lack of context to call Navigator.pushNamed(...). Note: You don't have to use no_context_navigation. You can implement the no context routing yourself. Here's an example.

// Add this
import 'package:no_context_navigation/no_context_navigation.dart';

void main() {
  runApp(MaterialApp(
    title: 'Dynamic Links Example',
    // Add this
    navigatorKey: NavigationService.navigationKey,
    routes: <String, WidgetBuilder>{
      '/': (BuildContext context) => MyHomeWidget(), // Default home route
      '/helloworld': (BuildContext context) => MyHelloWorldWidget(),
    },
  ));
}

class MyHomeWidgetState extends State<MyHomeWidget> {
  .
  .
  .
  @override
  void initState() {
    super.initState();
    this.initDynamicLinks();
  }

  void initDynamicLinks() async {
    FirebaseDynamicLinks.instance.onLink(
      onSuccess: (PendingDynamicLinkData dynamicLink) async {
        // Add this.
        final NavigationService navService = NavigationService();
        final Uri deepLink = dynamicLink?.link;

        if (deepLink != null) {
          // This doesn't work due to lack of context
          // Navigator.pushNamed(context, deepLink.path);
          
          // Use this instead
          navService.pushNamed('/helloworld', args: dynamicLink);
        }
      },
      onError: (OnLinkErrorException e) async {
        print('onLinkError');
        print(e.message);
      }
    );
    
    final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
    final Uri deepLink = data?.link;

    if (deepLink != null) {
      // This doesn't work due to lack of context
      // Navigator.pushNamed(context, deepLink.path);
      
      // Use this instead
      navService.pushNamed('/helloworld', args: dynamicLink);
    }
  }
  .
  .
  .
}

// pubspec.yaml
no_context_navigation: ^1.0.4

Upvotes: 2

Related Questions