How Android Chromium Uses Intent URLs to Launch Native Apps

This article explains the mechanics of how the Chromium web browser on Android processes intent:// URLs to transition users from a web page into a native mobile application. It covers the structure of an intent URL, how Chromium intercepts and parses these links, the security policies enforced during navigation, and the fallback mechanisms used when a target application is not installed on the device.

The Anatomy of an Intent URL

Traditional custom URL schemes (such as myapp://path) fail with a broken page error if the target application is not installed on the user's device. To solve this, Chromium on Android supports the intent: scheme, which maps a web link directly to an Android Intent object.

A standard Android intent URL follows this structure:

intent://host/path#Intent;scheme=custom_scheme;package=com.example.app;S.browser_fallback_url=https%3A%2F%2Fexample.com;end
  • intent://host/path: The base URI data passed to the application.
  • scheme: The custom scheme the target app listens for in its manifest.
  • package: The exact Android package name of the target application.
  • S.browser_fallback_url: An URL-encoded web address to load if the app is missing.
  • end: Signifies the end of the intent parameters.

When a user clicks an intent:// link, Chromium does not make a network request. Instead, the navigation is intercepted by Chromium's internal ExternalNavigationHandler class. Before handing the request over to the Android operating system, Chromium enforces several strict security policies:

  • User Gesture Requirement: The navigation must be initiated by a direct user action, such as tapping a link. If a webpage attempts to trigger an intent:// URL automatically via JavaScript on page load, Chromium blocks the navigation to prevent malicious redirects.
  • Browsable Category Enforcement: Chromium automatically attaches the android.intent.category.BROWSABLE category to the intent. The target Android application must explicitly declare this category in its AndroidManifest.xml file, proving it is safe to be launched from a web browser.
  • Component Stripping: To prevent websites from accessing private, unexported activities inside an app, Chromium strips any explicit component or class names defined in the intent string.

Parsing and Querying the OS

Once the security checks pass, Chromium converts the raw URL string into a native Android Intent object by calling the Android system method Intent.parseUri(url, Intent.URI_INTENT_SCHEME).

Chromium then passes this Intent object to the Android PackageManager using queryIntentActivities(). This asks the operating system for a list of installed applications capable of handling the specific combination of scheme, host, path, and package name defined in the link.

Execution and Fallback Handling

Based on the response from the Android PackageManager, Chromium executes one of three outcomes:

  1. Launching the App: If a matching application is installed on the device, Chromium calls startActivity() with the generated intent. The Android OS pauses the browser and brings the native application to the foreground.
  2. Triggering the Web Fallback: If no matching app is found, Chromium inspects the parsed intent for the browser_fallback_url string extra. If the developer included this parameter, Chromium cancels the external navigation and loads the fallback URL inside the current browser tab.
  3. Redirecting to the Play Store: If the app is not installed and no fallback URL is provided, Chromium checks if the package parameter was defined in the intent. If a package name is present, Chromium constructs a market://details?id=<package_name> intent and redirects the user directly to the Google Play Store to download the application. If neither a fallback URL nor a package name is present, the navigation silently fails.