我有一个活动撰写应用程序,并且希望防止在单个屏幕中截屏。但是,将
LayoutParams.FLAG_SECURE
应用于活动窗口将阻止此活动中所有屏幕的屏幕截图。
我知道我可以获取窗口并更改它,但必须在调用
setContent
之前完成。
有现成的解决方案吗?当我搜索时,什么也没找到。
我知道我可以将我想要阻止屏幕截图的屏幕放在不同的活动中,但我宁愿先看看是否有一个适合撰写的解决方案。
您需要观察生命周期,然后适当地设置安全标志。
这篇文章看起来不错,尽管我发现我没有看到 ON_START 生命周期事件,所以我根据 ON_RESUME 做了我的。
我已经有了一个生命周期观察者,所以我这样做了:
Composable
fun Lifecycle.observeAsState(): State<Lifecycle.Event> {
val state = remember { mutableStateOf(Lifecycle.Event.ON_ANY) }
DisposableEffect(this) {
val observer = LifecycleEventObserver { _, event ->
state.value = event
}
addObserver(observer)
onDispose {
removeObserver(observer)
}
}
return state
}
@Composable
fun ProtectScreen() {
val lifecycleState by LocalLifecycleOwner.current.lifecycle.observeAsState()
val activity = LocalContext.current.getActivity()
/* When screen has focus, set secure flag */
when (lifecycleState) {
Lifecycle.Event.ON_RESUME -> activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
Lifecycle.Event.ON_PAUSE -> activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
else -> Unit
}
/* Also reset the flag when the composable is disposed */
DisposableEffect(Unit) {
onDispose { activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) }
}
}
其中(如文章中所示)Context.getActivity() 是一个非常标准的扩展方法,用于获取给定上下文(可以是 ContextWrapper)的活动
我是这样做的 LifecycleEventListener.kt
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
@Composable
fun ComponentActivity.LifecycleEventListener(event: (Lifecycle.Event) -> Unit) {
val eventHandler by rememberUpdatedState(newValue = event)
val lifecycle = [email protected]
DisposableEffect(lifecycle) {
val observer = LifecycleEventObserver { _, event ->
eventHandler(event)
}
lifecycle.addObserver(observer)
onDispose {
lifecycle.removeObserver(observer)
}
}
}
受保护的屏幕.kt
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.Lifecycle
@Composable
fun ProtectedScreen() {
val activityContext = LocalContext.current as ComponentActivity
activityContext.LifecycleEventListener(event = { lifecycleEvent ->
when (lifecycleEvent) {
Lifecycle.Event.ON_RESUME -> {
activityContext.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
Lifecycle.Event.ON_PAUSE -> {
activityContext.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
}
else -> return@LifecycleEventListener
}
})
DisposableEffect(Unit) {
onDispose { activityContext.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) }
}
}