Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement deep linking in flutter, with redirect to app store?

Is there a way to achieve deep linking in a flutter, so that if a user clicks on a link then they are redirected to a specific part of the app, given that the app is installed, but if it isn't, they are redirected to the respective app store, to install the application and then taken to that specific part?

While searching for a solution I came across this package called uni_links but I am not sure if it can fulfill this requirement.

like image 452
Ayush Shekhar Avatar asked Dec 29 '18 07:12

Ayush Shekhar


3 Answers

You can use Firebase dynamic links for this purpose:

https://firebase.google.com/docs/dynamic-links

There it says:

if a user opens a Dynamic Link on iOS or Android and doesn't have your app installed, the user can be prompted to install it; then, after installation, your app starts and can access the link.

You can find information on how to implement this with Flutter here:

https://pub.dev/packages/firebase_dynamic_links

I have tried it myself with Android and iOS and it worked fine. If the app is not installed, the Google Play store or Apple AppStore is opened. The user can tap "Install" and then "Open". Afterward your app is started and the dynamic link is sent to your app (on iOS via the clipboard) where you can access it as explained on the website above. I.e. right after the start of your app in the first initState method you can call

final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink();
final Uri deepLink = data?.link;

to get the deep link. However in my experience on iOS this is too early to retrieve the link. I got "null" when trying it. It seemed to take a moment. I then used a WidgetsBindingObserver and watched in the didChangeAppLifecycleState method for AppLifecycleState.resumed. There I called retrieveDynamicLink. Due to a permission request (if the user allows notifications) the method was called twice. The first time it returned null but when it was called the second time it returned the deep link. So my solution looks like this:

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _retrieveDynamicLink();
    }
  }

  /**
   * Laden des Deep Link nach der Installation.
   */
  Future<void> _retrieveDynamicLink() async {
    final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.retrieveDynamicLink();
    final Uri deepLink = data?.link;

    if (deepLink != null) {
        // Use the deepLink
        // ...
    }
}
like image 142
Dominique Avatar answered Sep 18 '22 02:09

Dominique


As of iOS 12 there is no way to have a direct application deep link that redirects to the app store if your application is not installed.

You can have a deep link to the app store or a deep link within your app using the meta tag apple-itunes-app on a website. But this only shows a small banner at the top of the page, and is not a true deep link.

One system that I haven't used before but might be worth checking out as well is branch.io. You might be able to achieve something like that with their system, but I'm not exactly sure how it works. It for sure is not native as part of iOS 12.

like image 23
Charlie Fish Avatar answered Sep 22 '22 02:09

Charlie Fish


I am answering late but it will might help to others.

We can use firebase dynamic links for deep linking in a flutter with firebase_dynamic_links plugin. Refer this link for full implementation steps and create and receive a link, https://medium.com/better-programming/deep-linking-in-flutter-with-firebase-dynamic-links-8a4b1981e1eb. Here is a sample code for receiving a link inside the app and open a specific screen.

class MainWidgetState extends State<MainWidget> {

  @override
  void initState() {
    super.initState();
    this.initDynamicLinks();
  }

  initDynamicLinks(BuildContext context) async {
    await Future.delayed(Duration(seconds: 3));
    var data = await FirebaseDynamicLinks.instance.getInitialLink();
    var deepLink = data?.link;
    final queryParams = deepLink.queryParameters;
    if (queryParams.length > 0) {
      var userName = queryParams['userId'];
      openSpecificScreen(userName);
    }
    FirebaseDynamicLinks.instance.onLink(onSuccess: (dynamicLink)
    async {
      var deepLink = dynamicLink?.link;
      final queryParams = deepLink.queryParameters;
      if (queryParams.length > 0) {
        var userName = queryParams['userId'];
        openSpecificScreen(userName);
      }
      debugPrint('DynamicLinks onLink $deepLink');
    }, onError: (e) async {
      debugPrint('DynamicLinks onError $e');
    });
  }

  openSpecificScreen(String userName){
    Navigator.of(context).pushNamed("routeFormScreen", arguments: {"name": userName});
  }
}
like image 35
Kinjal Avatar answered Sep 18 '22 02:09

Kinjal