Flutter Universal Links: Bridging App and Web Navigation

Mohamed Abdo Elnashar
Flutter UAE
Published in
5 min readApr 29, 2023

Universal links are a powerful tool for mobile app developers that allows users to seamlessly navigate between web content and native mobile apps. In Flutter, universal links can be implemented using the Flutter plugins for handling deep links, and they are an essential part of any app that requires a smooth transition between web and app content. In this article, we will dive into the concept of universal links, explore how they can be implemented in Flutter, and look at some best practices for using them.

What are Universal Links?

Universal links are a feature that was introduced by Apple in iOS 9 and allows developers to associate their website with their native mobile app. When a user clicks on a universal link, it opens the associated app directly instead of loading the website in a web browser. This seamless experience makes engaging with app content easier and provides a more native experience.

How does Universal Links work?

Universal links work by associating a unique URL scheme with your app. When a user clicks on a Universal link, their device checks to see if the corresponding app is installed. If it is, the app is opened and the user is taken directly to the content they clicked on. If the app is not installed, the user is directed to the appropriate website.

Universal links use a specific URL scheme that starts with https:// and contains a unique domain name associated with the app. For example, if your app is called MyApp the universal link might be https://myapp.com.

Implementing Universal Links in Flutter

To implement universal links in Flutter, you will need to use the Flutter plugins for handling deep links. These plugins allow your app to receive and handle deep links, including universal links.

In Android

we need to declare permissions for deep linking in the AndroidManifest.xml file. The process of declaring deep link permissions in Android involves adding an intent filter for the specific URI pattern that you want to handle.

<manifest ...>
<!-- ... other tags -->
<application ...>
<activity ...>
<!-- ... other tags -->

<!-- App Links -->
<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" />
<!-- Accepts URIs that begin with https://YOUR_HOST -->
<data
android:scheme="https"
android:host="[YOUR_HOST]" />
</intent-filter>
</activity>
</application>
</manifest>

in iOS

Universal Links are used instead of Custom URL schemes. Developers need to create a apple-app-site association file and host it on a web server. This file associates your app with your website and allows your app to handle Universal Links.

To set up Universal Links in iOS, follow these steps:

  1. First, enable Associated Domains in your app’s entitlements file. To do this, go to your app target’s Signing & Capabilities tab, click the +button, and select Associated Domains.
  2. Add your domain to the list of Associated Domains. This tells iOS that your app is allowed to handle links that match the domain.
  3. Next, create a file named apple-app-site association at the root of your web server. This file is used by iOS to discover and verify your app’s support for Universal Links.
  4. The apple-app-site association file must be in JSON format and include information about your app’s bundle ID, the domain(s) it supports, and any URL schemes it handles. Here’s an example:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "your.app.bundle.identifier",
"paths": [ "/path1/*", "/path2/*" ]
}
]
}
}
  • appID: The URL identifier for your app.
  • paths: An array of strings that specify the paths on your website that should open your app.

In this code, replace your.app.bundle.identifier with the actual bundle identifier for your app. This file needs to be hosted on a web server that is accessible from the internet.

Next, upload the apple-app-site association file to the root of your domain. You can test your Universal Links by visiting a URL that matches the domains and paths you specified in the apple-app-site association file.

For Custom URL schemes you need to declare the scheme in ios/Runner/Info.plist (or through Xcode's Target Info editor, under URL Types)

<dict>
<!-- ... other tags -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>[ANY_URL_NAME]</string>
<key>CFBundleURLSchemes</key>
<array>
<string>[YOUR_SCHEME]</string>
</array>
</dict>
</array>
<!-- ... other tags -->
</dict>

in flutter

Finally, you need to handle the Universal link in your Flutter app. To do this, you can use the uni_links package. This package provides a simple API for handling Universal links in Flutter.

Here is an example of how to use the uni_links package:

import 'package:uni_links/uni_links.dart';
import 'package:flutter/services.dart' show PlatformException;

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
StreamSubscription _sub;
@override
initState() {
super.initState();
initPlatformState();
}
@override
dispose() {
_sub.cancel();
super.dispose();
}
initPlatformState() async {
_sub = getLinksStream().listen((String link) {
// Handle the link here
}, onError: (err) {
// Handle errors here
});
// Check if the app was opened from a Universal link
try {
String initialLink = await getInitialLink();
if (initialLink != null) {
// Handle the link here
}
} on PlatformException {
// Handle errors here
}
}
// ...
}

In this code, the initPlatformState() function sets up a stream subscription to listen for Universal links. The getLinksStream() function returns a stream of Universal links that the app can handle. The getInitialLink() function checks if the app was opened from a Universal link when it first launched.

Best Practices for Using Universal Links in Flutter

Here are some best practices for using universal links in your Flutter app:

  1. Test your universal links thoroughly. Make sure they work correctly on both iOS and Android devices and in different scenarios, such as when the app is not installed or when the user is logged out.
  2. Provide clear feedback to the user when they click on a universal link. If the app is not installed, provide a clear message and a call to action to download the app.
  3. Use deep links sparingly. While universal links are a great tool, overusing deep links can overwhelm users and make the app feel less native.
  4. Don’t forget about fallback options. If a universal link fails to open the app, provide a fallback option that loads the website in a web browser.

Conclusion

Universal links are a powerful tool for creating a seamless user experience between web and app content. In Flutter, implementing universal links is easy using the Flutter plugins for handling deep links. By following best practices for using universal links, you can create a more engaging and native app experience for your users.

I hope you all liked this blog and it helped you start with Flutter! Don’t forget to smash that clap button and leave a comment down below.

If you liked this article make sure to 👏 it below, and connect with me on Portfolio, Github, and LinkedIn.

Meet you at the next one.

--

--

Mohamed Abdo Elnashar
Flutter UAE

Senior Flutter Developer, and I study a master of computer science in the faculty of computer & information sciences at Mansoura university