Flutter : Dynamic Link not launching the app

Viewed 4555

I am using firebase dynamic links to open the email verification link in my app, but unfortunetly the link doesn't launch the app when tapped.

What I've done so far

When a new user is created, a link is sent by email to be verified :

if(firebaseUser != null && !firebaseUser.emailVerified){
        await createUserInDatabaseIfNew(firebaseUser);
        var actionCodeSettings = auth.ActionCodeSettings(
          url: 'https://muslimcoloc.page.link/?email=${firebaseUser.email}',
          dynamicLinkDomain: "muslimcoloc.page.link",
          androidInstallApp: true,
          androidMinimumVersion: "12",
          androidPackageName: "com.app.muslim_coloc",
          iOSBundleId: "com.muslim_coloc.ios",
          handleCodeInApp: true,
        );
        await firebaseUser.sendEmailVerification(actionCodeSettings);
      }

I got the dynamicLinkDomain in the firebase console :

enter image description here

Then, I handle the reception of the link in my main.dart file, with the firebase dynamic links package :

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(
    MyApp(),
  );
}
class MyApp extends StatelessWidget {
 MyApp({Key key, })  :  super(key: key);
 
 @override
 Widget build(BuildContext context) {
  return AppView();
 }
}

class AppView extends StatefulWidget {
  const AppView({
    Key key,
  }) : super(key: key);

  @override
  _AppViewState createState() => _AppViewState();
}
class _AppViewState extends State<AppView> with WidgetsBindingObserver {
@override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
       this.initDynamicLinks();
    }
  }
 
 void initDynamicLinks() async {
      FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData dynamicLink) async {
          final Uri deepLink = dynamicLink?.link;
          FirebaseAuth auth = FirebaseAuth.instance;

          //Get actionCode from the dynamicLink
          var actionCode = deepLink.queryParameters['oobCode'];

          try {
            await auth.checkActionCode(actionCode);
            await auth.applyActionCode(actionCode);

            // If successful, reload the user:
            auth.currentUser.reload();
          } on FirebaseAuthException catch (e) {
            if (e.code == 'invalid-action-code') {
              print('The code is invalid.');
            }
          }

          if (deepLink != null) {
            Navigator.pushNamed(context, deepLink.path);
          }
        },
        onError: (OnLinkErrorException e) async {
          print('onLinkError');
          print(e.message);
        }
      );
      
      final PendingDynamicLinkData data = 
        await FirebaseDynamicLinks.instance.getInitialLink();
      final Uri deepLink = data?.link;

      if (deepLink != null) {
        Navigator.pushNamed(context, deepLink.path);
      }
    }
  @override
  Widget build(BuildContext context) {
   return MaterialApp(...)
}

When I tap the link of the email, the app doesn't start nor does the browser. Here's what happens :

enter image description here

It tries to launch something on the browser, but then comes back to gmail.

However if I click on the link in a desktop browser, it works fine, the email is validated.

I'm having a hard time understanding what it going on. Is there something wrong about how I did things ?

1 Answers

You should write a function to handle your dynamic links, as per the documentation, and this is working for me in an app being used currently:

void handleDynamicLinks() async {
    ///To bring INTO FOREGROUND FROM DYNAMIC LINK.
    FirebaseDynamicLinks.instance.onLink(
      onSuccess: (PendingDynamicLinkData dynamicLinkData) async {
        await _handleDeepLink(dynamicLinkData);
      },
      onError: (OnLinkErrorException e) async {
        print('DynamicLink Failed: ${e.message}');
        return e.message;
      },
    );

    final PendingDynamicLinkData data =
        await FirebaseDynamicLinks.instance.getInitialLink();
    _handleDeepLink(data);
  }

  // bool _deeplink = true;
  _handleDeepLink(PendingDynamicLinkData data) async {
  
     final Uri? deeplink = data.link;
    if (deeplink != null) {
      print('Handling Deep Link | deepLink: $deeplink');
  }
}

and in initState:

@override
  void initState() {
    handleDynamicLinks();
    super.initState();
}

write this logic in your home page. Not in void(main..etc) But in your first widget after that, and it should work.

Also, be sure to double check your package name, i.e com.example.yourAwesomeApp123, it's what lets the whole system know what app is to be opened when the dynamic link is pressed.

Related