From e8700ec3846cb90dc7c7324738062c1f240379ab Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Mon, 4 May 2026 11:14:12 -0600 Subject: [PATCH 1/2] Fix some bugs in DownloadedPlayerActivity --- .../ui/player/DownloadedPlayerActivity.kt | 26 ++++++++++++++++--- .../ui/player/OfflinePlaybackHelper.kt | 19 +++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt index 7a42cea93f7..6a861eb47f2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt @@ -59,8 +59,26 @@ class DownloadedPlayerActivity : AppCompatActivity() { setContentView(R.layout.empty_layout) Log.i(TAG, "onCreate") - handleIntent(intent) - attachBackPressedCallback("DownloadedPlayerActivity") { finish() } + // When savedInstanceState != null the system saved state before killing the + // backgrounded process the NavController restores the correct player fragment + // automatically. Do not replay the intent as it would push a duplicate player. + if (savedInstanceState == null) { + handleIntent(intent) + } + + // Use moveTaskToBack instead of finish() so there is always exactly one task + // entry in recents, always reflecting the current file. + // + // finish() destroys the Activity but may leave the task in recents. Each new file + // open can create a new task entry, so recents accumulates stale entries for old + // files. The user then taps a stale entry and gets the wrong file. + // + // moveTaskToBack keeps the Activity alive in the background. There is only ever + // one task entry in recents. New files opened from the file manager arrive via + // onNewIntent on the live instance, updating the player immediately. The single + // recents entry always reflects the current state, ensuring we load the + // correct file. + attachBackPressedCallback("DownloadedPlayerActivity") { moveTaskToBack(true) } } private fun handleIntent(intent: Intent) { @@ -83,11 +101,11 @@ class DownloadedPlayerActivity : AppCompatActivity() { url != null -> playLink(this, url) data != null -> playUri(this, data) extraText != null -> playLink(this, extraText) - else -> { finish(); return } + else -> finishAndRemoveTask() } } else if (data?.scheme == "content") { playUri(this, data) - } else finish() + } else finishAndRemoveTask() } override fun onResume() { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/OfflinePlaybackHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/OfflinePlaybackHelper.kt index eb9f5c249eb..4b16d6238bd 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/OfflinePlaybackHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/OfflinePlaybackHelper.kt @@ -5,6 +5,7 @@ import android.content.ContentUris import android.content.Intent import android.net.Uri import androidx.core.content.ContextCompat.getString +import androidx.navigation.NavOptions import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.actions.temp.CloudStreamPackage import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -13,6 +14,15 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.safefile.SafeFile object OfflinePlaybackHelper { + /** + * Pop any existing player off the nav back stack before pushing the new one, + * keeping the stack flat (at most one player at a time). This prevents an + * OOM when many files are opened in sequence via DownloadedPlayerActivity. + */ + private val replacePlayerNavOptions = NavOptions.Builder() + .setPopUpTo(R.id.navigation_player, inclusive = true, saveState = false) + .build() + fun playLink(activity: Activity, url: String) { activity.navigate( R.id.global_to_navigation_player, GeneratorPlayer.newInstance( @@ -21,7 +31,8 @@ object OfflinePlaybackHelper { BasicLink(url) ) ) - ) + ), + replacePlayerNavOptions ) } @@ -53,7 +64,8 @@ object OfflinePlaybackHelper { subs, if (id != -1) id else null, ) - ) + ), + replacePlayerNavOptions ) return true } @@ -78,7 +90,8 @@ object OfflinePlaybackHelper { ) ) ) - ) + ), + replacePlayerNavOptions ) } } \ No newline at end of file From f4b2b957dc72e8df545f3f7ec0d33a117c44d778 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Wed, 6 May 2026 10:48:48 -0600 Subject: [PATCH 2/2] Remove savedInstanceState check and use better long comment format --- .../ui/player/DownloadedPlayerActivity.kt | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt index 6a861eb47f2..a086cc16ff1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt @@ -58,26 +58,22 @@ class DownloadedPlayerActivity : AppCompatActivity() { enableEdgeToEdgeCompat() setContentView(R.layout.empty_layout) Log.i(TAG, "onCreate") + handleIntent(intent) - // When savedInstanceState != null the system saved state before killing the - // backgrounded process the NavController restores the correct player fragment - // automatically. Do not replay the intent as it would push a duplicate player. - if (savedInstanceState == null) { - handleIntent(intent) - } - - // Use moveTaskToBack instead of finish() so there is always exactly one task - // entry in recents, always reflecting the current file. - // - // finish() destroys the Activity but may leave the task in recents. Each new file - // open can create a new task entry, so recents accumulates stale entries for old - // files. The user then taps a stale entry and gets the wrong file. - // - // moveTaskToBack keeps the Activity alive in the background. There is only ever - // one task entry in recents. New files opened from the file manager arrive via - // onNewIntent on the live instance, updating the player immediately. The single - // recents entry always reflects the current state, ensuring we load the - // correct file. + /** + * Use moveTaskToBack instead of finish() so there is always exactly one task + * entry in recents, always reflecting the current file. + * + * finish() destroys the Activity but may leave the task in recents. Each new file + * open can create a new task entry, so recents accumulates stale entries for old + * files. The user then taps a stale entry and gets the wrong file. + * + * moveTaskToBack keeps the Activity alive in the background. There is only ever + * one task entry in recents. New files opened from the file manager arrive via + * onNewIntent on the live instance, updating the player immediately. The single + * recents entry always reflects the current state, ensuring we load the + * correct file. + */ attachBackPressedCallback("DownloadedPlayerActivity") { moveTaskToBack(true) } }