From f7de3b478ba14213dbe3ad274bdc4595edef4aed Mon Sep 17 00:00:00 2001 From: Michal Wolski Date: Fri, 21 Nov 2025 01:23:21 +0100 Subject: [PATCH] Migrate back navigation from deprecated APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since Android 13, PlayerActivity.onBackPressed() is no longer invoked. This broke the app’s behavior, for example videos would unexpectedly resume when returning to the app, and the player’s controller wouldn’t hide on Android TV. This commit restores the intended behavior by migrating from onBackPressed() and onKeyDown(KEYCODE_BACK) to the new OnBackInvokedCallback API. --- .../com/brouken/player/PlayerActivity.java | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/brouken/player/PlayerActivity.java b/app/src/main/java/com/brouken/player/PlayerActivity.java index 1e2a7f18..e8974566 100644 --- a/app/src/main/java/com/brouken/player/PlayerActivity.java +++ b/app/src/main/java/com/brouken/player/PlayerActivity.java @@ -56,6 +56,8 @@ import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; @@ -214,6 +216,8 @@ public class PlayerActivity extends Activity { } }; + final Object onBackInvokedCallback = createOnBackInvokedCallback(); + @RequiresApi(api = Build.VERSION_CODES.O) @Override protected void onCreate(Bundle savedInstanceState) { @@ -684,6 +688,21 @@ public void onTargetClick(TapTargetView view) { errorToShow = null; } } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && isTvBox) { + if (visibility == View.VISIBLE) { + if (player != null && player.isPlaying()) { + //noinspection DataFlowIssue + getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, + (OnBackInvokedCallback) onBackInvokedCallback + ); + } + } else { + //noinspection DataFlowIssue + getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback((OnBackInvokedCallback) onBackInvokedCallback); + } + } } }); @@ -715,6 +734,18 @@ public void onAnimationEnd(Animator animation) { Utils.scanMediaStorage(this); } } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { + getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER, + () -> restorePlayStateAllowed = false + ); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + getOnBackInvokedDispatcher().registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, + this::onBackPressed + ); + } } @Override @@ -823,7 +854,6 @@ protected void onNewIntent(Intent intent) { } } - @SuppressLint("GestureBackNavigation") @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { @@ -907,13 +937,18 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { return true; } break; + //noinspection "GestureBackNavigation" case KeyEvent.KEYCODE_BACK: - if (isTvBox) { - if (controllerVisible && player != null && player.isPlaying()) { - playerView.hideController(); - return true; - } else { - onBackPressed(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return super.onKeyDown(keyCode, event); + } else { + if (isTvBox) { + if (controllerVisible && player != null && player.isPlaying()) { + playerView.hideController(); + return true; + } else { + onBackPressed(); + } } } break; @@ -2319,4 +2354,12 @@ private void updateButtonRotation() { } } } + + private Object createOnBackInvokedCallback() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return (OnBackInvokedCallback) () -> playerView.hideController(); + } else { + return null; + } + } } \ No newline at end of file