# Flutter Deep Linking with GoRouter

Deep linking allows apps to be opened with a specific screen by following a URL or URI link. Using **GoRouter** in Flutter, we can manage deep links effectively across iOS, Android, and Web platforms.

#### Prerequisites

* **Flutter** installed and set up.
* **GoRouter** dependency added to `pubspec.yaml`.
* Basic knowledge of Flutter navigation and routing.

#### Step 1: Install GoRouter

Add GoRouter to your `pubspec.yaml`:

```yaml
dependencies:
  flutter:
    sdk: flutter
  go_router: ^7.0.0  # Ensure you have the latest version
```

Run `flutter pub get` to install the dependencies.

#### Step 2: Set Up Routing with GoRouter

Create a `router.dart` file to define routes and initialize GoRouter.

```dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

final GoRouter router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      name: 'home',
      builder: (context, state) => HomeScreen(),
    ),
    GoRoute(
      path: '/product/:id',
      name: 'product',
      builder: (context, state) {
        final productId = state.params['id']!;
        return ProductScreen(id: productId);
      },
    ),
    GoRoute(
      path: '/settings',
      name: 'settings',
      builder: (context, state) => SettingsScreen(),
    ),
  ],
);
```

In this example, we have three routes:

* `/` ➔ Home screen.
* `/product/:id` ➔ Product screen with a dynamic `id` parameter.
* `/settings` ➔ Settings screen.

#### Step 3: Integrate GoRouter into Your App

Update `main.dart` to integrate GoRouter as the router delegate.

```dart
import 'package:flutter/material.dart';
import 'router.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: router.routerDelegate,
      routeInformationParser: router.routeInformationParser,
      routeInformationProvider: router.routeInformationProvider,
      title: 'Flutter Deep Linking Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
    );
  }
}
```

Now that GoRouter is set up, let's configure deep linking for iOS, Android, and Web.

***

### Deep Linking Configuration

#### Android

1. **Open `AndroidManifest.xml`:**\
   Add an `intent-filter` within your main `<activity>` tag to specify which URLs should open your app.

```xml
<activity
  android:name=".MainActivity"
  android:launchMode="singleTask"
  android:theme="@style/LaunchTheme"
  android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|density|layoutDirection|fontScale|screenHeightDp|screenWidthDp|uiMode"
  android:hardwareAccelerated="true"
  android:windowSoftInputMode="adjustResize">

  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <!-- URI scheme and host for deep linking -->
    <data android:scheme="https" android:host="www.example.com" />
    <data android:scheme="myapp" android:host="example" />
  </intent-filter>
</activity>
```

2. **Explanation:**
   * `scheme`: `https` for web links and `myapp` for custom scheme.
   * `host`: `www.example.com` (or your custom domain).
   * With this configuration, links like `https://www.example.com/product/1` or `myapp://example/product/1` will open the app to the appropriate screen.

***

#### iOS

1. **Add URL Types in Xcode:**
   * Open `ios/Runner.xcworkspace` in Xcode.
   * Select the **Runner** project > **Info** tab.
   * Under **URL Types**, click the `+` button.
     * Enter a unique identifier (like `com.example.app`).
     * Add the URL scheme you want to support, like `myapp`.
2. **Edit `Info.plist` for Universal Links:**

   ```xml
   <dict>
       ...
       <key>CFBundleURLTypes</key>
       <array>
           <dict>
               <key>CFBundleURLName</key>
               <string>com.example.app</string>
               <key>CFBundleURLSchemes</key>
               <array>
                   <string>myapp</string>
               </array>
           </dict>
       </array>
       <key>NSAppTransportSecurity</key>
       <dict>
           <key>NSAllowsArbitraryLoads</key>
           <true/>
       </dict>
   </dict>
   ```

   * Replace `com.example.app` with your app’s identifier.
   * Add your scheme (e.g., `myapp`) to `CFBundleURLSchemes`.
3. **Associated Domains for Universal Links:**
   * Go to the **Signing & Capabilities** tab.
   * Add **Associated Domains** and include `applinks:www.example.com`.

***

#### Web

1. **Run Flutter Web App:**
   * Use `flutter run -d chrome` to run the app as a web app.
2. **Configure Routes for Web in GoRouter:**
   * GoRouter is already configured for web; URLs like `/product/1` or `/settings` will open the appropriate pages.
3. **Direct Web Links:**
   * You can directly link to your Flutter web app using URLs like `https://www.example.com/#/product/1`. Ensure GoRouter routes match web URLs.

***

### Testing Deep Links

* **Android:** Use `adb` to test deep links.

  ```bash
  adb shell am start -W -a android.intent.action.VIEW -d "https://www.example.com/product/1" com.example.app
  ```
* **iOS:** Use the Safari browser or Xcode's debugging tools to test universal links.
* **Web:** Open the link directly in a browser to test.

***

### Sample Code for Handling Deep Links in Screens

Here's how you might set up a Product screen to handle incoming IDs via GoRouter.

```dart
class ProductScreen extends StatelessWidget {
  final String id;

  ProductScreen({required this.id});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Product $id"),
      ),
      body: Center(
        child: Text("Details for Product $id"),
      ),
    );
  }
}
```

And in `router.dart`, ensure the dynamic `id` parameter is correctly passed:

```dart
GoRoute(
  path: '/product/:id',
  name: 'product',
  builder: (context, state) {
    final productId = state.params['id']!;
    return ProductScreen(id: productId);
  },
),
```

***

### Summary

By following this setup:

1. **Android** handles deep links with `intent-filter` in `AndroidManifest.xml`.
2. **iOS** uses `URL Types` and `Associated Domains` for universal and custom links.
3. **Web** leverages GoRouter’s support for handling web URLs directly.

With GoRouter, deep linking is efficiently managed, enabling smooth navigation and allowing external links to direct users to specific screens in the app.
