Navigating the World of Deep Linking: Our Dynamic Approach
Imagine building an app like Instagram, complete with fun features like status updates and reels. That's what I've been working on during my internship at Neosao.
But here's the challenge: we wanted people to easily share their reels & statuses on WhatsApp, Messenger, and other apps. It's an essential part of our app's experience.
Here's the twist: Firebase Dynamic Links, the tool we were using to make this happen, is deprecated.
In this blog, I'll take you through our journey of solving this challenge. It's a story of problem-solving and making our app better, and it's one I can't wait to share with you!
The Challenge: Sharing Reels and Statuses
Our journey into deep linking started with a crucial challenge: making it easy for users to share exciting reels and status updates with their friends. Here's what we wanted to achieve:
Sharing: Users should be able to tap a share button and send a simple text message with the link to their friends.
Opening the App: When friends click the link, it should take them straight to our app and show them the shared reel or status.
App Not Installed: But what if their device doesn't have our app? We needed a way to guide them to the App/Play Store for a quick download.
Creating Shareable Links: Building the Foundation
Our journey into dynamic and deep linking started with the foundation of creating shareable links. For the sake of privacy and security, let's understand that the base URL we used in our project can't be shared here, so we'll use "https://example.com" as a placeholder.
To make our app's content shareable, we extended this base URL with two key paths: "/status" and "/reel." These paths became the addresses where our status updates and reels would reside on the web. So, we had two constants: "https://example.com/status" and "https://example.com/reel."
But we weren't done yet. To ensure each shared link was unique and could lead to the right content, we introduced query parameters. Specifically, we added the "id" parameter. Now, our URLs looked like this: "https://example.com/status?id=" and "https://example.com/reel?id=".
These two URLs became constants within our app. When a user decided to share a status update or a reel, the app appended the corresponding "id" to the URL. For instance, if a user was watching a reel with an "id" of 87, sharing it would transform the URL into "https://example.com/reel?id=87."
With our shareable links in place, we were one step closer to enhancing our app's user experience. But the real magic was yet to come.
Handling Deep Linking: Making the Connection
With shareable dynamic links in place, we had achieved the first part of our mission. When a user clicked on these links, a simple web page opened up. However, our goal was to seamlessly transition users from the web page to our app.
To bridge this gap, we used custom URL schemes. Android apps can register custom URL schemes to allow them to be opened from web links. Here's how we set it up for Android:
Register a Custom URL Scheme in Your Android App:
In Android app's manifest file, we registered a custom URL scheme using the following code snippet:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="myapp"
android:host="example.com" /> <!-- Replace with your actual domain -->
</intent-filter>
Here's what this code does:
android:scheme="myapp"
: This specifies that our app should handle deep links with the "myapp" scheme.android:host="
example.com
"
: This specifies the host (domain) that our app should handle.
Now, let's jump back to the web side of things. To create a deep link, we declared "myapp" as the scheme and "example.com" as the host. So, our deep link looked like this: myapp://
example.com/reel?id=87
.
Crucially, the scheme and host name declared in the manifest had to match exactly what we used in the deep link.
But how did we open the app? We used a simple JavaScript code snippet:
window.location.href = 'myapp://example.com/reel?id=87';
This code triggered the app to open when a user clicked the link.
Now, you might wonder how we got the "id" in the deep link. Our fantastic Web lead Abhishek came to the rescue. They devised a clever logic to extract the "id" query parameter from the URL and incorporate it into the deep link.
If you look our shareable link closely, you'll notice that we appended the "id" while sharing the link with others. For example, https://example.com/reel?id=87
. We simply took this "id" and added it to the deep link.
Cool, right? But we hadn't covered all scenarios yet. What if a user didn't have our app installed on their phone? No worries, we had a solution. We could detect the user's operating system and redirect them to the appropriate app store:
function openStore() {
if (/(android)/i.test(navigator.userAgent)) {
window.location.href = 'https://play.google.com/store/apps/details?id=com.example'; // Replace with your app's Play Store link
} else if (/(ipad|iphone|ipod)/i.test(navigator.userAgent)) {
window.location.href = 'https://apps.apple.com/us/app/your-app-name/idYOURAPPID'; // Replace with your app's App Store link
}
}
Handling Deep Linking Inside the App
With our web page now redirecting users to the app, the next piece of the puzzle was to handle these deep links within the app itself. This was the critical step to ensure that the shared content could be seamlessly accessed by our users.
For this task, we used a handy Flutter package called "uni_links." This package was a lifesaver as it helped us manage app and deep links.
The first step is to add this package in pubspec.yaml
file:
uni_links: ^0.5.1
Now, with the package in place, we were ready to put it to work. We began by incorporating it into our app's splash screen. Here's how it all came together:
import 'package:uni_links/uni_links.dart';
Future<void> _initUniLinks() async {
try {
final initialLink = await getInitialUri();
if (initialLink != null) {
_handleLink(initialLink);
print("App opened via deep link");
} else {
print("App opened manually");
}
} on PlatformException {
// Handle any exceptions here
}
}
In this code, we checked if the app was opened via a deep link or manually by a user. If it was indeed a deep link that brought the user in, we triggered the _handleLink
function.
Now, the heart of our deep linking strategy lay within the _handleLink
function. Here's how we extracted the "id" from the deep link:
void _handleLink(Uri uri) {
if (uri.host == 'example.com') {
final segments = uri.pathSegments;
if (segments[0] == 'status') {
// Extract the status id
final id = uri.queryParameters['id'];
// Handle it as needed for your app
} else if (segments[0] == 'reel') {
// Extract the reel id
final id = uri.queryParameters['id'];
// Handle it as needed for your app
} else {
// Handle other cases as per your app's requirements
}
}
}
In this function, we initially checked if the host of the incoming URI matched our domain. For our example, this meant checking if the host was 'example.com'.
Next, we extracted the path segments from the URI. For instance, if our URI was 'https://example.com/reel?id=87', uri.pathSegments
would return ['reel']
. We used these path segments to identify whether the link pointed to a status or a reel.
Finally, we accessed the "id" from the query parameters of the URI. This was the golden key that unlocked access to the specific content. With the "id" in hand, we could effortlessly direct the user to the appropriate screen within our app.
And just like that, our deep linking strategy was complete.
Thanks for Reading!
We hope you've enjoyed this journey into the world of deep linking and our unique approach to solving it. Our goal was to make sharing reels and statuses in our app effortless.
Stay connected, and happy exploring!
Subscribe to my newsletter
Read articles from Abhaysing Bhosale directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Abhaysing Bhosale
Abhaysing Bhosale
Hey, This is Abhay! ๐ ๐ฑ Android & Flutter Developer ๐ Crafting mobile magic with Kotlin & Dart ๐ Exploring the realms of Jetpack Compose & Compose Multiplatform ๐ Blogger in the making, sharing insights on tech ๐ Intern at Neosao Services, learning and growing ๐จโ๐ B.Tech Student