Skip to content

🐛 [firebase_dynamic_link] New iOS install doesn't open with dynamic link after install #7546

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

Closed
badrobot15 opened this issue Dec 10, 2021 · 48 comments · Fixed by #10493
Closed
Assignees
Labels
platform: ios Issues / PRs which are specifically for iOS. plugin: dynamic_links type: bug Something isn't working

Comments

@badrobot15
Copy link

badrobot15 commented Dec 10, 2021

Bug report

Dynamic Link returns null
On latest version of 4.0.2, for fresh app installs from a dynamic link in iOS via AppStore, the link isn't received in Flutter App. On clicking the link, the app store page opens as required, but after the user downloads the app, the dynamic link within the app seems to be null. Now if having the app already installed on the phone, on clicking the link, the app successfully gets the link. While this behavior is fine for users who already have the app, it totally ruins the experience for new users.

Additional context

Found a similar problem at issue #1861 but that seems to have been closed with the only solution being restart the phone and then install. Since the only way we are able to reproduce the bug is after deploying it to production on app store, it is quite difficult to debug and find the problem.

         final _appLinks = AppLinks(
         onAppLink: (Uri deepLink, String dataStr) async {
           
           if (deepLink == null) return false;

           pendingDynamicLinkData = await FirebaseDynamicLinks.instance.getDynamicLink(deepLink);
           actualDeepLink = pendingDynamicLinkData.link ?? null; 

           if (actualDeepLink == null) return false;
           .
           .
           .
           .
           return true;

         },
       );

As per #6913 I had to use AppLinks to get the link for iOS only.

@badrobot15 badrobot15 added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Dec 10, 2021
@darshankawar darshankawar added the triage Issue is currently being triaged. label Dec 14, 2021
@darshankawar
Copy link

@badrobot15
Does getInitialLink() get back with data or is null throughout the case ?
Also, is there a way for you to check if ibi parameter matches with your app's bundle Id ?

@darshankawar darshankawar added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Dec 14, 2021
@badrobot15
Copy link
Author

badrobot15 commented Dec 14, 2021

@darshankawar getInitialLink() comes null throughout the case even when app is intalled on phone hence the need to use app_links package. ibi parameter matches with apps's bundle id.

As per the flowchart here, getInitialLink() doesn't work for when the app is installed nor for when the user is sent to the app store to install the app. However, the dynamic link is copied to clipboard when user is redirected to app store.

After switching to app_links package we found that if the app is installed, the link is delivered successfully by the code snippet I posted above

Following is the initial code we tried

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

final Uri deepLink = data?.link;

FirebaseDynamicLinks.instance.onLink.listen((event)  {

        pendingDynamicLinkData = event;

        actualDeepLink = pendingDynamicLinkData.link ?? null;

        if (actualDeepLink == null) return false;
        ...
        ...
        return true;
      },

     onError: (error){
          
     },

     onDone: (){

     },

);

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Dec 14, 2021
@darshankawar
Copy link

Thanks for the update. Labeling it based on the report and the fact that this is replicable only after deploying prod app on appstore and then trying to install the app.

/cc @Salakar

@darshankawar darshankawar added plugin: dynamic_links platform: ios Issues / PRs which are specifically for iOS. and removed Needs Attention This issue needs maintainer attention. triage Issue is currently being triaged. labels Dec 15, 2021
@snghnishant
Copy link

flutter doctor -v

[✓] Flutter (Channel stable, 2.10.4, on macOS 12.3.1 21E258 darwin-arm, locale en-IN)
    • Flutter version 2.10.4 at /Users/snghnishant/Developer/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision c860cba910 (5 weeks ago), 2022-03-25 00:23:12 -0500
    • Engine revision 57d3bac3dd
    • Dart version 2.16.2
    • DevTools version 2.9.2

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at /Users/snghnishant/Library/Android/sdk
    • Platform android-31, build-tools 31.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
    • 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 11.0.11+0-b60-7772763)

[✓] VS Code (version 1.66.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (1 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 100.0.4896.127

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

I have tried implementing with the latest plugin firebase_dynamic_links: ^4.2.1 and both onLink.listen() getInitialLink() don't seem to work on iOS though Android works as expected without any issue.

Also tried implementing the workaround given in the related issue using app_links: ^3.1.0 but this too not working at all on iOS.

Here's the implementation of the code (I have separate functions for handling terminated and background/foreground redirects in our app

Future<void> handleTerminatedStateDynamicLinks(
    BuildContext context, FirebaseDynamicLinks dynamicLinkInstance) async {
  try {
    final Uri? deepLink;
    // Terminated app state
    /*if (Platform.isIOS) {
      AppLinks _appLinks = AppLinks();
      deepLink = await _appLinks.getInitialAppLink();
      debugPrint("Deeplink URL (iOS terminated): ${deepLink.toString()}");
    } else {
      final PendingDynamicLinkData? data =
          await dynamicLinkInstance.getInitialLink();
      deepLink = data?.link;
      debugPrint("Deeplink URL (on terminated): ${deepLink.toString()}");
    }*/
    final PendingDynamicLinkData? data =
        await dynamicLinkInstance.getInitialLink();
    deepLink = data?.link;
    debugPrint("Deeplink URL (on terminated): ${deepLink.toString()}");
    if (deepLink != null) {
      String? referCode = deepLink.queryParameters['invited_by'];
      // Store refer code in hive because user can drop off in b/w signup
      if (referCode != null) {
        bool flag = await putPersistentData('refer_code', referCode);
        if (flag) {
          debugPrint("Saved Referral Code to Hive");
          CleverTapPlugin.recordEvent('Referral App Open', {});
        }
      } else {
        // store deeplink for redirect
        await putPersistentData('deepLink', deepLink.toString());
      }
    }
    return;
  } catch (error) {
    debugPrint("Dynamic link terminated state error: ${error.toString()}");
    sendErrorLog("handleTerminatedStateDynamicLinks: ${error.toString()}");
  }
}

Future<void> handleBackgroundForegroundStateDynamicLinks(
    BuildContext context, FirebaseDynamicLinks dynamicLinkInstance) async {
  /*if (Platform.isIOS) {
    final AppLinks _appLinks = AppLinks();

    // Foreground or background app state [iOS]
    _appLinks.uriLinkStream.listen((uri) async {
      debugPrint('iOS onAppLink: $uri');
      PendingDynamicLinkData? deepLink =
          await dynamicLinkInstance.getDynamicLink(uri);
      handleDynamicLinksRedirects(context, deepLink?.link);
    });
  } else {*/
  // Foreground or background app state [ANDROID]
  dynamicLinkInstance.onLink.listen((dynamicLinkData) async {
    final Uri deepLink = dynamicLinkData.link;
    debugPrint(
        "Deeplink URL (on foreground/background): ${deepLink.toString()}");
    handleDynamicLinksRedirects(context, deepLink);
    return;
  }).onError((error) {
    // Handle errors
    debugPrint(
        "Dynamic Link error at foreground/background Listener: ${error.toString()}");
    sendErrorLog(
        "handleBackgroundForegroundStateDynamicLinks: ${error.toString()}");
  });
  //}
  return;
}

@otopba

This comment was marked as outdated.

@wederchr
Copy link

@darshankawar As discussed in #9103 (comment) I'm posting my question here.

This is the exact issue I am facing. I have already tried the workaround using the app_links plugin but it didn't solve the issue. Though I have only tested through TestFlight using the iosFallbackLink (pointing to the TestFlight app). Can you confirm testing dynamic links through TestFlight using the iosFallbackLink parameter should work?

@wederchr
Copy link

@darshankawar Any update on this issue?

@wederchr
Copy link

wederchr commented Aug 2, 2022

@darshankawar A response would be much appreciated. I have not heard back from you since you closed my original issue.

@russellwheatley russellwheatley modified the milestone: Test milestone Aug 2, 2022
@darshankawar
Copy link

@wederchr Sorry for not coming back to this earlier. Please take a look at below links and see if they help:

#8926
#8926 (comment)
#9110 (comment)
#9110 (comment)

@darshankawar
Copy link

/cc @russellwheatley

@wederchr
Copy link

wederchr commented Aug 2, 2022

@wederchr Sorry for not coming back to this earlier. Please take a look at below links and see if they help:

#8926 #8926 (comment) #9110 (comment) #9110 (comment)

Thank you for your response, I'll take a look! Did you also have time to clarify my question regarding firebase dynamic link testing using TestFlight?

@snghnishant
Copy link

flutter doctor -v


[✓] Flutter (Channel stable, 2.10.4, on macOS 12.3.1 21E258 darwin-arm, locale en-IN)

    • Flutter version 2.10.4 at /Users/snghnishant/Developer/flutter

    • Upstream repository https://github.com/flutter/flutter.git

    • Framework revision c860cba910 (5 weeks ago), 2022-03-25 00:23:12 -0500

    • Engine revision 57d3bac3dd

    • Dart version 2.16.2

    • DevTools version 2.9.2



[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)

    • Android SDK at /Users/snghnishant/Library/Android/sdk

    • Platform android-31, build-tools 31.0.0

    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java

    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7772763)

    • All Android licenses accepted.



[✓] Xcode - develop for iOS and macOS (Xcode 13.3.1)

    • Xcode at /Applications/Xcode.app/Contents/Developer

    • CocoaPods version 1.11.3



[✓] Chrome - develop for the web

    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome



[✓] Android Studio (version 2021.1)

    • 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 11.0.11+0-b60-7772763)



[✓] VS Code (version 1.66.2)

    • VS Code at /Applications/Visual Studio Code.app/Contents

    • Flutter extension can be installed from:

      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter



[✓] Connected device (1 available)

    • Chrome (web) • chrome • web-javascript • Google Chrome 100.0.4896.127



[✓] HTTP Host Availability

    • All required HTTP hosts are available



• No issues found!

I have tried implementing with the latest plugin firebase_dynamic_links: ^4.2.1 and both onLink.listen() getInitialLink() don't seem to work on iOS though Android works as expected without any issue.

Also tried implementing the workaround given in the related issue using app_links: ^3.1.0 but this too not working at all on iOS.

Here's the implementation of the code (I have separate functions for handling terminated and background/foreground redirects in our app

Future<void> handleTerminatedStateDynamicLinks(

    BuildContext context, FirebaseDynamicLinks dynamicLinkInstance) async {

  try {

    final Uri? deepLink;

    // Terminated app state

    /*if (Platform.isIOS) {

      AppLinks _appLinks = AppLinks();

      deepLink = await _appLinks.getInitialAppLink();

      debugPrint("Deeplink URL (iOS terminated): ${deepLink.toString()}");

    } else {

      final PendingDynamicLinkData? data =

          await dynamicLinkInstance.getInitialLink();

      deepLink = data?.link;

      debugPrint("Deeplink URL (on terminated): ${deepLink.toString()}");

    }*/

    final PendingDynamicLinkData? data =

        await dynamicLinkInstance.getInitialLink();

    deepLink = data?.link;

    debugPrint("Deeplink URL (on terminated): ${deepLink.toString()}");

    if (deepLink != null) {

      String? referCode = deepLink.queryParameters['invited_by'];

      // Store refer code in hive because user can drop off in b/w signup

      if (referCode != null) {

        bool flag = await putPersistentData('refer_code', referCode);

        if (flag) {

          debugPrint("Saved Referral Code to Hive");

          CleverTapPlugin.recordEvent('Referral App Open', {});

        }

      } else {

        // store deeplink for redirect

        await putPersistentData('deepLink', deepLink.toString());

      }

    }

    return;

  } catch (error) {

    debugPrint("Dynamic link terminated state error: ${error.toString()}");

    sendErrorLog("handleTerminatedStateDynamicLinks: ${error.toString()}");

  }

}



Future<void> handleBackgroundForegroundStateDynamicLinks(

    BuildContext context, FirebaseDynamicLinks dynamicLinkInstance) async {

  /*if (Platform.isIOS) {

    final AppLinks _appLinks = AppLinks();



    // Foreground or background app state [iOS]

    _appLinks.uriLinkStream.listen((uri) async {

      debugPrint('iOS onAppLink: $uri');

      PendingDynamicLinkData? deepLink =

          await dynamicLinkInstance.getDynamicLink(uri);

      handleDynamicLinksRedirects(context, deepLink?.link);

    });

  } else {*/

  // Foreground or background app state [ANDROID]

  dynamicLinkInstance.onLink.listen((dynamicLinkData) async {

    final Uri deepLink = dynamicLinkData.link;

    debugPrint(

        "Deeplink URL (on foreground/background): ${deepLink.toString()}");

    handleDynamicLinksRedirects(context, deepLink);

    return;

  }).onError((error) {

    // Handle errors

    debugPrint(

        "Dynamic Link error at foreground/background Listener: ${error.toString()}");

    sendErrorLog(

        "handleBackgroundForegroundStateDynamicLinks: ${error.toString()}");

  });

  //}

  return;

}


The flutter firebase dynamic links plugin seems to work now without any other package. There was an issue with some native code being override for supporting an attribution SDK in my case. Removing that helped making firebase dynamic link plugin work on both iOS and android in all 3 app state.

@darshankawar darshankawar removed the resolution: no-response Customer did not respond after some time. label Sep 28, 2022
@MrJohn2014
Copy link

Having the same issue. getInitialLink() always null and onLink method seems not called on ios. I also tried app_link package and it always return null.

@matthewfx
Copy link

It looks like @darshankawar and @russellwheatley don't care anymore because they keep promising to look into it and then nothing happens for weeks and bots try to either tag it or close it. It is a pity because even though branch.io offers a working alternative I'd prefer to use Firebase because my app has been already having too many dependencies...

@darshankawar
Copy link

Did you also have time to clarify my question regarding firebase dynamic link testing using TestFlight?

I think using ifl parameter as you had already mentioned and verified, can be used which will install the app from testlfight instead of app store.

It looks like @darshankawar and @russellwheatley don't care anymore because they keep promising to look into it and then nothing happens for weeks and bots try to either tag it or close it.

This isn't true. We care for each and every issue that is filed. The team comes back to issues when they have completed the task at their hand. I will also forward this issue for team's attention.

@matthewfx
Copy link

@darshankawar Thanks!

@russellwheatley russellwheatley self-assigned this Oct 6, 2022
@markglibres
Copy link

hi.. this issue is unfortunately bugging us too.. hope this can be fixed soon...

@russellwheatley
Copy link
Member

I'm going to be looking at dynamic links soon. I've been working on major SDK updates and latest count API for Firestore.

@stevenspiel
Copy link

Thanks for looking at it @russellwheatley. It's becoming a hinderance for our company.

@migalv
Copy link

migalv commented Nov 12, 2022

Same issue happening for us too. I have used the app_links workaround when app is in Terminated state but I'm afraid it's not working when the app is installed from App Store.

void initDynamicLinks() {
  FirebaseDynamicLinks.instance.onLink.listen((dynamicLink) {
    linkParameters = dynamicLink.link.queryParameters;
  });
  
  if (Platform.isIOS) {
    final dynamicLink = await AppLinks().getInitialAppLink();
    if (dynamicLink != null) {
      try {
        initialLink = await FirebaseDynamicLinks.instance.getDynamicLink(dynamicLink);
      } catch (e) {
        log("Firebase could not find a Dynamic Link for the given App Link: $dynamicLink");
      }
    }
  } else {
    initialLink = await FirebaseDynamicLinks.instance.getInitialLink();
  }
  
  if (initialLink != null) {
    linkParameters = initialLink.link.queryParameters;
  }
}

@migalv
Copy link

migalv commented Nov 12, 2022

I tried using the Dynamic Links example as @russellwheatley suggests in this comment.

But since I don't have access to the Provisioning Profile I can't test it.

I have copied and pasted the code to another project where I have configured Firebase following the Firebase Dynamic Links documentation.

This is what I get

RPReplay_Final1668287401.MP4

@jasonJamEther
Copy link

I am facing the same issue. Has anyone found a solution? I had this working about a year ago. So either ios or this package changed.

@shadyashraf96
Copy link

In case anyone still needs a solution, here's what worked for me.
I added these imports in AppDelegate.mm

#import <FirebaseDynamicLinks.h>
#import <RNFBDynamicLinksAppDelegateInterceptor.h>
#import <React/RCTLinkingManager.h>

And this block after @implementation AppDelegate

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

and I added this line after '[FIRApp configure];'

[RNFBDynamicLinksAppDelegateInterceptor sharedInstance]; // add this line

@marialaguna
Copy link

marialaguna commented Jan 27, 2023

We have been struggling with the same issue for weeks an non of the solutions above worked for us. Moreover, both the flutter library for Firebase Dynamic Links and the example, are written in Objective-C and our flutter app is written on Swift.
In order to address the problem we had to look the iOS native implementation provided by Firebase .
Adding the code provided in the last step was the solution for us. To be more precise the next method:

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: url){
        // Handle dynamic link and call to flutter channel
        return true;
    }
    return false;
  }

@GsusBiking
Copy link

I also have the same problem, when starting the application from the appstore through a dynamic link, the popup appears that the data has been copied, but once it is started through "getInitialLink" they all appear in null

link example:
https://appname.com/?&apn=appname.mobile.prod&ibi=appname.mobile.prod&link=appname.com%3Faction%26component%3Dreferral%26data%26utm_source%3Dweb%26utm_content%3Dtest%26utm_medium%3Dorganic%26utm_campaign%3Dtest %26utm_term%3Dtest%26aib_ref%3Dtest

@bcgreijnlautier
Copy link

This comment provides a solution that worked for me. All I had to do is setup my onLink listener before getting the initial link:

final linkSubscription = FirebaseDynamicLinks.instance.onLink.listen(
  (event) {
    print(event.link.toString());
  },
);

final initialLink = await FirebaseDynamicLinks.instance.getInitialLink();

@russellwheatley I think the documentation should be updated to demonstrate this.

@jasonJamEther
Copy link

@bcgreijnlautier thank you! this solution worked for me too.

@russellwheatley
Copy link
Member

@bcgreijnlautier that is a good idea. I will do that 👍

@migalv
Copy link

migalv commented Feb 28, 2023

I'm so confused @russellwheatley you say here:

@bcgreijnlautier that is a good idea. I will do that 👍

that you should first set up the stream as @bcgreijnlautier mentions

This comment provides a solution that worked for me. All I had to do is setup my onLink listener before getting the initial link:

final linkSubscription = FirebaseDynamicLinks.instance.onLink.listen(
  (event) {
    print(event.link.toString());
  },
);

final initialLink = await FirebaseDynamicLinks.instance.getInitialLink();

@russellwheatley I think the documentation should be updated to demonstrate this.

But then on the documentation, you state the opposite, I'm just confused.

(From the commit 915a75d) PR: #10493

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseConfig.platformOptions);
  // Get any initial links
  // Check if you received the link via `getInitialLink` first
  final PendingDynamicLinkData? initialLink = await FirebaseDynamicLinks.instance.getInitialLink();
  if (initialLink != null) {
    final Uri deepLink = initialLink.link;
    // Example of using the dynamic link to push the user to a different screen
    Navigator.pushNamed(context, deepLink.path);
  }
  FirebaseDynamicLinks.instance.onLink.listen(
        (pendingDynamicLinkData) {
          // Set up the `onLink` event listener next as it may be received here
          if (pendingDynamicLinkData != null) {
            final Uri deepLink = pendingDynamicLinkData.link;
            // Example of using the dynamic link to push the user to a different screen
            Navigator.pushNamed(context, deepLink.path);
          }
        },
      );
  runApp(MyApp(initialLink));
}

@russellwheatley
Copy link
Member

russellwheatley commented Feb 28, 2023

@migalv both are fine. The point is, on iOS, the initial link could be received by either getInitialLink or onLink API. You have to set it up so that if getInitialLink is null, you receive it in the onLink handler.

@ifk-tiger
Copy link

Same issue. Everything works perfect on Android. But, after download from App Store, it does not works on inital opening on iOS. However, when I clicked the dynamic link when app is open on the background, it works. Any update about this issue? My configurations of Firebase related packages and code are below:

Packages:
firebase_core: ^2.7.0
firebase_dynamic_links: ^5.0.15
firebase_analytics: ^10.1.4
cloud_firestore: ^4.4.3
firebase_crashlytics: ^3.0.15

void init() async { final linkSubscription = FirebaseDynamicLinks.instance.onLink.listen( (linkData) async { handleLink(linkData); }, onError: (linkData) async { handleLink(linkData); }, ); final initialLink = await FirebaseDynamicLinks.instance.getInitialLink(); handleLink(initialLink); }

@mortenthansen
Copy link

Make sure you have GoogleService-Info.plist included in your iOS project. Old versions of flutterfire_cli did not generate this file. You may have to run flutterfire_cli again to do so.

@ifk-tiger
Copy link

Make sure you have GoogleService-Info.plist included in your iOS project. Old versions of flutterfire_cli did not generate this file. You may have to run flutterfire_cli again to do so.

I have GoogleService-Info.plist. If I had problem related GoogleService-Info.plist, probably does not work also other Firebase/Firestore services. All of them works without problem currently.

@firebase firebase locked and limited conversation to collaborators Mar 31, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform: ios Issues / PRs which are specifically for iOS. plugin: dynamic_links type: bug Something isn't working
Projects
None yet