Explicit and implicit intents

Lifecycle and app components Junior Kotlin 2.0+ API 30+ Reviewed By Best Latest Apps

Pick the fix

Since targeting Android 11, intent.resolveActivity(packageManager) returns null and the Share button hides, even though email apps are installed. Best fix?

Options
Hint 1 of 1

Is the problem starting the intent, or asking who can handle it?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Call startActivity directly and catch ActivityNotFoundException, or add a <queries> entry

Correct. Package visibility hides other apps from queries, not from starting them.

Why not the others?
  • B Request QUERY_ALL_PACKAGES. Play restricts that permission to apps that truly need it.
  • C Use an explicit intent to a mail app's package. That only works for one app and breaks if it isn't installed.
  • D Lower targetSdk. Play requires a recent target.

30-second answer

An explicit intent names the component to start, usually inside your app. An implicit intent describes an action and data, like ACTION_VIEW with a URL, and the system finds apps whose intent filters match. Since Android 11, apps can't see most other installed apps by default, so queries about which apps can handle an intent need a <queries> entry.

Practise saying it · 35 s. No recording, just a timer

Explain explicit vs implicit intents.

Say your answer out loud, then check which of these points you covered:

  • Explicit names the component
  • Implicit matches intent filters
  • Package visibility needs <queries>
  • android:exported is required

Deep dive

Calling startActivity with an implicit intent works without <queries>; catch ActivityNotFoundException if nothing handles it.

Since Android 12, components with intent filters must declare android:exported explicitly.

Since Android 14, implicit intents to your own app's non-exported components are blocked; use explicit intents internally.

Use Intent.createChooser when users should pick each time, such as sharing.

Opening a link safely Compile-checked · Kotlin 2.4.21
fun openLink(context: Context, url: String) {
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    try {
        context.startActivity(intent)
    } catch (e: ActivityNotFoundException) {
        Toast.makeText(context, "No browser installed", Toast.LENGTH_SHORT).show()
    }
}

Common mistakes

  • Calling resolveActivity without a <queries> entry and wrongly concluding no app exists.
  • Exporting components that don't need to be.
  • Using implicit intents for your own internal screens.

Senior take & follow-ups

Seniors mention package visibility and the exported rules, which bite real apps on upgrade.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why did resolveActivity start returning null on Android 11?

    Show hint

    Package visibility: the app must declare the intent in <queries>.

  2. What must every component with an intent filter declare?

    Show hint

    android:exported, since Android 12.

Suggest a fix if something here is wrong or out of date.