I'm trying to take a screenshot after I minimize my App and enter Floating Window Mode (like Facebook Messenger) so when I click on the minimized icon, I can take a screenshot. I found some relevant samples on screen capture: https://gist.github.com/ch8n/73b937d49b4347e0cab113b038ba6046 and Mirroring without capture: https://github.com/android/media-samples/tree/main/ScreenCapture but didn't find any example about the usage with services and jetpack compose and eventually how to use it together. The wished behavior is like in the added picture.
MainActivity.kt
class MainActivity : ComponentActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MisInfoTheme {
Column(
Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(onClick = {
startService(Intent(this@MainActivity, FloatingWindowService::class.java))
}) {
Text(text = "Floating Widget")
}
}
}
}
}
}
FloatingWindowScreen.kt
@Composable
fun floatWindowScreen() {
val context = LocalContext.current
Box(
modifier = Modifier
.clip(RoundedCornerShape(10.dp))
.width(200.dp)
.height(50.dp)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
ClickableText(
text = AnnotatedString("On click take screenshot and disoplay it in the original app"),
onClick = {
Toast.makeText(context, "TODO", Toast.LENGTH_SHORT).show()
}
)
}
}
FloatingWindowService.kt
class FloatingWindowService : Service() {
private val TAG = "FloatingWindowService"
private var resultCode = 0
private val windowManager get() = getSystemService(WINDOW_SERVICE) as WindowManager
private val params = initWindowManagerParams()
override fun onBind(intent: Intent): IBinder? = null
override fun onCreate() {
super.onCreate()
drawFloatingWindow()
}
private fun initWindowManagerParams(): WindowManager.LayoutParams {
val paramType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_PHONE
}
val paramFlags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
0,
0,
paramType,
paramFlags,
PixelFormat.TRANSLUCENT
)
params.gravity = Gravity.TOP or Gravity.LEFT
return params
}
private fun drawFloatingWindow() {
val composeView = ComposeView(this)
composeView.setContent {
floatWindowScreen()
}
// Trick The ComposeView into thinking we are tracking lifecycle
val viewModelStore = ViewModelStore()
val lifecycleOwner = FloatingWindowLifeCycleOwner()
lifecycleOwner.performRestore(null)
lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
ViewTreeLifecycleOwner.set(composeView, lifecycleOwner)
ViewTreeViewModelStoreOwner.set(composeView) { viewModelStore }
composeView.setViewTreeSavedStateRegistryOwner(lifecycleOwner)
windowManager.addView(composeView, params)
}
}