Understanding Intents And Intent Filters In Android

Android applications are built from components that often need to communicate without knowing every implementation detail of one another. Intents provide that communication layer, allowing an activity to open another screen, a service to perform work, or a broadcast receiver to respond to a system event.

Intent filters define which kinds of requests a component can handle. Once these concepts are clear, common Android features such as sharing, opening maps, launching a camera, selecting a document, and responding to deep links become easier to design and troubleshoot.

What An Intent Represents

An Intent is a message describing an action to perform. It can identify a specific component, carry data such as a URI, and include additional values called extras. For example, an activity might send a product ID to a detail screen, while another component might request that Android display a web page.

An explicit intent names its destination directly. This is the usual choice for moving between activities inside your own application:

val intent = Intent(this, CheckoutActivity::class.java)
intent.putExtra("order_id", orderId)
startActivity(intent)

The receiving activity can read the value from its Intent object. In production code, use stable keys and validate every extra because values can be missing, malformed, or supplied by another application.

An intent can also launch a service or send a broadcast. Modern Android versions place limits on background activity starts and implicit service launches, so developers should check the current platform rules rather than relying on behaviour from older tutorials.

Explicit And Implicit Navigation

An implicit intent describes the requested operation without naming a particular application. Android searches installed components for a suitable match. This makes it possible to use the user’s preferred browser, email application, map provider, camera, or document manager.

val intent = Intent(Intent.ACTION_VIEW).apply {
    data = Uri.parse("https://example.com")
}
startActivity(intent)

The same pattern can support sharing text:

val share = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, "A message to share")
}
startActivity(Intent.createChooser(share, "Share with"))

Always consider the possibility that no application can fulfil an implicit request. resolveActivity(packageManager) can be used before launching, allowing the app to show a useful fallback instead of crashing. Android developers looking for broader examples of component communication can also consult Android Open Tutorials, particularly when comparing older Java patterns with current Kotlin practices.

Explicit intents provide predictability, while implicit intents provide flexibility. A well-designed application uses explicit navigation for its own screens and carefully constrained implicit requests when cooperating with the wider Android ecosystem.

How Intent Filters Match Requests

An intent filter is declared in AndroidManifest.xml. It tells Android which implicit intents a component may receive. A filter can specify an action, categories, and data such as a MIME type, scheme, host, or path.

<intent-filter>
    <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="shop.example.com"
        android:pathPrefix="/offers" />
</intent-filter>

For an activity to receive an implicit intent, the requested action must match an action in the filter. The requested categories must be supported by the filter, and its data requirements must also match. Android adds the CATEGORY_DEFAULT requirement when resolving an implicit intent to an activity, so this category is essential for most activity filters.

A filter is not an access-control mechanism. It announces that a component can handle a request; it does not prove that the request is trustworthy. The receiving component must still inspect the calling context, validate URI values, and apply authentication or authorisation checks where appropriate.

Deep Links And Data Handling

Deep links let a link open a particular location within an application. For example, a retail app might handle https://shop.example.com/product/42 and display product 42. Android App Links add domain verification so that supported web addresses can open directly in the approved application rather than showing an ambiguous chooser.

URI parsing deserves careful attention. Never assume that a path segment is numeric, that a query parameter exists, or that a supplied file is safe to open. Validate schemes and hosts, reject unexpected values, and avoid exposing sensitive information in URLs because links can appear in browser history, analytics systems, notifications, and screenshots.

The same principle applies to entertainment and promotional links. If an app opens an external page such as wild casino games, it should make the destination clear, use a verified HTTPS address, and avoid presenting an external service as though it were part of the app. Australian distribution also calls for responsible treatment of gambling-related content, including age-sensitive messaging and compliance review.

For Android applications distributed in Australia, privacy obligations under the Privacy Act 1988 and the Australian Privacy Principles may affect information passed through intents. Avoid placing email addresses, access tokens, health information, or precise location data in extras or publicly visible deep links.

Common Intent Security And Compatibility Issues

Exported components require particular care. On recent Android versions, activities, services, and receivers with intent filters generally need an explicit android:exported value in the manifest. Set it deliberately: use false for internal components and true only when external applications genuinely need access.

A mutable PendingIntent can be modified by another party if it is not configured correctly. Prefer immutable pending intents unless mutation is required, and specify the intended component for sensitive operations. Broadcast receivers should likewise use restricted broadcasts or explicit receiver names when a message must stay inside the application.

Compatibility testing matters because Android behaviour changes across API levels and manufacturers. Test on current Pixel devices and common Samsung models, as well as different screen sizes and default applications. A user in Sydney may have Google Maps set as the default navigation handler, while someone in regional Queensland may use a different mapping or connectivity setup.

On Android 12 and later, package visibility restrictions can affect attempts to inspect installed applications. Do not assume that querying every package is permitted. Declare only the visibility needs your feature genuinely requires and handle absent applications gracefully.

Building A Reliable Intent Workflow

A dependable intent workflow starts with a precise contract. Define the action, expected data type, URI format, extras, authentication state, and fallback behaviour before writing the manifest. Document whether a component is internal, externally callable, or intended for browser integration.

Use Android Studio’s manifest tools, lint checks, and log output to investigate resolution problems. Test both successful and unsuccessful paths: no matching application, malformed data, a cancelled chooser, a missing extra, and a link opened from a browser. Automated tests can verify that an intent contains the expected action, categories, MIME type, and destination.

Australian user habits can influence testing. Many people use mobile devices during public transport commutes in Melbourne or Sydney, where connectivity may change between stations. A shopping application should preserve state if the user leaves it to confirm a payment in another app, and it should avoid losing a form when Android reclaims a background activity.

Practical Checks Before Release

Before publishing an intent-based feature, review these implementation points:

  • Use explicit intents for internal screens and restrict exported components.
  • Add CATEGORY_DEFAULT to activity filters that handle ordinary implicit launches.
  • Validate every URI, MIME type, extra, and identifier received from another app.
  • Provide a fallback for devices with no browser, camera, map, or document provider.
  • Test deep links, chooser behaviour, permissions, and API-level differences on real devices.

Intent filters are powerful because they connect an application to Android’s broader ecosystem, yet that openness must be controlled. Build clear contracts, verify external data, and test the complete hand-off between applications before release. Start by auditing one navigation flow in your project, then expand the same disciplined approach to sharing, notifications, deep links, and background work.