【发布时间】:2021-04-02 17:36:08
【问题描述】:
我正在使用 Android MediaProjection Api 编写一个屏幕截图应用程序,其中一个覆盖按钮显示在所有内容的顶部,用户可以单击它以在任何地方捕获屏幕截图。由于 MediaProjection 记录屏幕内容,因此覆盖按钮本身位于捕获的屏幕截图中。为了在截屏时隐藏按钮,我尝试将视图visibility 设置为INVISIBLE,截屏并将其还原为VISIBLE,但由于更改可见性是Android 中的异步操作,有时覆盖按钮仍然存在出现在录制的镜头中。
我改成下面的 sn-p 并且它在我的实验中起作用:
floatingButton?.setOnClickListener { view ->
view.visibility = View.INVISIBLE
view.postDelayed(100) {
takeShot()
view.post {view.visibility = View.VISIBLE}
}
}
但这基本上是说我感觉很好,在 100 毫秒内,按钮将不可见。这不是一个好的解决方案,对于视频,100 毫秒内的内容可能与用户当时实际看到的内容大不相同。
Android 不提供 onVisibiltyChangedListener 之类的东西,那么在确保视图可见性发生变化后,我该如何执行任务?
编辑 1
这是takeShot() 方法:
private fun takeShot() {
val image = imageReader.acquireLatestImage()
val bitmap = image?.run {
val planes = image.planes
val buffer: ByteBuffer = planes[0].buffer
val pixelStride = planes[0].pixelStride
val rowStride = planes[0].rowStride
val rowPadding = rowStride - pixelStride * width
val bitmap = Bitmap.createBitmap(
width + rowPadding / pixelStride,
height,
Bitmap.Config.ARGB_8888
)
bitmap.copyPixelsFromBuffer(buffer)
image.close()
bitmap
}
bitmap?.let{
serviceScope.launch {
gallery.store(it)
}
}
}
代码在前台服务中,当用户接受媒体投影时,我创建ImageReader 和VirtualDisplay:
imageReader = ImageReader.newInstance(size.width, size.height, PixelFormat.RGBA_8888, 2)
virtualDisplay = mediaProjection.createVirtualDisplay(
"screen-mirror",
size.width,
size.height,
Resources.getSystem().displayMetrics.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, // TODO: DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC ??
imageReader.surface, null, null
)
mediaProjection.registerCallback(object : MediaProjection.Callback() {
override fun onStop() {
virtualDisplay.release()
mediaProjection.unregisterCallback(this)
}
}, null)
我试过没有暂停和协程的东西,结果是一样的,所以它们很可能与问题无关。
【问题讨论】:
-
我尝试使用 AndroidX
View.doOnPreDraw但没有成功。你能解释一下吗? -
stackoverflow.com/a/32778292/4168607 。我猜这应该可行。
-
我使用了该方法并通过设置日志,我看到当覆盖按钮不可见时,实际上调用了捕获方法 (
imageReader.acquireLatestImage()),但它有时仍会出现在屏幕截图中!acquireLatestImage()似乎没有必要给你“最新图像”。时间是不确定的。 -
你能把
takeShot()方法加上 question 吗?还要在其他设备上检查它。
标签: android android-view visibility android-mediaprojection