DeepLynks

DeepLynks (now URLynk) is a Flutter package for deep linking. It opens the app directly if it's installed, or redirects to the store for download if not, preserving the link context through installation.

Features

  • Quick Integration: Minimal setup required to get started.
  • Platform Support: Supports Android App Links and iOS Universal Links.
  • Deferred Linking: Seamlessly redirect users to the store for downloads and preserve link even after installation.
  • Optional account creation: Start creating unlimited deferred deep links for free — no account required.

🚀 New Feature: Branded Domains for Deep Links!
You can now use your own branded domain to generate deep links via our package (v2.0.0 onwards).
Enhance your brand visibility and user trust with custom domain support!

🌐 Visit URLynk

Installation

  1. Add this package to your pubspec.yaml:

    dependencies:
      deeplynks: <latest_version>
    
  2. Run flutter pub get to install the package.

Platform Setup

Android

  1. Open android/app/src/main/AndroidManifest.xml.
  2. Add the following <meta-data> tag and <intent-filter> inside the <activity> tag with .MainActivity.
    Replace <app_id> with the unique app ID generated during the first DeepLynks.init() call. (Check Usage section below.)
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />

  <data android:scheme="http" android:host="urlynk.in" android:pathPrefix="/<app_id>/" />
  <data android:scheme="https" android:host="urlynk.in" android:pathPrefix="/<app_id>/" />

  <!-- If you have created links using older versions (below v3.0.0) -->
  <data android:scheme="http" android:host="deeplynks.web.app" android:pathPrefix="/<app_id>/" />
  <data android:scheme="https" android:host="deeplynks.web.app" android:pathPrefix="/<app_id>/" />
  <!-- End -->
</intent-filter>
  1. Update MainActivity.kt to handle deep links:
import android.net.Uri
import android.os.Bundle
import android.content.Intent
import io.flutter.plugin.common.MethodChannel
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
    private val CHANNEL = "app.web.deeplynks"
    private var initialLink: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        intent?.let {
            if (Intent.ACTION_VIEW == it.action) {
                initialLink = it.data.toString()
            }
        }
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "getInitialLink") {
                result.success(initialLink)
                initialLink = null
            } else {
                result.notImplemented()
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        intent.data?.let {
            flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger ->
                MethodChannel(messenger, CHANNEL).invokeMethod("onLink", it.toString())
            }
        }
    }
}
  1. Test on Emulator
  • Run the app on emulator.

  • Execute this command on the terminal.

adb shell am start -a android.intent.action.VIEW -d "<created_deep_link>" <application_id>
  • If successful, the app will launch & Deeplynks().stream will receive the link data.

iOS

1. Add FlutterDeepLinkingEnabled Key in Info.plist

<key>FlutterDeepLinkingEnabled</key>
<true/>

2. Add Associated Domains

  1. Open the Runner.xcworkspace file in Xcode.
  2. Select the top-level Runner project in the Navigator.
  3. Go to the Signing & Capabilities tab.
  4. Click the + Capability button.
  5. Select Associated Domains.
  6. In the Associated Domains section, click the + button.
  7. Add this domain: applinks:urlynk.in.
  8. If you have created links using older versions (below v3.0.0), add this domain also: applinks:deeplynks.web.app

3. Update AppDelegate.swift

Modify AppDelegate.swift to handle incoming deep links:

import UIKit
import Flutter

@main
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    // TODO: ADD THIS METHOD
    override func application(
        _ application: UIApplication,
        continue userActivity: NSUserActivity,
        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
    ) -> Bool {
        if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
           let url = userActivity.webpageURL,
           let flutterViewController = window?.rootViewController as? FlutterViewController {
            let channel = FlutterMethodChannel(name: "app.web.deeplynks", binaryMessenger: flutterViewController.binaryMessenger)
            channel.invokeMethod("onLink", arguments: url.absoluteString)
        }
        return true;
    }
}

4. Test on Simulator

  1. Run the app on simulator.
  2. Close the app.
  3. Run this command on the terminal.
xcrun simctl openurl booted <created_deep_link>
  1. If successful, the app will launch & Deeplynks().stream will receive the link data.

Usage

1. Initialize DeepLynks

Initialize the service at the start of your app. This generates a unique app ID that persists unless the application ID or bundle ID changes.

final appId = await Deeplynks().init(
  context: context,
  metaData: MetaInfo(
    name: 'Deeplynks Demo',
    description: 'This app is a working demo for showcasing Deeplynks features',
  ),
  androidInfo: AndroidInfo(
    sha256: [],
    applicationId: 'com.example.deeplynks',
  ),
  iosInfo: IOSInfo(
    teamId: '',
    appStoreURL: '',
    bundleId: 'com.example.deeplynks',
  ),
);
print(appId);

Arguments

Argument Type Description
context BuildContext The build context.
metaData MetaInfo App meta data. Used for link preview.
metaData.name String App name / title for link preview.
metaData.description String App description for link preview.
metaData.imageURL String Image for link preview, typically an App Logo.
androidInfo AndroidInfo Android-specific configuration.
androidInfo.sha256 List<String> List of release SHA-256 keys
androidInfo.applicationId String The application ID (package name) of your app.
iosInfo IOSInfo iOS-specific configuration.
iosInfo.teamId String Your Apple Developer Team ID.
iosInfo.appStoreURL String The App Store download URL for your app.
iosInfo.bundleId String The bundle ID of your app.
Deeplynks().stream.listen((data) {
    print(data);
});

Generate a deep link with your custom data (string format), which can include absolute URLs, relative URLs, query parameters, JSON objects, plain text, or any other format you want to retrieve later.

final link = await Deeplynks().createLink(jsonEncode({
  'referredBy': '12345',
  'referralCode': 'WELCOME50',
}));
print('Generated link: $link');

Additional information

Think you've found a bug, or would like to see a new feature? We'd love to hear about it! Visit the Issues section of the git repository.