Android SharedPreferences Tutorial and Example

Deep linking: opening an Android app from a URL

Deep linking lets an Android application respond when someone taps a web address. Instead of opening a generic home screen in Chrome, the operating system can launch a specific screen, such as a product page, booking form, article, or user profile.

For Android developers, opening an app from a URL involves URI patterns, intent filters, activity navigation, and careful input handling. A well-designed link can carry useful information while still giving people a sensible web fallback when the app is not installed.

This feature is useful for marketing campaigns, email notifications, QR codes, customer support messages, and links shared through social media. An Australian retailer might send a myshop.com.au/product/coffee link that opens its product screen, while a transport app could direct users to a saved route for Sydney, Melbourne, or Brisbane.

The implementation can start with ordinary deep links and become more secure with Android App Links. The following approach uses Kotlin and modern Android concepts while remaining clear enough for developers who are still becoming comfortable with activities and intents.

What happens when a URL opens an app

A deep link is a URL that contains enough information to identify content inside an application. For example, https://example.com/article/42 has a host, a path, and an article identifier. Android examines the URL and searches installed applications whose manifest declares a matching intent filter.

If one application matches, Android can launch the relevant activity with an ACTION_VIEW intent. The activity receives the complete URI through intent.data. Your code then reads the path or query parameters and navigates to the correct screen.

A normal deep link may display a chooser or ask the user which application should handle the address. An Android App Link uses domain verification to show that your app is authorised for a particular website. This creates a smoother experience and reduces the risk of another app claiming the same URL pattern.

Declare a URL pattern in the manifest

The activity that receives links needs an intent filter in AndroidManifest.xml. This example handles HTTPS addresses on www.example.com with paths beginning with /article/:

<activity
    android:name=".ArticleActivity"
    android:exported="true">

    <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="https"
            android:host="www.example.com"
            android:pathPrefix="/article/" />
    </intent-filter>
</activity>

ACTION_VIEW allows the activity to display content, while BROWSABLE permits links from browsers and other applications. On Android 12 and later, an activity with an intent filter must explicitly set android:exported. Without it, the application may fail to install or build.

Use HTTPS for production links. You can also declare a custom scheme such as myapp://article/42, but custom schemes are easier for another application to imitate. A real domain is better for email campaigns, QR codes on Australian event posters, and links shared in local community groups.

Read the incoming URI safely

The receiving activity should treat URL data as untrusted input. A missing path, malformed identifier, or unexpected query value must not crash the application. It should produce a useful error state or return the user to a safe screen.

class ArticleActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val uri = intent?.data
        val articleId = uri
            ?.pathSegments
            ?.takeIf { it.size >= 2 && it[0] == "article" }
            ?.getOrNull(1)

        if (articleId.isNullOrBlank()) {
            showInvalidLink()
            return
        }

        openArticle(articleId)
    }

    private fun openArticle(id: String) {
        // Load the article and update the screen.
    }

    private fun showInvalidLink() {
        // Display an error or navigate to a safe destination.
    }
}

Do not assume that an identifier is numeric just because your current links use numbers. Validate it according to your application rules, encode values correctly, and avoid placing secrets or personal data in a URL. A link can be copied, logged, displayed in browser history, or forwarded to another person.

If your app uses a single activity with Jetpack Navigation, convert the URI into a navigation destination. For a multi-activity application, a small routing activity can inspect the link and forward the user to the appropriate screen. Keep this routing logic centralised so that links behave consistently from notifications, browser tabs, and other apps.

Verify ownership with Android App Links

App Links use a file hosted on your website to prove that the Android package is allowed to handle the domain. Place assetlinks.json at:

https://www.example.com/.well-known/assetlinks.json

A basic file looks like this:

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.reader",
      "sha256_cert_fingerprints": [
        "AA:BB:CC:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD"
      ]
    }
  }
]

Replace the package name and certificate fingerprint with the values from your application. Debug and release builds often use different signing certificates, so verify the fingerprint for the build distributed through Google Play. A staging domain can use a separate file and package where appropriate.

The file must be served over HTTPS with valid JSON and no redirect that prevents Android from retrieving it. Confirm that the domain, path, certificate, and manifest host all match. For an Australian service using both example.com.au and www.example.com.au, each host needs deliberate configuration rather than an assumption that one verification covers both.

Choose the right linking approach

The best option depends on whether your application owns a public website, needs a private handoff between apps, or must support older marketing links. A website-backed HTTPS link usually provides the strongest user experience because it can open the app or remain useful in a browser.

Approach Example Main benefit Important limitation
HTTPS App Link https://example.com.au/item/42 Verified domain and trusted routing Requires website verification
Standard HTTPS deep link https://example.com/item/42 Simple to add and browser-friendly May show an app chooser
Custom scheme reader://item/42 Useful for internal app-to-app flows Another app can claim the scheme
Intent URL Browser-generated intent link Can include additional launch data Browser and device support varies
Deferred deep link Campaign link to install then open content Preserves campaign context after install Usually needs a link provider or backend

A website fallback matters when a customer has not installed the app. For example, a Melbourne café loyalty campaign can send the same URL to Android users, iPhone users, and desktop visitors. The app can show the loyalty offer, while the website presents the same offer or an install prompt.

Avoid depending on a link provider without checking its privacy, pricing, and redirect behaviour. Links are often printed on signage, included in SMS messages, or used in paid campaigns, so a broken redirect can affect customer service and advertising performance across the Australian market.

Test links across real Android states

Testing only by tapping a link in Android Studio is not enough. Try the address from Chrome, Gmail, Messages, a QR scanner, and a second application. Check behaviour when the app is installed, installed but not running, already open, and completely absent.

Use Android Debug Bridge to send a URL directly to the device:

adb shell am start \
  -a android.intent.action.VIEW \
  -c android.intent.category.BROWSABLE \
  -d "https://www.example.com/article/42"

Test invalid paths, empty identifiers, encoded characters, query parameters, and links received after an app update. Also check back navigation: after opening a deep link, the user should understand where the Back button will take them.

Before publishing, review the following implementation points:

  • Use HTTPS and declare the exact scheme, host, and path required by the feature.
  • Add DEFAULT and BROWSABLE categories to the receiving intent filter.
  • Set android:exported="true" for an externally reachable activity.
  • Validate every URI component before loading data or making a network request.
  • Host a correct assetlinks.json file for verified App Links.
  • Test signed release builds, not only debug builds.
  • Provide a useful browser fallback when the application is unavailable.

A reliable deep-linking design makes a URL a direct route into the app rather than a fragile shortcut. With clear manifest rules, verified domain ownership, safe URI parsing, and realistic device testing, Android applications can turn shared web addresses into smooth, context-aware experiences.