flutter_link_nav 3.0.0 copy "flutter_link_nav: ^3.0.0" to clipboard
flutter_link_nav: ^3.0.0 copied to clipboard

Combining Navigator with Deep Links (Android) and Universal Links (iOS) in Flutter

flutter_link_nav #

Combining Navigator with Deep Links (Android), Universal Links (iOS, macOS) in Flutter

How to config #

First, example config with schema example.vn: #

Android #

  1. Add the following to your AndroidManifest.xml file:
    <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="example.vn" />
    </intent-filter>

iOS, macOS #

  1. Add the following to your Info.plist file:
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>example.vn</string>
            </array>
        </dict>
    </array>
    <key>NSUserActivityTypes</key>
    <array>
        <string>NSUserActivityTypeBrowsingWeb</string>
    </array>

How to use #

  1. First example have 2 screens: MainScreen and DetailScreen.
    • In MainScreen, because I want every navigate to another screen after start from MainScreen to be handled by deep link, I will call DeepLinkHandler().init(context) in initState().
class MainScreen extends StatefulWidget {
  static const String routeName = "main_screen";
  ...
}

class _MainScreenState extends State<MainScreen> {
  @override
  void initState() {
    super.initState();
     /// option 1: use the default deep link handler
    DeepLinkHandler().init(context);
    /// option 2: use a custom deep link handler
    // DeepLinkHandler().init(context, customHandler: (context, uri) {
    //   // Custom deep link handling logic can be added here
    //   debugPrint('MainScreen Custom deep link handler: $uri');
    // });
  }
  ...
}

class DetailScreen extends StatelessWidget {
  static const String routeName = "detail_screen";
  ...
}
  1. Then, create implementation of AppRoutes:
class ExampleAppRoutes extends AppRoutes {
  static const String mainScreen = MainScreen.routeName;
  static const String detailScreen = DetailScreen.routeName;

  @override
  Map<String, RouteConfig> get routes => {
    mainScreen: RouteConfig(
      widgetRegister: (queryParams) => const MainScreen(),
    ),
    detailScreen: RouteConfig(
      widgetRegister: (queryParams) => const DetailScreen(),
    ),
    'sheet': RouteConfig(
      actionRegister: (query) async {
        await showDialog(
          context: globalNavigatorKey.currentContext!,
          builder: (context) => AlertDialog(
            title: const Text('Deep Link Detected'),
            content: Text(query['label'] ?? ''),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: const Text('OK'),
              ),
            ],
          ),
        );
      },
    ),
  };
}
  1. Finally, setup in main.dart:
final globalNavigatorKey = GlobalObjectKey<NavigatorState>('nav');
void main() {
  ExampleAppRoutes().registerRoutes();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: globalNavigatorKey,
      initialRoute: ExampleAppRoutes.mainScreen,
      onGenerateRoute: AppRoutes.generateRoute,
    );
  }
}

How to test #

  1. Navigate into app:
Navigator.pushNamed(context, [screen_name]);

example:
Navigator.pushNamed(context, ExampleAppRoutes.detailScreen);
  1. For Android, you can use the adb command to test deep links:
adb shell am start -W -a android.intent.action.VIEW -d [deeplink] [package_name]

# Example command to test deep link
adb shell am start -W -a android.intent.action.VIEW -d "example.vn/detail_screen" com.example.example

# With query params
adb shell am start -W -a android.intent.action.VIEW -d "example.vn/detail_screen?param1=value1&param2=value2" com.example.example
  1. For iOS, you can use the xcrun command to test universal links:
xcrun simctl openurl [device_id] [universal link]

# Example command to test universal link
xcrun simctl openurl 55331C47-EDBD-439A-B098-34A9382F3A83 "example.vn://detail_screen"

# With query params
xcrun simctl openurl 3ACB75D6-C7A4-4BDD-A6E4-AE17C8773949 example.vn://detail_screen?param1=value1&param2=value2
  1. For macOS, you can use the open command to test universal links:
open "example.vn://[route_name]"

open "example.vn://detail_screen"
# With query params
open "example.vn://detail_screen?param1=value1&param2=value2"
  1. Additional case:
# Don't use `routename` in actionRegister with Navigator
  Navigator.pushNamed(context, 'routeName')
# instead, use:
  AppRoutes.executeRouteAction('routeName', arguments: {...});

6
likes
160
points
377
downloads
screenshot

Publisher

unverified uploader

Weekly Downloads

Combining Navigator with Deep Links (Android) and Universal Links (iOS) in Flutter

Homepage
Repository (GitHub)
View/report issues

Topics

#deeplink #navigator #universal-links

Documentation

API reference

License

MIT (license)

Dependencies

app_links, flutter

More

Packages that depend on flutter_link_nav