The Illusion of a Single App
Users expect the back button to reverse their exact workflow. If they tap an email link, open a browser, and share a page to a chat app, they expect the back button to retrace those exact steps. If Android treated every application as an isolated sandbox, the back button would just drop the user onto the home screen. That behavior ruins the mental model of completing a single goal. Android solves this routing problem using Tasks.
A Task is a logical grouping of Activities arranged in a stack. The operating system pushes new Activities onto this stack in the order they open. The application boundary does not matter. The system completely ignores which package owns the Activity.
When the user presses the back button, the OS pops the top Activity off the stack and destroys it. This reveals the previous screen exactly as the user left it.
The flowchart below shows a single Task holding Activities from completely different applications. Visualizing this multi-app stack clarifies why navigation feels continuous. Read from top to bottom as the user navigates deeper.
By keeping these Activities in one stack, the OS ensures that pressing back in the Gallery app returns the user directly to the Email app. The user feels like they are completing one continuous job.
The default push-and-pop behavior works perfectly for linear workflows. But what happens when a user logs out of your app?
Bending the Stack with Intent Flags
Linear navigation fails completely during authentication flows. If a user logs out and you simply open the Login screen, pressing back returns them to their secure account page. The default stack behavior suddenly becomes a severe security flaw.
To fix routing issues like this, Android provides Intent Flags. These are specific constants you append to an Intent before calling startActivity(). They allow developers to radically manipulate the back stack at runtime.
You apply these flags using the addFlags() method on your Intent. For example, FLAG_ACTIVITY_NEW_TASK starts an Activity in a brand new Task. This prevents background notifications from hijacking the current app flow. Another flag, FLAG_ACTIVITY_NO_HISTORY, keeps the Activity off the stack entirely, destroying it as soon as the user navigates away.
To solve the logout problem, you combine two flags.
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Common Mistake: Forgetting to include
FLAG_ACTIVITY_NEW_TASKwhen callingstartActivity()from a Service context will cause a runtime crash.
When you apply FLAG_ACTIVITY_CLEAR_TASK, the system instantly destroys all Activities in the current task before launching the target Activity. This guarantees the Login screen is the only thing on the stack. You gain precise control over user routing, preventing duplicate screens or trapped navigation states.
Tasks and Intent flags control screen-to-screen routing, but what if the app needs to intercept the back button itself?
The Problem with Blind Interception
Historically, apps altered the back button behavior by overriding onBackPressed(). This created a massive user experience problem. The operating system had absolutely no idea what the app planned to do when the back button was pressed. The app might pop a fragment, close a drawer, or exit completely.
Since the OS was blind to the outcome, animating the transition safely was impossible. If the OS guessed wrong and animated an app exit while the app only intended to close a side drawer, the screen would flash and glitch. Android 13 fixed this visual garbage by introducing Predictive Back Navigation.
Predictive Back Navigation requires apps to declare their back behavior ahead of time using the OnBackPressedDispatcher. Instead of waiting for the user to press the button, your app registers a callback that the OS queries immediately.
This sequence diagram illustrates how the OS and the app coordinate before the user even finishes swiping the screen edge. Mapping this communication clarifies why early registration prevents visual glitches. Pay attention to how the OS checks the dispatcher first.
The system identifies the callback before the user completes their swipe. Because the OS knows exactly what the back action will do, it renders fluid animations safely. It can shrink the current window to reveal the home screen wallpaper beneath it, eliminating navigation anxiety for the user.
You implement this mechanism by adding a callback to the dispatcher during your Activity creation phase.
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
closeCustomDrawer();
}
});
Tasks manage travel across app boundaries. Intent Flags give you the power to manipulate that travel. Predictive Back Navigation guarantees the user always understands where that travel will take them next.
Navigating between screens is only half the battle. When a user rotates their device or leaves your app for a moment, the system might aggressively destroy your Activities to reclaim memory. Preserving user state through that destruction requires a closer look at the Activity Lifecycle.