diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index a21e801ac1..876e3969b6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -596,7 +596,7 @@ class NotificationReceiver : BroadcastReceiver() { */ internal fun openEpisodePendingActivity(context: Context, anime: Anime, episode: Episode): PendingIntent { val newIntent = PlayerActivity.newIntent(context, anime.id, episode.id) - return PendingIntent.getActivity(context, Constants.REQUEST_INTERNAL, newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + return PendingIntent.getActivity(context, anime.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreen.kt index 2928141bb5..7d71934f44 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreen.kt @@ -46,8 +46,7 @@ import eu.kanade.tachiyomi.ui.category.CategoriesTab import eu.kanade.tachiyomi.ui.entries.anime.track.AnimeTrackInfoDialogHomeScreen import eu.kanade.tachiyomi.ui.home.HomeScreen import eu.kanade.tachiyomi.ui.library.anime.AnimeLibraryTab -import eu.kanade.tachiyomi.ui.player.ExternalIntents -import eu.kanade.tachiyomi.ui.player.PlayerActivity +import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.player.settings.dialogs.SkipIntroLengthDialog import eu.kanade.tachiyomi.ui.webview.WebViewScreen import eu.kanade.tachiyomi.util.system.copyToClipboard @@ -262,10 +261,8 @@ class AnimeScreen( } private suspend fun openEpisode(context: Context, episode: Episode, useExternalPlayer: Boolean) { - if (useExternalPlayer) { - context.startActivity(ExternalIntents.newIntent(context, episode.animeId, episode.id)) - } else { - context.startActivity(PlayerActivity.newIntent(context, episode.animeId, episode.id)) + withIOContext { + MainActivity.startPlayerActivity(context, episode.animeId, episode.id, useExternalPlayer) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryTab.kt index 3572ccae9d..24cd053a89 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryTab.kt @@ -21,8 +21,6 @@ import eu.kanade.presentation.history.anime.AnimeHistoryScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.entries.anime.AnimeScreen import eu.kanade.tachiyomi.ui.main.MainActivity -import eu.kanade.tachiyomi.ui.player.ExternalIntents -import eu.kanade.tachiyomi.ui.player.PlayerActivity import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest @@ -46,14 +44,9 @@ fun Screen.animeHistoryTab( suspend fun openEpisode(context: Context, episode: Episode?) { val playerPreferences: PlayerPreferences by injectLazy() - val altPlayer = playerPreferences.alwaysUseExternalPlayer().get() + val extPlayer = playerPreferences.alwaysUseExternalPlayer().get() if (episode != null) { - val intent = if (altPlayer) { - ExternalIntents.newIntent(context, episode.animeId, episode.id) - } else { - PlayerActivity.newIntent(context, episode.animeId, episode.id) - } - context.startActivity(intent) + MainActivity.startPlayerActivity(context, episode.animeId, episode.id, extPlayer) } else { snackbarHostState.showSnackbar(context.getString(R.string.no_next_episode)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryTab.kt index d3ab376560..6fc7aad585 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryTab.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.library.anime -import android.content.Context import androidx.activity.compose.BackHandler import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi import androidx.compose.animation.graphics.res.animatedVectorResource @@ -45,8 +44,6 @@ import eu.kanade.tachiyomi.ui.category.CategoriesTab import eu.kanade.tachiyomi.ui.entries.anime.AnimeScreen import eu.kanade.tachiyomi.ui.home.HomeScreen import eu.kanade.tachiyomi.ui.main.MainActivity -import eu.kanade.tachiyomi.ui.player.ExternalIntents -import eu.kanade.tachiyomi.ui.player.PlayerActivity import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest @@ -116,21 +113,10 @@ object AnimeLibraryTab : Tab { started } - fun openEpisodeInternal(context: Context, animeId: Long, episodeId: Long) { - context.startActivity(PlayerActivity.newIntent(context, animeId, episodeId)) - } - - suspend fun openEpisodeExternal(context: Context, animeId: Long, episodeId: Long) { - context.startActivity(ExternalIntents.newIntent(context, animeId, episodeId)) - } - suspend fun openEpisode(episode: Episode) { val playerPreferences: PlayerPreferences by injectLazy() - if (playerPreferences.alwaysUseExternalPlayer().get()) { - openEpisodeExternal(context, episode.animeId, episode.id) - } else { - openEpisodeInternal(context, episode.animeId, episode.id) - } + val extPlayer = playerPreferences.alwaysUseExternalPlayer().get() + MainActivity.startPlayerActivity(context, episode.animeId, episode.id, extPlayer) } val defaultTitle = if (fromMore) stringResource(R.string.label_library) else stringResource(R.string.label_anime_library) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index ac660b0307..564e8e96da 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.ui.main import android.animation.ValueAnimator +import android.app.Activity import android.app.SearchManager import android.app.assist.AssistContent import android.content.Context @@ -12,6 +13,9 @@ import android.view.View import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.compose.BackHandler +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.WindowInsets @@ -87,12 +91,12 @@ import eu.kanade.tachiyomi.ui.entries.manga.MangaScreen import eu.kanade.tachiyomi.ui.home.HomeScreen import eu.kanade.tachiyomi.ui.more.NewUpdateScreen import eu.kanade.tachiyomi.ui.player.ExternalIntents +import eu.kanade.tachiyomi.ui.player.PlayerActivity import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.isNavigationBarNeedsScrim import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.view.setComposeContent -import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.delay import kotlinx.coroutines.flow.callbackFlow @@ -103,7 +107,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import logcat.LogPriority -import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.system.logcat import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.presentation.core.components.material.Scaffold @@ -126,8 +129,6 @@ class MainActivity : BaseActivity() { private val animeDownloadCache: AnimeDownloadCache by injectLazy() private val downloadCache: MangaDownloadCache by injectLazy() - private val externalIntents: ExternalIntents by injectLazy() - // To be checked by splash screen. If true then splash screen will be removed. var ready = false @@ -295,6 +296,12 @@ class MainActivity : BaseActivity() { elapsed <= SPLASH_MIN_DURATION || !ready && elapsed <= SPLASH_MAX_DURATION } setSplashScreenExitAnimation(splashScreen) + + externalPlayerResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> + if (result.resultCode == Activity.RESULT_OK) { + ExternalIntents.externalIntents.onActivityResult(result.data) + } + } } override fun onProvideAssistContent(outContent: AssistContent) { @@ -500,13 +507,6 @@ class MainActivity : BaseActivity() { registerSecureActivity(this) } - @OptIn(DelicateCoroutinesApi::class) - @Deprecated("Deprecated in Java") - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - launchIO { externalIntents.onActivityResult(requestCode, resultCode, data) } - super.onActivityResult(requestCode, resultCode, data) - } - companion object { // Splash screen private const val SPLASH_MIN_DURATION = 500 // ms @@ -517,5 +517,15 @@ class MainActivity : BaseActivity() { const val INTENT_ANIMESEARCH = "eu.kanade.tachiyomi.ANIMESEARCH" const val INTENT_SEARCH_QUERY = "query" const val INTENT_SEARCH_FILTER = "filter" + + var externalPlayerResult: ActivityResultLauncher? = null + + suspend fun startPlayerActivity(context: Context, animeId: Long, episodeId: Long, extPlayer: Boolean) { + if (extPlayer) { + externalPlayerResult?.launch(ExternalIntents.newIntent(context, animeId, episodeId)) ?: return + } else { + context.startActivity(PlayerActivity.newIntent(context, animeId, episodeId)) + } + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/player/ExternalIntents.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/player/ExternalIntents.kt index d2287c04c3..51b80daf5b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/player/ExternalIntents.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/player/ExternalIntents.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.player -import android.app.Activity import android.app.Application import android.content.ComponentName import android.content.Context @@ -19,7 +18,6 @@ import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.tachiyomi.animesource.AnimeSource import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource -import eu.kanade.tachiyomi.core.Constants.REQUEST_EXTERNAL import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager import eu.kanade.tachiyomi.data.track.AnimeTrackService import eu.kanade.tachiyomi.data.track.TrackManager @@ -27,10 +25,12 @@ import eu.kanade.tachiyomi.ui.player.loader.EpisodeLoader import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.toast +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.first import logcat.LogPriority +import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat @@ -209,6 +209,7 @@ class ExternalIntents { return intent.apply { putExtra("title", anime.title + " - " + episode.name) putExtra("position", getLastSecondSeen().toInt()) + putExtra("return_result", true) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) if (isSupportedPlayer) putExtra("secure_uri", true) } @@ -284,52 +285,51 @@ class ExternalIntents { /** * Saves the episode's data based on whats returned by the external player. * - * @param requestCode the code sent to ensure that the returned [data] is from an external player. - * @param resultCode the code sent to ensure that the returned [data] is valid. - * @param data the [Intent] that contains the episode's position and duration. + * @param resultCode the code sent to ensure that the returned [intent] is valid. + * @param intent the [Intent] that contains the episode's position and duration. */ + @OptIn(DelicateCoroutinesApi::class) @Suppress("DEPRECATION") - suspend fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == REQUEST_EXTERNAL && resultCode == Activity.RESULT_OK) { - val anime = anime - val currentExtEpisode = episode - val currentPosition: Long - val duration: Long - val cause = data!!.getStringExtra("end_by") ?: "" - - // Check for position and duration as Long values - if (cause.isNotEmpty()) { - val positionExtra = data.extras?.get("position") - currentPosition = if (positionExtra is Int) { - positionExtra.toLong() - } else { - positionExtra as? Long ?: 0L - } - val durationExtra = data.extras?.get("duration") - duration = if (durationExtra is Int) { - durationExtra.toLong() - } else { - durationExtra as? Long ?: 0L - } + fun onActivityResult(intent: Intent?) { + val data = intent ?: return + val anime = anime + val currentExtEpisode = episode + val currentPosition: Long + val duration: Long + val cause = data.getStringExtra("end_by") ?: "" + + // Check for position and duration as Long values + if (cause.isNotEmpty()) { + val positionExtra = data.extras?.get("position") + currentPosition = if (positionExtra is Int) { + positionExtra.toLong() } else { - if (data.extras?.get("extra_position") != null) { - currentPosition = data.getLongExtra("extra_position", 0L) - duration = data.getLongExtra("extra_duration", 0L) - } else { - currentPosition = data.getIntExtra("position", 0).toLong() - duration = data.getIntExtra("duration", 0).toLong() - } + positionExtra as? Long ?: 0L + } + val durationExtra = data.extras?.get("duration") + duration = if (durationExtra is Int) { + durationExtra.toLong() + } else { + durationExtra as? Long ?: 0L } + } else { + if (data.extras?.get("extra_position") != null) { + currentPosition = data.getLongExtra("extra_position", 0L) + duration = data.getLongExtra("extra_duration", 0L) + } else { + currentPosition = data.getIntExtra("position", 0).toLong() + duration = data.getIntExtra("duration", 0).toLong() + } + } - // Update the episode's progress and history - withIOContext { - if (cause == "playback_completion" || (currentPosition == duration && duration == 0L)) { - saveEpisodeProgress(currentExtEpisode, anime, currentExtEpisode.totalSeconds, currentExtEpisode.totalSeconds) - } else { - saveEpisodeProgress(currentExtEpisode, anime, currentPosition, duration) - } - saveEpisodeHistory(currentExtEpisode) + // Update the episode's progress and history + launchIO { + if (cause == "playback_completion" || (currentPosition == duration && duration == 0L)) { + saveEpisodeProgress(currentExtEpisode, anime, currentExtEpisode.totalSeconds, currentExtEpisode.totalSeconds) + } else { + saveEpisodeProgress(currentExtEpisode, anime, currentPosition, duration) } + saveEpisodeHistory(currentExtEpisode) } } @@ -480,7 +480,7 @@ class ExternalIntents { companion object { - private val externalIntents: ExternalIntents by injectLazy() + val externalIntents: ExternalIntents by injectLazy() /** * Used to direct the [Intent] of a chosen episode to an external player. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesTab.kt index a0a5ce6919..8ec0054f64 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesTab.kt @@ -27,8 +27,6 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.entries.anime.AnimeScreen import eu.kanade.tachiyomi.ui.home.HomeScreen import eu.kanade.tachiyomi.ui.main.MainActivity -import eu.kanade.tachiyomi.ui.player.ExternalIntents -import eu.kanade.tachiyomi.ui.player.PlayerActivity import eu.kanade.tachiyomi.ui.player.settings.PlayerPreferences import kotlinx.coroutines.flow.collectLatest import tachiyomi.core.util.lang.launchIO @@ -46,22 +44,11 @@ fun Screen.animeUpdatesTab( val navigateUp: (() -> Unit)? = if (fromMore) navigator::pop else null - fun openEpisodeInternal(context: Context, animeId: Long, episodeId: Long) { - context.startActivity(PlayerActivity.newIntent(context, animeId, episodeId)) - } - - suspend fun openEpisodeExternal(context: Context, animeId: Long, episodeId: Long) { - context.startActivity(ExternalIntents.newIntent(context, animeId, episodeId)) - } - suspend fun openEpisode(updateItem: AnimeUpdatesItem, altPlayer: Boolean = false) { val playerPreferences: PlayerPreferences by injectLazy() val update = updateItem.update - if (playerPreferences.alwaysUseExternalPlayer().get() != altPlayer) { - openEpisodeExternal(context, update.animeId, update.episodeId) - } else { - openEpisodeInternal(context, update.animeId, update.episodeId) - } + val extPlayer = playerPreferences.alwaysUseExternalPlayer().get() != altPlayer + MainActivity.startPlayerActivity(context, update.animeId, update.episodeId, extPlayer) } return TabContent( diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/Constants.kt b/core/src/main/java/eu/kanade/tachiyomi/core/Constants.kt index b07cd1815e..f829cb7da9 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/core/Constants.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/core/Constants.kt @@ -9,11 +9,6 @@ object Constants { const val MAIN_ACTIVITY = "eu.kanade.tachiyomi.ui.main.MainActivity" - // Player Constants - const val REQUEST_INTERNAL = 102 - - const val REQUEST_EXTERNAL = 103 - // Shortcut actions const val SHORTCUT_ANIMELIB = "eu.kanade.tachiyomi.SHOW_ANIMELIB" const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY"