【Android】Jetpack Composeでwakelock対応(スリープさせない)をする【Tips】


個人的なメモも兼ねて

概要

Androidアプリにおいて、何らかの都合で画面をスリープ状態にさせないようにする場合は専用の実装が必要です。
Android公式の推奨方法はFLAG_KEEP_SCREEN_ONをActivityから呼ぶ実装です。

    // コードで呼ぶ例
    class MainActivity : Activity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }

ところで、Jetpack Compose対応する場合、ActivityからsetContentを呼んで実装していきますが、Jetpack ComposeのComposable側からはActivityにアクセスできないように見えます。どのように実装すればいいのでしょうか。

結論

Stack Overflowで紹介されていました。

LocalContextを使うとcontextを取得できるため、ここからActivityを取得し、フラグを追加することができます。

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

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

もうちょっと解説

既存のAndroidフレームワークとの連携については以下のページで解説されています。

CompositionLocalを使用している一連のクラス群を使うことでAndroidフレームワークの値にアクセスできます。LocalContextでContextが取得できる他、LocalConfigurationでConfigration(端末のサイズなど)を得たり、LocalViewで現在のViewそのものを得ることもできます。覚えておくと今後役に立つでしょう。

参考