Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Jetpack Compose equivalent for android:keepScreenOn to keep screen alive?

I have a Composable that uses a Handler to slowly update the alpha of an image inside a composable. However, I'm seeing that the screen turns off before the animation could complete.

In XML layouts, we could keep it alive using
android:keepScreenOn
or
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

Is there a way to do this using compose without using the wake lock permission?

like image 554
Bharadwaj Giridhar Avatar asked Sep 03 '21 04:09

Bharadwaj Giridhar


People also ask

Is Android jetpack compose stable?

Today, we're releasing version 1.2 of Jetpack Compose, Android's modern, native UI toolkit, continuing to build out our roadmap.

Is jetpack compose the future of Android development?

Jetpack Compose comes with all the functionality needed to build a rich and responsive application UI and features full interoperability with current Android views, making it easy for developers to implement in existing projects.

Is jetpack compose available on Android Studio?

Stay organized with collections Save and categorize content based on your preferences. For the best experience developing with Jetpack Compose, download and install Android Studio.

What is mutableStateOf?

mutableStateOf creates an observable MutableState<T> , which is an observable type integrated with the compose runtime. interface MutableState<T> : State<T> { override var value: T. } Any changes to value will schedule recomposition of any composable functions that read value .


3 Answers

You can use LocalContext to get activity, and it has a window on which you can apply needed flags.

In such cases, when you need to run some code on both view appearance and disappearance, DisposableEffect can be used:

@Composable
fun KeepScreenOn() {
    val context = LocalContext.current
    DisposableEffect(Unit) {
        val window = context.findActivity()?.window
        window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        onDispose {
            window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }
}

fun Context.findActivity(): Activity? {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    return null
}

Usage: when screen appears flag is set to on, and when disappears - it's cleared.

@Composable
fun Screen() {
    KeepScreenOn()
}

As @Louis CAD correctly pointed out, you can have problems if you use this "view" in many views: if one view appears that uses it, and then disappears previous views that also used it, it will reset the flag.

I haven't found a way of tracking flags state to update the view, I think @Louis CAD solution is OK until Compose have some system support.

like image 116
Philip Dukhov Avatar answered Oct 18 '22 04:10

Philip Dukhov


This one should be safe from any interference if you have multiple usages in the same composition:

@Composable
fun KeepScreenOn() = AndroidView({ View(it).apply { keepScreenOn = true } })

Usage is then as simple as that:

if (screenShallBeKeptOn) {
    KeepScreenOn()
}
like image 11
Louis CAD Avatar answered Oct 18 '22 03:10

Louis CAD


In a more Compose way:

@Composable
fun KeepScreenOn() {
    val currentView = LocalView.current
    DisposableEffect(Unit) {
        currentView.keepScreenOn = true
        onDispose {
            currentView.keepScreenOn = false
        }
    }
}

This will be disposed of as soon as views disappear from the composition. Usage is as simple as:

@Composable
fun Screen() {
    KeepScreenOn()
}
like image 5
FireZenk Avatar answered Oct 18 '22 04:10

FireZenk