Implementing Different Types of Deep Links (URL Schemes, Universal Links, App Links) in Flutter

Deep links are essential for creating a seamless user experience by allowing users to navigate directly to specific content within a mobile application from outside sources. In Flutter, implementing deep links can significantly enhance user engagement and navigation. There are three main types of deep links: URL Schemes, Universal Links (iOS), and App Links (Android). This post will guide you through implementing each type in a Flutter application.

What are Deep Links?

Deep links are hyperlinks that take users to a specific location within an app instead of just launching the app’s home screen. This can be used for onboarding, referrals, content sharing, and marketing campaigns, providing a more direct and engaging experience.

Why Implement Deep Links?

  • Enhanced User Experience: Direct users to relevant content within the app.
  • Improved Onboarding: Guide new users directly to specific features.
  • Marketing Campaigns: Track and optimize campaigns by directing users to specific promotions.
  • Content Sharing: Allow users to easily share content by directing others to it.

Types of Deep Links

  1. URL Schemes: A custom URL scheme registered by the app.
  2. Universal Links (iOS): Standard HTTP/HTTPS URLs that redirect to the app.
  3. App Links (Android): HTTP/HTTPS URLs that directly open the app without redirection.

1. URL Schemes

URL schemes are the oldest form of deep linking. They use a custom protocol (e.g., myapp://) to open an app.

Implementation Steps:

  1. Configure URL Scheme in Native Projects:
    • iOS: Open ios/Runner/Info.plist and add the following:
    • CFBundleURLTypes
      
        
          CFBundleURLSchemes
          
            myapp
          
          CFBundleURLName
          com.example.myapp
        
      
    • Android: Open android/app/src/main/AndroidManifest.xml and add the following inside the <activity> tag:
    • 
          
          
          
          
      
  2. Flutter Code to Handle the URL:
  3. Use the uni_links package to listen for incoming links.

    dependencies:
      uni_links: ^0.5.1

    Add this to your Flutter code:

    import 'package:flutter/material.dart';
    import 'package:uni_links/uni_links.dart';
    import 'dart:async';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      String? _latestLink = 'Unknown';
      StreamSubscription? _sub;
    
      @override
      void initState() {
        super.initState();
        _initDeepLinkHandling();
      }
    
      @override
      void dispose() {
        _sub?.cancel();
        super.dispose();
      }
    
      Future<void> _initDeepLinkHandling() async {
        _sub = uriLinkStream.listen((Uri? uri) {
          if (!mounted) return;
          print('Got Deep Link: $uri');
          _latestLink = uri?.toString() ?? 'Unknown';
          setState(() {});
        }, onError: (Object err) {
          if (!mounted) return;
          print('Got Deep Link Error: $err');
          _latestLink = 'Unknown';
          setState(() {});
        });
    
        // Check initial Uri if available
        final initialUri = await getInitialUri();
        if (initialUri != null) {
          print('Initial URI received $initialUri');
          _latestLink = initialUri.toString();
        } else {
          print('Null Received');
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Deep Link Example'),
            ),
            body: Center(
              child: Text('Latest Deep Link: $_latestLink'),
            ),
          ),
        );
      }
    }

Advantages:

  • Easy to implement.
  • Works on all devices.

Disadvantages:

  • Not secure: Another app can register the same scheme.
  • Requires app to be installed.

2. Universal Links (iOS)

Universal Links use standard HTTPS URLs that point to both a web page and your app. When a user opens the link, iOS checks if the app is installed and directly opens the app without showing any intermediary page.

Implementation Steps:

  1. Configure Associated Domains:
    • Add an Associated Domain to your app’s entitlements. Go to your Xcode project, select your target, and under “Signing & Capabilities,” add “+ Capability.”
    • Search for “Associated Domains” and add an entry for your domain: applinks:yourdomain.com
  2. Upload apple-app-site-association File:
    • Create a file named apple-app-site-association without any file extension.
    • Place it in the .well-known directory of your domain.
    • Here’s an example file content:
    • {
        "applinks": {
          "apps": [],
          "details": [
            {
              "appID": "YOUR_TEAM_ID.com.example.myapp",
              "paths": [ "*" ]
            }
          ]
        }
      }
    • Make sure your server serves this file with the MIME type application/json and without any redirects.
  3. Flutter Code:
  4. The same code from the URL Schemes example can be used. iOS will automatically direct the link to the app if installed.

Advantages:

  • More secure than URL Schemes.
  • Better user experience since no intermediate page is displayed.

Disadvantages:

  • Requires server configuration.
  • If the app is not installed, the user is directed to the website.

3. App Links (Android)

App Links are similar to Universal Links on iOS. They use standard HTTPS URLs to link directly to your app. Android verifies the link by checking a file on your website, ensuring only your app can handle links to your domain.

Implementation Steps:

  1. Configure Intent Filter in AndroidManifest.xml:
  2. Add the following intent filter to your app’s main activity in android/app/src/main/AndroidManifest.xml:

    
        
        
        
        
        
    

    Ensure android:autoVerify="true" is set. This tells Android to automatically verify the link.

  3. Upload assetlinks.json File:
    • Create a file named assetlinks.json.
    • Place it in the .well-known directory of your domain.
    • Here’s an example file content:
    • [
        {
          "relation": ["delegate_permission/common.handle_all_urls"],
          "target": {
            "namespace": "android_app",
            "package_name": "com.example.myapp",
            "sha256_cert_fingerprints":
            ["YOUR_SHA256_CERT_FINGERPRINT"]
          }
        }
      ]
    • Replace YOUR_SHA256_CERT_FINGERPRINT with your app’s SHA256 certificate fingerprint. You can obtain this using the following command:
    • keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
  4. Flutter Code:
  5. The same code from the URL Schemes example can be used. Android will automatically direct the link to the app if verified.

Advantages:

  • Most secure form of deep linking on Android.
  • Directly opens the app without intermediary pages.

Disadvantages:

  • Requires server configuration.
  • If the app is not installed, the user is directed to the website.

Best Practices for Implementing Deep Links

  • Handle All Possible States: Ensure your app can handle cases where the app is not installed, the link is invalid, or the user is not logged in.
  • Secure Deep Links: Verify incoming links to prevent malicious redirection.
  • Use Fallbacks: Provide alternative experiences when the app cannot handle the link (e.g., redirect to the website).
  • Test Thoroughly: Test all types of deep links on different devices and operating systems.

Conclusion

Implementing deep links in Flutter enhances user experience and app engagement. By supporting URL Schemes, Universal Links (iOS), and App Links (Android), you can provide a seamless navigation experience across different platforms. Follow the detailed steps and best practices outlined in this guide to integrate deep links effectively into your Flutter application.