Explicit and Implicit Intents
What is an Intent?
An Intent is a messaging object used to request an action from another component. It's the primary mechanism for communication between Android components — Activities, Services, and Broadcast Receivers.
Explicit Intents
Explicit intents specify exactly which component to start:
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
findViewById<Button>(R.id.btnDetail).setOnClickListener {
// Explicit intent — target is known
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("itemId", "12345")
intent.putExtra("title", "Android Fundamentals")
startActivity(intent)
}
}
}
Explicit intents are used within your own app — you know the exact class you want to launch.
Implicit Intents
Implicit intents declare what action to perform, and the system finds the appropriate component:
// Open a URL in browser
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://developer.android.com"))
startActivity(intent)
// Share text
val shareIntent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "Check out this article!")
}
startActivity(Intent.createChooser(shareIntent, "Share via"))
// Send an email
val emailIntent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:")
putExtra(Intent.EXTRA_EMAIL, arrayOf("user@example.com"))
putExtra(Intent.EXTRA_SUBJECT, "Hello")
putExtra(Intent.EXTRA_TEXT, "Body text")
}
startActivity(emailIntent)
The system resolves implicit intents by matching against intent filters declared in manifests. If multiple apps can handle it, the user sees a chooser dialog.
Intent Filters
Components declare what intents they can handle:
<activity
android:name=".ui.DeepLinkActivity"
android:exported="true">
<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="myapp.com"
android:pathPrefix="/items" />
</intent-filter>
</activity>
This activity handles URLs like https://myapp.com/items/123.
Extras and Result Handling
Passing Data with Extras
Intents carry data via Bundle extras:
// Sending
class ListActivity : AppCompatActivity() {
private val openDetail = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
val updated = result.data?.getBooleanExtra("updated", false) ?: false
if (updated) refreshList()
}
}
fun onItemClick(itemId: String) {
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("itemId", itemId)
putExtra("isEditing", true)
putExtra("score", 95.5)
putStringArrayListExtra("tags", arrayListOf("android", "kotlin"))
}
openDetail.launch(intent)
}
}
// Receiving
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val itemId = intent.getStringExtra("itemId") ?: return
val isEditing = intent.getBooleanExtra("isEditing", false)
val score = intent.getDoubleExtra("score", 0.0)
val tags = intent.getStringArrayListExtra("tags")
}
}
Serializable vs Parcelable
For complex objects, implement Parcelable (preferred) or Serializable:
@Parcelize
data class Item(
val id: String,
val title: String,
val price: Double
) : Parcelable
// Passing
class ListActivity : AppCompatActivity() {
private val openDetail = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { /* handle result */ }
fun openItem(item: Item) {
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra("item", item)
}
openDetail.launch(intent)
}
}
// Receiving
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val item = intent.getParcelableExtra<Item>("item") ?: return
}
}
Parcelable is significantly faster than Serializable on Android because it avoids reflection.
Activity Result API
The modern way to get results from activities:
class ProfileActivity : AppCompatActivity() {
private val pickImage = registerForActivityResult(
ActivityResultContracts.GetContent()
) { uri: Uri? ->
uri?.let { displayImage(it) }
}
private val requestPermission = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted: Boolean ->
if (granted) startCamera()
else showPermissionDenied()
}
fun onSelectImage() {
pickImage.launch("image/*")
}
fun onTakePhoto() {
requestPermission.launch(Manifest.permission.CAMERA)
}
}
This replaces the deprecated startActivityForResult and onActivityResult pattern.
Quiz
1. What is the difference between explicit and implicit intents?
2. Why is Parcelable preferred over Serializable on Android?
3. What replaced the deprecated startActivityForResult pattern?
4. What does an intent filter's data element specify?
Flashcards
Question
When should you use an explicit vs implicit intent?
Click to reveal answer
Answer
Explicit: within your app when you know the exact target component. Implicit: when you want the system to find a handler (e.g., open URL, share content, take photo).
Question
What is Parcelable and why is it preferred?
Click to reveal answer
Answer
Parcelable is an interface for objects that can be written to and restored from a Parcel. Preferred over Serializable because it's faster — no reflection.
Question
How does the Activity Result API work?
Click to reveal answer
Answer
registerForActivityResult with a contract (e.g., GetContent, RequestPermission) returns a launcher. Call launcher.launch() and receive results in the callback.
Question
What makes an intent 'implicit'?
Click to reveal answer
Answer
It doesn't specify a target component — it declares an action and optional data. The system resolves which component can handle it via intent filters.
Revision Notes
Key Takeaways
- 1. Explicit intents target known components; implicit intents let the system resolve the target
- 2. Parcelable is much faster than Serializable for passing complex objects
- 3. The Activity Result API replaces deprecated startActivityForResult pattern
- 4. Intent filters in the manifest declare what actions a component can handle
- 5. Always use createChooser for implicit intents so the user can pick the app
Interview Tips
- • Know when to use explicit vs implicit intents
- • Explain why Parcelable is faster than Serializable on Android
- • Discuss the Activity Result API and its advantages over the old pattern
- • Be ready to explain how deep linking works with intent filters
Cheat Sheet
Intents Cheat Sheet
Explicit Intent:
Intent(this, TargetActivity::class.java)
Implicit Intent:
Intent(Intent.ACTION_VIEW, Uri.parse(url))
Common Actions:
ACTION_VIEW— open URL, map, etc.ACTION_SEND— share contentACTION_SENDTO— send emailACTION_PICK— pick from gallery
Result Handling:
registerForActivityResult(contract) { result ->
// handle result
}
launcher.launch(intent)
Data Types:
- Primitives:
putExtra("key", value) - Parcelable:
@Parcelizeannotation - Bundle:
putBundle("key", bundle)