Connecting the Dots: Exploring Flutter Deep-linking for Seamless User Experiences without Firebase.
Tags: flutter, webdev, firebase, beginners
Published: 2023-06-25 16:14:58

Welcome, fellow Flutter enthusiasts, to a whimsical world where widgets dance, hot reloads rule, and bugs tremble in fear of the mighty Flutter framework! Prepare yourself for a journey through the land of code and laughter as we unravel the hilarious side of Flutter development. So put on your debugging cape, grab a cup of virtual coffee, and get ready to flutter your way through this delightful adventure!.

We are about to embark on a journey to learn and implement Deep-linking in Flutter. But before we set sail, let's take a moment to review the basics. 

## What is Deep-linking?

Let's face it: humans are inherently lazy creatures. We want everything instantly, at the snap of our fingers, or rather, the tap of our screens. When we stumble upon an intriguing post or a captivating cat video on social media, the last thing we want is to be redirected to some random website in a browser. Deep linking swoops in to save the day, allowing us to seamlessly transition from our social media feeds to the juicy content we crave, all within the confines of our favorite apps.

![Deep-link](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jyj6w4ywbf82449r6hmt.jpg)


## Difference between App-link and Deep links?

![image](https://i.stack.imgur.com/pfauV.png)

[Read More](https://stackoverflow.com/questions/46169025/android-deep-links-and-app-links-confused)

> Note we will started with App Links and deep-links will be integrated in next part using firebase dynamic link.

## Getting Started with App links 

So basically we are going to use blog website with [react js](https://reactjs.com),hosted on [vercel](vercel.com) which will have following routes:

- '/': Home routes,basic dummy data.
- '/blogs': will list all the blogs from [dev.to/api/articles?username=name](https://dev.to/api/articles?username=djsmk123) 
   and on click will navigate to route '/blog/:id'.

- '/blog/:id': will show html content from the following API [https://dev.to/api/articles/id](https://dev.to/api/articles/1483531).

> This is completely web framework independent you can you use any web technology for website.

## Setup Website:

- You can create website own your own or just copy following content for example.

{% gist https://gist.github.com/Djsmk123/8025711179b62d36442e5b9f1c11c4f7 %}

- As mentioned above, App Links require digital assets links hosted on your website. 

[for more information](https://simonmarquis.github.io/Android-App-Linking/#app-links)

- Create `/.well-known/assetlinks.json` file and it should be accessible with following url `your-domain.com/.well-known/assetlinks.json`.  (for ReactJS add this file in `public` folder)

```
[
    {
        "relation": [
            "delegate_permission/common.handle_all_urls"
        ],
        "target": {
            "namespace": "android_app",
            "package_name": "package_name",
            "sha256_cert_fingerprints": [
               "SHA256KEY"
            ]
        }
    }
]

```

`package_name`: Add your flutter application package name.

`sha256_cert_fingerprints`: Add your SHA256 keys. [How to create?](https://stackoverflow.com/questions/42290681/android-studio-only-gives-me-sha1-i-need-sha256)

- Now make this file accessible

{% gist https://gist.github.com/Djsmk123/5be9cc60cfefd873aba4faeb9e738ed8 %}


- Deploy your project.


> We are done with website part.

## Setup Flutter Project

For flutter, we are not going to create project from starting, I am just going to share how link is handled.

- Add following dependencies:

```
dependencies:
  uni_links: ^0.5.1
```
- For Android

Uni Links supports two types of Android links: "App Links" and "Deep Links".

    - App Links only work with https scheme and require a specified host, plus a hosted file - assetlinks.json. Check the Guide links below.
    - Deep Links can have any custom scheme and do not require a host, nor a hosted file. The downside is that any app can claim a scheme + host combo, so make sure yours are as unique as possible, eg. HST0000001://host.com.

You need to declare at least one of the two intent filters in `android/app/src/main/AndroidManifest.xml`:

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

      <!-- Deep Links -->
      <intent-filter>
        <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 YOUR_SCHEME://YOUR_HOST -->
        <data
          android:scheme="[YOUR_SCHEME]"
          android:host="[YOUR_HOST]" />
      </intent-filter>

      <!-- 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>
```
Note: The `android:host` attribute is optional for Deep Links.


- For iOS: It requires valid apple associated domain, you can refer to this for [iOS](https://pub.dev/packages/uni_links).



## Lets Dive into App Link

if you are using on generated routes which match/exact same as link shared then you do not need to handle Link, it will automatically redirect you to received `route`. but if you are not using or want to handle link manually then we have 

- `getInitialLink()`: 
Returns the link that the app was started with, if any.

You should handle this very early in your app's life and handle it only once.

```
import 'dart:async';
import 'dart:io';

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

// ...

  Future<void> initUniLinks() async {
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      final initialLink = await getInitialLink();
      // Parse the link and warn the user, if it is not correct,
      // but keep in mind it could be `null`.
    } on PlatformException {
      // Handle exception by warning the user their action did not succeed
      // return?
    }
  }

// ...
```

- Listen for links: 

```

import 'dart:async';
import 'dart:io';

import 'package:uni_links/uni_links.dart';

// ...

  StreamSubscription _sub;

  Future<void> initUniLinks() async {
    // ... check initialLink

    // Attach a listener to the stream
    _sub = linkStream.listen((String? link) {
      // Parse the link and warn the user, if it is not correct
    }, onError: (err) {
      // Handle exception by warning the user their action did not succeed
    });

    // NOTE: Don't forget to call _sub.cancel() in dispose()
  }

// ...
```

## Testing Your Deep Links

- Testing for Android

Use the ADB tool to send test deep-links to your app and verify that they open the correct content.

```
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://host/path/subpath"'
```
- Testing for iOS

Use Xcode to simulate test deep-links and verify that they open the correct content.

```
/usr/bin/xcrun simctl openurl booted "unilinks://host/path/subpath"
```

## Let's Look into Sample Project:

- Using Material `onGeneratedRoutes` in Flutter as follow:

{% gist https://gist.github.com/Djsmk123/9ed91ba87f7cc85dfba5320c836d418b %}

- Link Share: Using `share_plus` package to share the link.

```
 onPressed: () {
                Share.share(
                    'check out my blog "https://blogs-deeplink-example.vercel.app/blog/${blog?.id}');
              },

```

- Link Handling or listening for AppLinks:

{% gist https://gist.github.com/Djsmk123/c1cbdb25ce8c0f6d6360bb7a386aa3d8  %}


## OUTPUT

- **React Website**:


![web1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j75dlu8jetaurdf97488.png)

![web2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbly64e7z1kvpe1zg2ts.png)


![web3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oeozkyspjx46j1szblsz.png)

- **Flutter Application**: 



![output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zyxtqxtfh7467fyfhhu5.gif)


PART 2 Soon !!!!!


## Source code : 
[Github Repo](https://github.com/Djsmk123/flutter_deeplinking_example)

## Follow me on 

- [Twitter](https://twitter.com/smk_winner)

- [Instagram](https://www.instagram.com/smkwinner/)

- [Github](https://www.github.com/djsmk123)

- [linkedin](https://www.linkedin.com/in/md-mobin-bb928820b/)

- [dev.to](https://dev.to/djsmk123)

- [Medium](https://medium.com/@djsmk123)