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
- URL Schemes: A custom URL scheme registered by the app.
- Universal Links (iOS): Standard HTTP/HTTPS URLs that redirect to the app.
- 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:
- Configure URL Scheme in Native Projects:
- iOS: Open
ios/Runner/Info.plistand add the following: - Android: Open
android/app/src/main/AndroidManifest.xmland add the following inside the<activity>tag: - Flutter Code to Handle the URL:
CFBundleURLTypes
CFBundleURLSchemes
myapp
CFBundleURLName
com.example.myapp
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:
- 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 - Upload
apple-app-site-associationFile: - Create a file named
apple-app-site-associationwithout any file extension. - Place it in the
.well-knowndirectory of your domain. - Here’s an example file content:
- Make sure your server serves this file with the MIME type
application/jsonand without any redirects. - Flutter Code:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "YOUR_TEAM_ID.com.example.myapp",
"paths": [ "*" ]
}
]
}
}
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:
- Configure Intent Filter in
AndroidManifest.xml: - Upload
assetlinks.jsonFile: - Create a file named
assetlinks.json. - Place it in the
.well-knowndirectory of your domain. - Here’s an example file content:
- Replace
YOUR_SHA256_CERT_FINGERPRINTwith your app’s SHA256 certificate fingerprint. You can obtain this using the following command: - Flutter Code:
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.
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.myapp",
"sha256_cert_fingerprints":
["YOUR_SHA256_CERT_FINGERPRINT"]
}
}
]
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
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.