Charlemagne
Charlemagne

Reputation: 31

Flutter : My deeplink is always "/" in my deeplinkBuilder of AutoRoute library

I've been stuck for a few days on the subject of deeplinks on Flutter.

I use the Flutter "auto_route" library, which gives me direct access to deeplinks via its "deeplinkBuilder" in router.config().

After configuring the Android part (for testing purposes) and adding the intent-filter in the AndroidManifest.xml, each time a deeplink is opened, the deeplinkBuilder doesn't detect my link and tells me it's equal to "/".

Here my deeplink : scheme://main/dashboard

Here my MaterialApp.router :

return MaterialApp.router(
            routerConfig: _appRouter.config(
              deepLinkBuilder: (deepLink) {
                if (deepLink.path.contains('/main')) {
                  return deepLink;
                } else {
                  return DeepLink.defaultPath;
                }
              },
            ),
            title: 'App name',
            localizationsDelegates: const [
              AppLocalizations.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate,
            ],
            supportedLocales: const [
              Locale('fr', 'FR'),
            ],
            theme: AppTheme.lightThemeData,
            darkTheme: AppTheme.darkThemeData,
            themeMode: state.themeMode,
          );

Where deepLink.path is always as "/" instead of "/main/dashboard"

Also here my AndroidManifest.xml :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">

    <!-- Android 11+ -->
    <uses-feature android:name="android.hardware.camera" />
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data
                android:host="*"
                android:scheme="https" />
        </intent>
    </queries>

    <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
    <uses-permission android:name="android.permission.ACTION_MANAGE_WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:usesCleartextTraffic="true">
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:exported="true"
            android:hardwareAccelerated="true"
            android:launchMode="singleTask"
            android:networkSecurityConfig="@xml/network_security_config"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme"
            android:windowSoftInputMode="adjustResize">
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <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="${deeplinkScheme}" />
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
        <meta-data
            android:name="flutter_deeplinking_enabled"
            android:value="true" />
    </application>
</manifest>

Where "${deeplinkScheme}" is defined in build.gradle with the same scheme than my deeplink.

So the deeplink does open the application, but is never detected inside it.

Did I forget to initiate something?

How can I get my application to recognize my deeplink inside itself?

Little note:

I only need deeplink and not AppLink (Universal link). My deeplink is not an "http" link. Just a simple deeplink for mobile platform.

Also, I work on version auto_route: ^7.8.4

Any help is welcome.

Thanks in advance 🙂

What I tried too :

I tested on iOS by giving the scheme in the Info.plist file, the application can open it but doesn't detect the deeplink on opening either.

Upvotes: 3

Views: 1172

Answers (4)

You should Add a deeplink Handler in your router.config() by passing the deepLinkBuilder argument.

I think this is because auto_route routes you by directly to the DeepLink.default by default. This route corresponds to your initial route.

To customize the behavior of your deeplink builder you can add some checks before returning the link.

This is how you handle it.

 routerConfig: _router.config(
        placeholder: (context) => const Center(
          child: CupertinoActivityIndicator(),
        ),
        rebuildStackOnDeepLink: true,
        deepLinkBuilder: (link) {
          if (link.path.contains('invitation')) {
            final args = link.uri.queryParameters;
            final invitation = Invitation.fromMap(args, fromInvite: true);
            return DeepLink(
              [
                SignupRoute(invitation: invitation),
              ],
            );
          } else {
            return DeepLink.defaultPath;
          }
        },

      //deepLinkTransformer: (uri) {},
 ),

  • I think the logic here is quite easy to understand
  • It checks if the incoming link is from a certain path invitation
  • Then it gets the query params then return the DeepLink object. Note that this object takes a List<PageRouteInfo<dynamic>> (If you're familiar with auto_route, you understand this) that will be used to build the router stack.

Upvotes: 0

GullTee
GullTee

Reputation: 11

I also faced same issue, I fixed it with below code:

MaterialApp.router(
    debugShowCheckedModeBanner: false,
    theme: appThemeData[AppTheme.light],
    darkTheme: appThemeData[AppTheme.dark],
    themeMode: ThemeMode.system,
    routerConfig: router.config(
      deepLinkBuilder: (deepLink) {
        if (deepLink.uri.fragment.startsWith('/password-reset-form')) {
          return DeepLink.path(deepLink.uri.fragment);
        } else {
          return DeepLink.defaultPath;
        }
      },
      navigatorObservers: () => [
        locator<AppRouterObserver>(),
      ],
    ),
  ),

Concentrate the code for deepLinkBuilder.

Hope this fix your issue.

Upvotes: 0

Jacoo
Jacoo

Reputation: 178

I just had a very similar problem, for me it is because I use "FlutterFragmentActivity" inside MainActivity.kt instead of using "FlutterActivity".

I still need FlutterFragmentActivity so I'm looking for a solution, but that's what I found as my error

Upvotes: 0

Bharath
Bharath

Reputation: 1166

From the flutter docs

For Android, you'll need to modify your AndroidManifest.xml file. Add the following metadata inside the tag of your main activity:

<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />

Ref: Set up app links for Android - Flutter

For ios, to enable deep linking in your Flutter application, you need to add the following entry to your Info.plist file:

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

Ref: Set up universal links for iOS - flutter

Upvotes: 0

Related Questions