This article by Jian Yue SimpRead transcoding, original address www.raywenderlich.com

Learn how to build a Flutter application to handle deep linking of mobile and Web applications.

Sometimes it’s just too much trouble for users to open your app and navigate to get a screen. Redirecting to a specific part of your application is a powerful marketing tool to promote user engagement. For example, generating a special QR code for a promotion and then having users scan the QR code to access specific products in your app is a cool and effective way to build interest in the product.

In the previous chapter, you learned how to use Navigator 2.0 to navigate your application declaratively by moving router widgets from screen to screen. Now you’ll learn more about using Navigator 2.0. Specifically, you’ll learn how to deeply link to the screen in your application and handle Web urls on the web.

For example, here’s what Fooderlich looks like in Chrome Web browser.

By the end of this chapter, you will know how.

  • Parse the URL string and query parameters.
  • Convert the URL to your app state.
  • Deep linking is supported on iOS and Android.
  • Support URL-driven navigation for the Flutter web application in the browser.

This chapter shows you how to support deep linking on three platforms: iOS, Android, and the Web. You will be able to direct the user to any screen of your choice.

Pay attention to. You need to install Chrome web browser to view Fooderlich to the page. If you don’t already have Chrome, you can get it from www.google.com/chrome/. The Flutter Web project can run on other browsers, but this chapter only covers testing and development on Chrome.

Understanding deep links

A deep link is a URL that navigates to a specific destination in your mobile application. You can think of a deep link as a URL you type into a web browser to get to a specific page of a site rather than the home page.

Deep linking facilitates user engagement and business marketing. For example, if you’re making a sale, you can direct users to specific product pages in your app instead of having them search around.

Imagine Fooderlich has its own website. When users browse the site, they find a recipe they want to cook. By using deep links, you can let users click on recipes, open the app directly on the grocery project screen, and immediately start adding ingredients to their shopping list. This saves them time and makes the application more enjoyable.

  • With deep linking, Fooderlich is more automated. It takes the user directly to the item’s screen, making it easier to create a new item.
  • Without deep links, it’s more manual. Users must launch the application, browse to the buy TAB, and click the **+** button before they can create a project. It takes three steps, not one, and probably a few headaches!

Types of deep links

There are three types of deep links.

  • The URI scheme. An application’s own URI scheme. fooderlich://raywenderlich.com/home Fooderlich is an example of the URI of the scheme. This form of deep linking only works after the user installs your application.
  • IOS General links. At the root of your web domain, you place a file pointing to a specific App ID to know whether to open your App or direct the user to the App Store. You must register that particular application ID with Apple to handle links from that domain.
  • Android app link. These are like iOS universal links, but for Android. Android app link The specific content of a link that takes the user directly to your app. They use HTTP URLs and are associated with a web site. For users who do not have your application installed, these links will go directly to your site content.

In this chapter, you will only look at URI plans. For more information on how to set up iOS universal links and Android app links, check out the following.

  • IOS General links. www.raywenderlich.com/6080-univer… .
  • Android app link. www.raywenderlich.com/18330247-de… .

Begin to use

Pay attention to. We recommend that you use the startup project in this chapter rather than continuing with the project in the previous chapter.

Open the startup project in Android Studio and run flutter Pub Get. Then, run the application on iOS or Android.

You’ll see that Fooderlich’s application displays the login screen.

Soon, you’ll be able to redirect users to different parts of your application. But first, take a moment to review the changes in your startup project since the previous chapter.

The project file

Before you delve into parsing urls, take a look at the new files in the startup project.

Screens folder

2. There is a change in lib/screens/.

  • profile_screen.dart. Handles two different cases when a user opens Raywenderlich.com.
    • If the user is on a phone, it opens the site in web view.
    • If the user is using a Web browser, it opens the site in a different TAB.

Model folder

There are two new additions in lib/ Models /.

  • App_cache. Dart. Helps to cache user information, such as the user’s login and onboarding status. It checks the cache to see if the user needs to log in or complete the onboarding process.
  • app_state_manager.dart: depends on theAppCacheTo check the user’s login and entry status. When the application callsinitializeApp(), it checks the application cache to update the corresponding state.

A new package

In Pubspec.yaml, there are two new packages.

Url_launcher. ^ 6.0.4
shared_preferences: ^ at 2.0.5
Copy the code

Here’s what each of them does.

  • Url_launcher. A cross-platform library that helps launch a URL.
  • shared_preferences: simple data that wraps platform-specific persistent storage.AppCacheUse this package to store user login and onboarding status.

The new Flutter Network project

The startup project includes a pre-built Flutter Web project.

Pay attention to. To speed things up, the Web project is already pre-built in your startup project. To learn how to create a Flutter web application, check it out. Flutter. Dev/docs/get – st… .

Set deep Links

In order to enable deep linking on iOS and Android, you must add some metadata tags to each platform.

Set up deep links on iOS

Open the ios/Runner/Info. The plist. You’ll see some new key-value pairs that enable deep linking on iOS.

<key>FlutterDeepLinkingEnabled</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
  <dict>
  <key>CFBundleTypeRole</key>
  <string>Editor</string>
  <key>CFBundleURLName</key>
  <string>raywenderlich.com</string>
  <key>CFBundleURLSchemes</key>
  <array>
  <string>fooderlich</string>
  </array>
  </dict>
</array>
Copy the code

CFBundleURLName is a unique URL that distinguishes your application from other applications that use the same scheme. Fooderlich is the name of the URL scheme you will use later.

Set up deep links on Android

Open the android/app/SRC/main/AndroidManifest. The XML. Here you’ll also find two new definitions in the tag.

<! -- Deep linking -->
<meta-data android: />
<intent-filter>
<action android: />
<category android: />
<category android: />
<data
  android:scheme="fooderlich"
  android:host="raywenderlich.com" />
</intent-filter>
Copy the code

Like iOS, you set the same values for Scheme and host.

When you create a deep link for Fooderlich, the custom URL scheme looks like this.

fooderlich://raywenderlich.com/<path>
Copy the code

Now, take a quick look at the URL path you will create.

Fooderlich’s path overview

You have a lot of options when it comes to which screen you can deeply link to Fooderlich. Here are all the possible paths you can redirect your users to.

Path: /

The application initializes and checks the application cache to see if the user has logged in and completed the onboarding guide.

  • / login. If the user has not logged in, the user is redirected to the login screen.
  • /onboarding: Redirects to the onboarding screen if the user has not completed the onboarding training.

Path: / home? tab=[index]

The /home path is redirected to the home screen only if the user has logged in and completed the onboarding training. It contains a query parameter, TAB, which points to a label index. As shown in the following screenshot, the label indexes are 0, 1, or 2.

Path: / profile

If the user has logged in and completed onboarding, /profile redirects to the profile screen.

Path: / item? id=[uuid]

/item redirects to the grocery store item screen. It contains a query parameter, ID. There are two scenarios.

  1. If query parameteridThere is a value that redirects to a specific item in the list.
  2. If there are no query parameters, it displays an empty project screen for the user to create a new project.

You can see the result in the middle screenshot below.

Pay attention to. Keep in mind that these URL paths are the same for mobile and web applications.

When you do deep linking on mobile, you will use the following URI scheme.

fooderlich://raywenderlich.com/ < path >.Copy the code

On the web, the URI scheme is the same as the URL of any Web browser.

http://localhost:60738/#/<path>
Copy the code

Before you start implementing deep linking, take a moment to quickly review Navigator 2.0.

Review the Navigator 2.0

In the previous chapter, you learned how to set up four components. RouterDelegate, Router, Navigator, and BackButtonDispatcher.

  • RouterDelegateResponsibilities include.
    • Use App State to create and configure the page list.
    • When the application is first started, the initial route is retrieved and set.
    • Listen for new intents when you display a new route.
    • Listen to the request of the pop-up route put forward by the operating system.BackButtonDispatcher.
  • RouterIs an extensionRouterDelegateWidgets. The router ensures that messages are delivered toRouterDelegate.
  • NavigatorOne is defined declarativelyThe stack of MaterialPage'. It also handles anyOnPopPage ‘events.
  • BackButtonDispatcher handles the pressing of the system back button for a particular platform. It listens for requests from the operating system and notifies the router representative to pop up a route.

The next two components you’ll look at are the RouteInformationProvider and the RouteInformationParser.

  • RouteInformationProvider. Provides routing information to the router. It notifies the router of the original route and notifies the router of the new intent. You don’t need to create this class; the default implementation is usually what you need.
  • RouteInformationParser. fromRouteInformationProviderGet the route string, then parse the URL string into a generic user-defined data type. This data type is a navigation configuration.

Deep links under the hood

To make deep linking work, you need to do two key things: convert urls to app state, and convert app state to urls. Next, you’ll see the details of both events.

Convert a URL to an application state

The first part of supporting deep linking is figuring out which state of the application corresponds to a particular URL. Here’s how it works.

  1. The user enters a new URL triggered by a deep link, or by changing the URL in the web browser’s address bar.
  2. inRouteInformationParser,parseRouteInformation()Converts the URL string to a user-defined data type. This is known asNavigational state. This data type includes path and query parameters. You will build this soon.
  3. The router then callssetNewRoutePath()Convert your navigation state to application state. It then uses the current application state to configure the navigator stack.

Converts application state to URL string

When a user clicks a button or the application state changes, you need to change the current URL. Here’s what happens when you set up your application to handle urls.

  1. Router callrouterDelegatethenotifyListeners()To let Flutter know that it needs to update the current URL.
  2. It USEScurrentConfiguration()Switch your application state back to the navigation state.
  3. restoreRouteInformation()Then convert your navigation state to a URL string. In the Flutter web application, this updates the URL bar address.

Pay attention to. As you recall, navigational state is just a user-defined data type. It converts a URL string to an appropriate data type. This object holds information about your navigation, including.

  • The path or location of the URL.
  • Query parameters.

In the next section, AppLink is the data type that encapsulates the URL string.

Enough theory. It’s time to start

Create a navigation state object

AppLink is the intermediary object between the URL string and the state of your application. The purpose of this class is to parse the navigation configuration in relation to the URL string.

In lib/navigation, create a new file called app_link.dart and add the following.

class AppLink {
  / / 1
  static const String kHomePath = '/home';
  static const String kOnboardingPath = '/onboarding';
  static const String kLoginPath = '/login';
  static const String kProfilePath = '/profile';
  static const String kItemPath = '/item';
	/ / 2
  static const String kTabParam = 'tab';
  static const String kIdParam = 'id';
	/ / 3
  String location;
  / / 4
  int currentTab;
  / / 5
  String itemId;
  / / 6
  AppLink({this.location, this.currentTab, this.itemId});

  // TODO: Add fromLocation

  // TODO: Add toLocation
}
Copy the code

AppLink is your navigational state object. Take the time to understand the attributes you are adding. In the code above, you.

  1. Create constants for each URL path.
  2. Create constants for each query parameter you will support.
  3. uselocationThe path to store the URL.
  4. usecurrentTabTo store the tags you want to redirect to the user.
  5. initemIdStore the ID of the project you want to view.
  6. Initialize the application link with the location and two query parameters.

Convert a URL string to an AppLink

AppLink is an object that helps store path information. It helps parse the URL string into the route and vice versa, converting the route information back into the URL string. It essentially encapsulates all the logic that converts a simple string to a state and returns it.

Next go to // TODO: add fromLocation and add the following.

static AppLink fromLocation(String location) {
  / / 1
  location = Uri.decodeFull(location);
  / / 2
  final uri = Uri.parse(location);
  final params = uri.queryParameters;
  / / 3
  void trySet(String key, void Function(String) setter) {
    if(params.containsKey(key)) setter? .call(params[key]); }/ / 4
  finallink = AppLink().. location = uri.path;/ / 5
  trySet(AppLink.kTabParam, (s) => link.currentTab = int.tryParse(s));
  trySet(AppLink.kIdParam, (s) => link.itemId = s);
  / / 6
  return link;
}
Copy the code

FromLocation () converts a URL string to an AppLink.

  1. First, you need to decode the URL. The URL path often contains special characters, so you need to encode the URL path with **%. For example, you want to puthello! worldEncoded ashello%21world.
  2. Query parameter keys and key-value pairs for resolving URIs.
  3. trySet()Is an internal function that injects keys if the value is not empty.
  4. Create ‘AppLink’ with the current path.
  5. Inject the query parameters you found in the URL.
  6. returnAppLinkThe instance.

Convert AppLink to a URL string

The application also needs to do the reverse conversion, from AppLink to a simple string.

Go to // TODO: Add toLocation and Add the following.

String toLocation() {
  / / 1
  String addKeyValPair({String key, String value}) =>
      value == null ? ' ' : '${key}=$value& ';
	/ / 2
  switch (location) {
    / / 3
    case kLoginPath:
     return kLoginPath;
    / / 4
    case kOnboardingPath:
      return kOnboardingPath;
    / / 5
    case kProfilePath:
      return kProfilePath;
    / / 6
    case kItemPath:
      var loc = '$kItemPath? ';
      loc += addKeyValPair(key: kIdParam, value: itemId);
      return Uri.encodeFull(loc);
    / / 7
    default:
      var loc = '$kHomePath? ';
      loc += addKeyValPair(key: kTabParam, value: currentTab.toString());
      return Uri.encodeFull(loc); }}Copy the code

This converts the AppLink to a URI string. Here’s how it works. You are.

  1. Create an internal function that converts the key-value pairs of query parameters to string format.

  2. Traverse each defined path.

  3. If the path is kLoginPath, return the correct string path. / login.

  4. If the path is kOnboardingPath, return the correct string path. / onboarding.

  5. If the path is kProfilePath, return the correct string path. ` / profile ‘.

  6. If the path is kItemPath, return the correct string path. /item, if there are any arguments, append? Id = ${id}.

  7. If the path is invalid, the default path is /home. If the user selects a tag, append? TAB = ${tabIndex}.

Next, you will use RouteInformationParser to parse routing information into AppLink.

Create a route information parser

In the navigation directory, create a new file named app_route_parser.dart and add the following.

import 'package:flutter/material.dart';
import 'app_link.dart';

/ / 1
class AppRouteParser extends RouteInformationParser<AppLink> {
  / / 2
  @override
  Future<AppLink> parseRouteInformation(
      RouteInformation routeInformation) async {
    / / 3
    final link = AppLink.fromLocation(routeInformation.location);
    return link;
  }

  / / 4
  @override
  RouteInformation restoreRouteInformation(AppLink appLink) {
    / / 5
    final location = appLink.toLocation();
    / / 6
    returnRouteInformation(location: location); }}Copy the code

Here’s how the code works.

  1. AppRouteParserExtend theRouteInformationParser. Note that it requires a generic type. In this case, your type isAppLinkIt holds all the routing and navigation information.
  2. The first method you need to cover isparseRouteInformation(). The route information contains the URL string.
  3. Take the route information and build one from itAppLinkThe instance.
  4. The second way you need to cover it isrestoreRouteInformation().
  5. This function passes in aAppLink 'object. Do you requireAppLink ‘gives you back the URL string.
  6. You wrap it inRouteInformationTo pass it.

Connect the parser to the application router

Now that you’ve set up your RouteInformationParser, it’s time to connect it to your router delegate.

Open lib/main.dart, find // TODO: Initialize RouteInformationParser and change it to the following.

final routeParser = AppRouteParser();
Copy the code

Here, you initialize your application route resolver. If it doesn’t import automatically, make sure to add the following at the top.

import 'navigation/app_route_parser.dart';
Copy the code

Next, find // TODO. Replace it with Material. Router, and replace the return statement below it with the following.

return MaterialApp.router(
  theme: theme,
  title: 'Fooderlich',
  backButtonDispatcher: RootBackButtonDispatcher(),
  / / 1
  routeInformationParser: routeParser,
  / / 2
  routerDelegate: _appRouter,
);
Copy the code

You have created a MaterialApp that initializes an internal router. Here’s what it does.

  1. Set up therouteParser. Remember, the job of the routing information parser is to convert application state into URL strings.
  2. routerDelegateHelps build a stack of pages that represent the state of your application.

At this point, you might see some errors in the emulator. You’ll fix them in no time.

Convert a URL to an application state

When a user enters a new URL on a web page or triggers a deep link on a mobile device, RouteInformationProvider notifys RouteInformationParser of a new route, as shown in the figure below.

The following is the process from the URL to the application state.

  1. The user enters a new URL in the address bar of the Web browser.
  2. RouteInformationParserParse the new route into your navigational state, i.eAppLinkAn instance of.
  3. Based on the navigation state,RouterDelegateUpdate the application state to reflect the new changes.

Configuration navigation

Quick theory test. Where is the logic to map a particular URL path to a particular screen? It’s in setNewRoutePath()!

Open lib/navigation/app_router.dart and find // TODO: Add

and replace it and the space before it with the following.

<AppLink>
Copy the code

Remember, AppLink encapsulates all the routing information. The code above sets the User defined data type for the RouterDelegate to AppLink.

If you haven’t already added an import at the top, add the following.

import 'app_link.dart';
Copy the code

Next, find // TODO: Replace setNewRoutePath with the comments and code below.

/ / 1
@override
Future<void> setNewRoutePath(AppLink newLink) async {
  / / 2
  switch (newLink.location) {
    / / 3
    case AppLink.kProfilePath:
      profileManager.tapOnProfile(true);
      break;
    / / 4
    case AppLink.kItemPath:
      / / 5
      if(newLink.itemId ! =null) {
        groceryManager.setSelectedGroceryItem(newLink.itemId);
      } else {
        / / 6
        groceryManager.createNewItem();
      }
      / / 7
      profileManager.tapOnProfile(false);
      break;
    / / 8
    case AppLink.kHomePath:
      / / 9
      appStateManager.goToTab(newLink.currentTab ?? 0);
      / / 10
      profileManager.tapOnProfile(false);
      groceryManager.groceryItemTapped(null);
      break;
    / / 11
    default:
      break; }}Copy the code

Here’s how you can convert your app link to app state.

  1. Call when a new route is pushedsetNewRoutePath(). It passes an ‘AppLink’. This is your navigation configuration.
  2. Use a ‘switch’ to check each position.
  3. If the new position is/profileThe Profile screen is displayed.
  4. Check that the new location is valid/itemAt the beginning.
  5. ifitemIdNot empty, sets the selected grocery item and displays the grocery item screen.
  6. ifitemIdEmpty, showing an empty grocery item screen.
  7. Hide the introduction screen.
  8. If the new position is/home.
  9. Sets the currently selected label.
  10. Make sure the profile screen and grocery store item screen are hidden.
  11. If the location doesn’t exist, do nothing.

Convert the state of the application to a URL

At this point, you have converted a URL to an application state. Next, you need to do the opposite. When the user clicks a button or navigates to another screen, you need to convert the application state back to a URL string. For web applications, this synchronizes the browser’s address bar.

  1. When a user presses a button or changes a state,notifyListeners()It will start.
  2. RouteInformationParserThe current navigation configuration is required, so you must transition your application state toAppLink.
  3. RouteInformationParserAnd then callrestoreRouteInformationAnd will beAppLinkConvert to a URL string.

Dart again in lib/navigation/app_router.dart, find //TODO: Convert app state to applink and replace it with the following.

AppLink getCurrentPath() {
  / / 1
  if(! appStateManager.isLoggedIn) {return AppLink(location: AppLink.kLoginPath);
  / / 2
  } else if(! appStateManager.isOnboardingComplete) {return AppLink(location: AppLink.kOnboardingPath);
  / / 3
  } else if (profileManager.didSelectUser) {
    return AppLink(location: AppLink.kProfilePath);
  / / 4
  } else if (groceryManager.isCreatingNewItem) {
    return AppLink(location: AppLink.kItemPath);
  / / 5
  } else if(groceryManager.selectedGroceryItem ! =null) {
    final id = groceryManager.selectedGroceryItem.id;
    return AppLink(location: AppLink.kItemPath, itemId: id);
  / / 6
  } else {
    returnAppLink( location: AppLink.kHomePath, currentTab: appStateManager.getSelectedTab); }}Copy the code

This is a helper function that converts the application state into an AppLink object. Here’s how it works.

  1. If the user has not logged in, return to the application link with the login path.
  2. If the user has not completed the orientation, return to the application link with the orientation path.
  3. If the user clicks on the profile, the application link is returned with the profile path.
  4. If the user clicks the + button to create a new grocery project, the app link is returned with the project path.
  5. If the user selects an existing project, return an application link with the project path and the project ‘ID’.
  6. If none of the criteria are met, the main path with the selected label is returned by default.

Next, find // TODO: Apply Configuration Helper and replace it with the following.

@override
AppLink get currentConfiguration => getCurrentPath();
Copy the code

Accessing currentConfiguration calls the helper getCurrentPath(), which checks the application state and returns the correct application link configuration.

Congratulations, you’ve now set everything up and now you can see your work in action.

Testing deep linking

Next, you’ll test how deep linking works on iOS, Android, and the Web.

Test deep linking on iOS

In Android Studio, select an iOS device and press the Play button.

Once the emulator is running, log in and complete the machine as shown below.

Deep links to the home screen

Enter the following in your terminal.

xcrun simctl openurl booted 'fooderlich://raywenderlich.com/home?tab=1'
Copy the code

In the emulator, this automatically switches to Fooderlich’s second TAB, as shown below.

Deep links to the introduction screen

Next, run the following command.

xcrun simctl openurl booted 'fooderlich://raywenderlich.com/profile'Copy the code

This opens the profile screen, as shown below.

Deep linking creates a new project

Next, run the following command.

xcrun simctl openurl booted 'fooderlich://raywenderlich.com/item'Copy the code

The grocery store item screen will now display.

With this model, you can create a path to any location in your application!

Reset the cache in the iOS simulator

Recall that the AppStateManager checks with AppCache to see if the user is logged in or on. If you want to reset the cache to see the login screen again, you have two options.

  1. Go to the profile view and click Logout. This invalidates the application’s cache.

  1. If you’re running on an iOS emulator, you can select ** to erase all content and Settings… ** to clear the cache.

Pay attention to. Any other apps you have on the emulator will also be deleted.

Test deep linking on Android

Stop running on iOS. Open Android Studio, select an Android device and click the Play button.

Once the emulator or device is running, log in and complete the on-machine process as shown below.

Deep links to the home screen

Enter the following in your terminal.

~/Library/Android/sdk/platform-tools/adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE
    -d 'fooderlich://raywenderlich.com/home?tab=1'
Copy the code

Pay attention to. If you get a similar message on your terminal. Warning: Activity did not start, intent has been delivered to the currently running topmost instance, please ignore it. This simply means that the application is already running.

The full PATH is listed to ensure that if you don’t have ADB in your $PATH, you can still execute this command. The \ at the end of each line is used to nicely format multiple lines of the script.

This command points to the second tag of Fooderlich, as shown below.

Deep links to the introduction screen

Next, run the following command.

~/Library/Android/sdk/platform-tools/adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE
    -d 'fooderlich://raywenderlich.com/profile'Copy the code

This brings up the profile screen, as shown below.

Deep links to creating new projects

Next, run the following command.

~/Library/Android/sdk/platform-tools/adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE
    -d 'fooderlich://raywenderlich.com/item'Copy the code

The Grocery Item screen appears, as shown below.

Reset the cache in Android

If you need to reset your user cache, here’s what to do.

  1. Long press the Fooderlich app icon, then click App Info.
  2. Next, click Store and Cache.
  3. Finally, click Clear cache. This will clear your cache.

Now, it’s time to test how Fooderlich handles urls on the network.

Run the network application

Stop running on Android. In Android Studio, select Chrome (Web) and click the Play button.

Pay attention to. Your data doesn’t last between app launches. This is because Flutter Web was developed to run in stealth mode.

If you build and publish your Flutter web application, it will work as expected. For more information on how to build a publication, see. Flutter. Dev/docs/deploy… .

Through the Fooderlich UI process, you will see that the web browser’s address bar has changed.

If you change the value of the TAB query parameter to 0, 1, or 2, the application will automatically switch to that TAB.

Next, notice that clicking the + button opens the grocery store item.

One cool thing to note is that the application stores a history of the entire browser.

Click the back and forward buttons and the application will restore that state! How cool is that? Another thing you can do is long press the back button to jump to a specific state in the browser’s history.

Congratulations on learning how to use deep links in your Flutter application!

The key point

  • The application notifies you when a new route is availableRouteInformationProvider.
  • The provider passes routing information toRouteInformationParserTo parse the URL string.
  • The parser converts the application state to and from the URL string.
  • AppLinkModel navigation state. It is a user-defined data type that encapsulates information about the URL string.
  • In development mode, Flutter web applications do not persist data between application startup. Web applications generated in publish mode will work on other browsers.

Where to go?

If you’re curious about how to remove the # symbol from urls in Web applications, check it out. Flutter. Dev/docs/develo… .

See how gSkinner’s Flutter – Folio app handles navigation. The idea for application linking came from this sample project. Check out their examples here. Github.com/gskinnerTea… .

You can see examples of two different types of web renderers here. Flutter. Dev/docs/develo… .

You learned how to extend Navigator 2.0 to support deep linking and syncing your Web browser’s URL bar. This helps drive users to specific destinations within your application, building better user engagement

Being able to manage your navigation state for multiple platforms is truly amazing!


www.deepl.com translation