correct way to replace super.onBackPressed() on Android 13+ when using registerOnBackInvokedCallback?


What is the correct way to replace super.onBackPressed() on Android 13+ when using registerOnBackInvokedCallback?
I'm updating my Activity to support Android 13+, where onBackPressed() is deprecated.
Previously I had:

@Override
public void onBackPressed() {
    dontStopMusicOnPause = true;
    super.onBackPressed();
}

Now I'm using registerOnBackInvokedCallback:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
        OnBackInvokedDispatcher.PRIORITY_DEFAULT,
        () -> {
            dontStopMusicOnPause = true;
            getOnBackPressedDispatcher().onBackPressed(); // is this correct?
        }
    );
}

I'm not sure whether calling getOnBackPressedDispatcher().onBackPressed() inside the Android 13 callback is valid, or if I should call finish() or something else to mimic the behavior of super.onBackPressed().

0
May 20 at 9:34 PM
User AvatarNullPointerException
#android#kotlin

Accepted Answer

For an AppCompatActivity / ComponentActivity, the correct replacement is not to manually register OnBackInvokedCallback and then call getOnBackPressedDispatcher().onBackPressed() from inside it.

Use AndroidX OnBackPressedCallback instead. AndroidX bridges it to Android 13+ / predictive back for you when using a recent androidx.activity version. Android’s own migration guide says most apps should use the backward-compatible AndroidX API, and migrate old onBackPressed() logic to OnBackPressedDispatcher / OnBackPressedCallback.

Your case should look like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            dontStopMusicOnPause = true;

            // Let the normal back behavior continue.
            setEnabled(false);
            getOnBackPressedDispatcher().onBackPressed();
        }
    });
}

Why this works:

getOnBackPressedDispatcher().onBackPressed() calls registered callbacks in reverse order. If no enabled callbacks remain, it triggers the Activity’s fallback back behavior. By calling setEnabled(false) first, you avoid calling your own callback again recursively.

So this is the modern equivalent of:

dontStopMusicOnPause = true;
super.onBackPressed();

Do not use this pattern inside a manually registered OnBackInvokedCallback unless you are intentionally writing low-level platform-only back handling. In an AndroidX Activity, AndroidX already knows how to connect OnBackPressedDispatcher to Android 13+ via OnBackInvokedDispatcher. The dispatcher even has a setOnBackInvokedDispatcher() API specifically for Android T+ system back handling.

Also, finish() is not exactly equivalent to super.onBackPressed():

finish();

only finishes the current Activity. It will not automatically delegate through AndroidX callbacks, Navigation Component, Fragment back stacks, drawers, dialogs, etc. Also, Android’s default back behavior can differ by version and task state, especially for launcher/root activities. So use finish() only when you explicitly want to close that Activity and you know there is no other back stack to process.

Recommended dependency:

implementation "androidx.activity:activity:1.8.0" // or newer

Or if using AppCompat, keep AppCompat updated too. The Android migration docs mention AndroidX Activity 1.6.0-alpha05 or higher as the minimum migration path for predictive back support, but in a real app today you should use a stable current version.

User AvatarLivaiz
May 20 at 9:44 PM
1