Skip to content

Updated video player logic: now it pauses also when another window is occluding it #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 4, 2025
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ dependencies {
implementation(projects.feature.results)

implementation(projects.core.theme)
implementation(projects.core.util)

baselineProfile(projects.benchmark)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,31 @@
*/
package com.android.developers.androidify

import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import android.window.TrustedPresentationThresholds
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import com.android.developers.androidify.navigation.MainNavigation
import com.android.developers.androidify.theme.AndroidifyTheme
import com.android.developers.androidify.util.LocalOcclusion
import dagger.hilt.android.AndroidEntryPoint

@ExperimentalMaterial3ExpressiveApi
@AndroidEntryPoint
class MainActivity : ComponentActivity() {

private val isWindowOccluded = mutableStateOf(false)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

Expand All @@ -46,8 +55,30 @@ class MainActivity : ComponentActivity() {
Color.Transparent.toArgb(),
),
)
MainNavigation()
CompositionLocalProvider(LocalOcclusion provides isWindowOccluded) {
MainNavigation()
}
}
}
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
val minAlpha = 1f
val minFractionRendered = 0.25f
val stabilityRequirements = 500
val presentationThreshold = TrustedPresentationThresholds(
minAlpha, minFractionRendered, stabilityRequirements
)

val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better type safety and to avoid a potentially unsafe cast, it's recommended to use the typed getSystemService(Class<T>) method.

            val windowManager = getSystemService(WindowManager::class.java)

windowManager.registerTrustedPresentationListener(
window.decorView.windowToken,
presentationThreshold,
mainExecutor
) { isMinFractionRendered -> isWindowOccluded.value = !isMinFractionRendered }
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.animation.scaleOut
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -42,7 +43,6 @@ import com.android.developers.androidify.creation.CreationScreen
import com.android.developers.androidify.home.AboutScreen
import com.android.developers.androidify.home.HomeScreen
import com.android.developers.androidify.theme.transitions.ColorSplashTransitionScreen
import com.google.android.gms.oss.licenses.OssLicensesActivity
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity

@ExperimentalMaterial3ExpressiveApi
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.android.developers.androidify.util

import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateOf

val LocalOcclusion = compositionLocalOf { mutableStateOf(false) }

Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class HomeScreenTest {
},
onAboutClicked = {}, // Provide a default or mock value,
videoLink = "",
dancingBotLink = "",
dancingBotLink = ""
)
}
}
Expand All @@ -78,7 +78,7 @@ class HomeScreenTest {
onClickLetsGo = { },
onAboutClicked = {},
videoLink = "",
dancingBotLink = "",
dancingBotLink = ""
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import com.android.developers.androidify.theme.components.AndroidifyTopAppBar
import com.android.developers.androidify.theme.components.AndroidifyTranslucentTopAppBar
import com.android.developers.androidify.theme.components.SquiggleBackground
import com.android.developers.androidify.util.LargeScreensPreview
import com.android.developers.androidify.util.LocalOcclusion
import com.android.developers.androidify.util.PhonePreview
import com.android.developers.androidify.util.isAtLeastMedium
import com.android.developers.androidify.theme.R as ThemeR
Expand All @@ -123,6 +124,7 @@ fun HomeScreen(
onAboutClicked: () -> Unit = {},
) {
val state = homeScreenViewModel.state.collectAsStateWithLifecycle()

if (!state.value.isAppActive) {
AppInactiveScreen()
} else {
Expand Down Expand Up @@ -537,6 +539,7 @@ private fun VideoPlayer(
}

var videoFullyOnScreen by remember { mutableStateOf(false) }
val isWindowOccluded = LocalOcclusion.current
Box(
Modifier
.background(MaterialTheme.colorScheme.surfaceContainerLowest)
Expand All @@ -547,8 +550,8 @@ private fun VideoPlayer(
.then(modifier),
) {
player?.let { currentPlayer ->
LaunchedEffect(videoFullyOnScreen) {
if (videoFullyOnScreen) currentPlayer.play() else currentPlayer.pause()
LaunchedEffect(videoFullyOnScreen, LocalOcclusion.current.value) {
if (videoFullyOnScreen && !isWindowOccluded.value) currentPlayer.play() else currentPlayer.pause()
}

// Render the video
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class HomeScreenScreenshotTest {
onClickLetsGo = { },
onAboutClicked = {},
videoLink = "",
dancingBotLink = "",
dancingBotLink = ""
)
}
}
Expand Down