使用 MediaProjection API 在屏幕录制期间捕获屏幕截图

问题描述 投票:0回答:1

我有一个服务课程,我正在其中捕获屏幕录制。我想在这堂课上截图,但我还没有找到任何合适的方法来做到这一点。任何人都可以建议一种在服务类中截取屏幕截图的方法吗?

这是我的屏幕录制期间初始化的 mediaProjection 和 virtualDisplay 对象

mMediaProjection = (Objects.requireNonNull(
    getSystemService(
        MEDIA_PROJECTION_SERVICE
    )
) as MediaProjectionManager).getMediaProjection(
    mResultCode,
    mResultData!!
)

mVirtualDisplay = mMediaProjection!!.createVirtualDisplay(
    TAG,
    mScreenWidth,
    mScreenHeight,
    mScreenDensity,
    DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
    mMediaRecorder!!.surface,
    null,
    null
)

这是我的截图代码

var imageReader: ImageReader? = null // Initialize as needed

// Call this function to capture a screenshot
private fun captureScreenshot() {
    if (imageReader == null) {
        // Set up ImageReader to capture the screen content
        val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val metrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(metrics)
        val screenDensity = metrics.densityDpi
        val screenWidth = metrics.widthPixels
        val screenHeight = metrics.heightPixels
        imageReader = ImageReader.newInstance(screenWidth, screenHeight, ImageFormat.RGB_565, 1)

        // Set the OnImageAvailableListener to handle new images
        imageReader!!.setOnImageAvailableListener({ reader ->
            // Process the captured image data
            val image = reader.acquireLatestImage()
            if (image != null) {
                try {
                    // Your image processing logic here
                    processImage(image)
                } finally {
                    // Always close the image to avoid resource leaks
                    image.close()
                }
            }
        }, Handler())
    }

}

private fun processImage(image: Image) {
    val planes = image.planes
    val buffer = planes[0].buffer
    val pixelStride = planes[0].pixelStride
    val rowStride = planes[0].rowStride
    val rowPadding = rowStride - pixelStride * image.width

    // Create a Bitmap to hold the screenshot
    val bitmap = Bitmap.createBitmap(
        image.width + rowPadding / pixelStride,
        image.height,
        Bitmap.Config.ARGB_8888
    )

    bitmap.copyPixelsFromBuffer(buffer)

    // Save the bitmap to a file (You may want to handle this more appropriately)
    saveBitmapToFile(bitmap)
}

private fun getParentFolder(): String {
    return "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)}/${
        getString(R.string.app_name)
    }"
}

private fun saveBitmapToFile(bitmap: Bitmap) {
    Log.d("de_save", "saveBitmapToFile: ")
    try {
        // Save the bitmap to a file (You may want to handle this more appropriately)
        val savePath = getFolder()
        Log.d("de_save", "saveBitmapToFile: savepath: $savePath")
        val file = File(savePath, "ScreenShot_${System.currentTimeMillis()}")
        val fileOutputStream = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)
        fileOutputStream.close()

        ToastUtils.showToast("Screenshot Taken")

    } catch (e: IOException) {
        e.printStackTrace()
    }
}

private fun getFolder(): String {
    val location = getParentFolder() + File.separator + "ScreenShot"
    val file = File(location)
    if (!file.exists()) {
        file.mkdirs()
    }
    return location
}

使用此代码 setOnImageAvailableListener 永远不会被调用。

android kotlin screenshot screen-recording android-mediaprojection
1个回答
0
投票

你应该在createVirtualDisplay中使用ImageReader的surface。但是在Android14中会中断录屏。

© www.soinside.com 2019 - 2024. All rights reserved.