Question
Android onBackPressed Deprecation: Modern Back Handling in Kotlin
Question
I upgraded targetSdkVersion and compileSdkVersion to 33, and now I get a warning that onBackPressed() is deprecated.
The documentation and examples suggest using either android.window.OnBackInvokedCallback or androidx.activity.OnBackPressedCallback for back navigation handling. How do I migrate my existing code to the newer approach?
Here is my current use case: inside onBackPressed() I check isTaskRoot to determine whether the activity is the last one in the task stack. If it is, I open Dashboard; otherwise, I finish the current activity and return a result.
override fun onBackPressed() {
if (isTaskRoot) {
// This activity is the last one in the task stack
// for example, when opened from a push notification
startActivity(Intent(this, Dashboard::class.java))
finish()
} else {
finishWithResultOK()
}
}
Short Answer
By the end of this page, you will understand why onBackPressed() was deprecated, when to use OnBackPressedDispatcher with OnBackPressedCallback, and how to convert older Activity back-button logic to the modern Android approach in Kotlin. You will also see how this fits into real apps and how to avoid common migration mistakes.
Concept
onBackPressed() used to be the common way to intercept the system back button in an Android Activity. However, Android introduced a more modern back navigation system so back handling can be lifecycle-aware, easier to compose, and more consistent with newer Android behavior.
For most apps, the recommended replacement is:
onBackPressedDispatcherOnBackPressedCallback
These come from AndroidX and work well across Android versions.
Why was onBackPressed() deprecated?
The old method had some limitations:
- It tightly coupled back handling to a single overridden Activity method.
- It was less flexible for Fragments and nested UI components.
- It did not fit as well with newer predictive and system-managed back behavior.
- It made lifecycle-safe registration harder.
What should you use instead?
In most Activity and Fragment code, use:
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// custom back logic
}
})
This registers a callback that runs when the user presses back.
Mental Model
Think of the back button like a queue of handlers.
In older Android code, the Activity had one main back-button method: onBackPressed(). It was like saying, "When back is pressed, ask the Activity what to do."
With the newer system, back handling is more like a list of listeners:
- Android asks the top active back callback first.
- If that callback handles the event, the process stops.
- If not, Android can continue to the next handler or default system behavior.
A good analogy is a stack of sticky notes on a screen:
- The top note gets checked first.
- If it has instructions, those are used.
- If not, Android moves on.
This makes back handling easier for screens, dialogs, Fragments, and reusable UI parts.
Syntax and Examples
The modern syntax in an Activity looks like this:
import android.content.Intent
import android.os.Bundle
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
class DetailsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isTaskRoot) {
startActivity(Intent(this@DetailsActivity, Dashboard::class.java))
finish()
} else {
finishWithResultOK()
}
}
})
}
private fun finishWithResultOK() {
setResult(RESULT_OK)
finish()
}
}
What this does
addCallback(this, ...)attaches the callback to the Activity lifecycle.
Step by Step Execution
Consider this example:
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isTaskRoot) {
startActivity(Intent(this@MyActivity, Dashboard::class.java))
finish()
} else {
finishWithResultOK()
}
}
})
Step-by-step
- The Activity starts.
- In
onCreate(), a back callback is registered. - The user presses the system back button.
- Android sends the event to
onBackPressedDispatcher. - The dispatcher finds your enabled callback.
handleOnBackPressed()runs.- The code checks
isTaskRoot.
Case 1: isTaskRoot == true
- This means the current Activity is the root of the task.
Dashboardis started.finish()closes the current Activity.
Case 2:
Real World Use Cases
Modern back handling is used in many practical Android scenarios:
- Form screens: ask the user whether they want to discard unsaved changes.
- Search screens: close search mode before leaving the screen.
- Bottom sheets or dialogs: collapse or dismiss UI before exiting the Activity.
- Push notification flows: redirect users to a safe home screen if the Activity was opened directly.
- Multi-step flows: go back one step inside the screen rather than immediately finishing the Activity.
- Fragment-based apps: let the visible Fragment intercept back before the Activity handles it.
Your isTaskRoot example is common in notification-driven navigation. If a user lands directly on a detail screen from a push notification, pressing back may need to take them to Dashboard instead of leaving the app in an odd state.
Real Codebase Usage
In real Android projects, developers often use OnBackPressedCallback with a few common patterns.
1. Guard clauses
Keep back logic easy to read by returning early.
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (isTaskRoot) {
startActivity(Intent(this@MyActivity, Dashboard::class.java))
finish()
return
}
finishWithResultOK()
}
})
2. Validation before leaving
override fun handleOnBackPressed() {
if (hasUnsavedChanges()) {
showDiscardDialog()
return
}
finish()
}
3. Enabling and disabling callbacks
A callback can be turned on only when needed.
val callback = object : OnBackPressedCallback(false) {
override {
closeSelectionMode()
}
}
onBackPressedDispatcher.addCallback(, callback)
callback.isEnabled =
Common Mistakes
1. Using this instead of the Activity context
Broken example:
startActivity(Intent(this, Dashboard::class.java))
Inside the callback, this refers to the OnBackPressedCallback, not the Activity.
Correct:
startActivity(Intent(this@MyActivity, Dashboard::class.java))
2. Registering the callback without lifecycle awareness
Prefer:
onBackPressedDispatcher.addCallback(this, callback)
Using the Activity or Fragment as the lifecycle owner helps Android remove the callback at the right time.
3. Forgetting that the callback is enabled or disabled
If you create a callback with false, it will not run.
object : OnBackPressedCallback(false) {
override fun handleOnBackPressed {
finish()
}
}
Comparisons
| Approach | When to use | Pros | Cons |
|---|---|---|---|
onBackPressed() | Legacy code only | Simple and familiar | Deprecated, less flexible |
OnBackPressedDispatcher + OnBackPressedCallback | Most modern apps | Lifecycle-aware, AndroidX-friendly, works well with Fragments | Slightly more setup |
OnBackInvokedCallback | Platform-specific newer back integration | Matches newer Android platform behavior | Usually not necessary directly for most app code |
onBackPressed() vs OnBackPressedCallback
onBackPressed()is one overridden Activity method.
Cheat Sheet
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// custom back logic
}
})
Rules
- Use
OnBackPressedCallbackinstead of overridingonBackPressed(). - In Activities, register the callback in
onCreate(). - In Fragments, register with
viewLifecycleOwnerwhen appropriate. - Use
this@MyActivityinside the callback when you need the Activity context. truemeans enabled;falsemeans disabled.
Common migration pattern
Old:
override fun onBackPressed() {
if (isTaskRoot) {
startActivity(Intent(this, Dashboard::class.java))
finish()
} else {
finishWithResultOK()
}
}
FAQ
What is the replacement for onBackPressed() in Android?
For most apps, use onBackPressedDispatcher with OnBackPressedCallback. It is the recommended AndroidX alternative.
Should I use OnBackInvokedCallback or OnBackPressedCallback?
In most app code, use OnBackPressedCallback. It is simpler, AndroidX-based, and works across Android versions.
Where should I register OnBackPressedCallback in an Activity?
Usually in onCreate(), using the Activity as the lifecycle owner.
Can I still check isTaskRoot with the new API?
Yes. Your business logic stays the same. Only the back-handling mechanism changes.
Why does Intent(this, Dashboard::class.java) fail inside the callback?
Because this refers to the callback object, not the Activity. Use this@MyActivity instead.
Does OnBackPressedCallback work with Fragments?
Yes. It is commonly used in Fragments and is one of the reasons the newer approach is preferred.
Mini Project
Description
Build an Android Activity that handles the system back button using the modern API. The screen should decide whether to return to a dashboard or finish with a result based on whether it is the root of the task. This mirrors a common real-world case where a screen may be opened from inside the app or directly from a push notification.
Goal
Create a Kotlin Activity that replaces deprecated onBackPressed() logic with OnBackPressedCallback and preserves the original navigation behavior.
Requirements
- Create an Activity that registers a back callback using
onBackPressedDispatcher - If
isTaskRootis true, openDashboardActivityand close the current Activity - If
isTaskRootis false, returnRESULT_OKand finish the Activity - Use the correct Activity context when creating the
Intent - Keep the code lifecycle-aware by attaching the callback to the Activity
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.