Android CameraX 图像捕获 onImageSaved 从不运行

Android CameraX image capture onImageSaved never runs

我正在学习一些 camerax 教程,我正在尝试让图像捕获和保存正常工作,但是 'onImageSaved' 函数从未被调用 ,即使我可以获得图像位置的 Uri,它也没有指向任何内容。我花了几个小时试图对此进行调试,但无法弄清楚出了什么问题。 我试过检查文件访问权限,这不是问题。

private fun takePhoto(){
    // Get a stable reference of the modifiable image capture use case
    val imageCapture = imageCapture ?: return

    // Create time-stamped output file to hold the image
    //val photoFile = File(externalMediaDirs[0],"JPEG_${System.currentTimeMillis()}.jpg")
    val directory: File = applicationContext.getDir("imageDir", Context.MODE_PRIVATE)
    val photoFile = File(directory, "JPEG_${System.currentTimeMillis()}.jpg")

    // Create output options object which contains file + metadata
    val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
    
    // Convert filepath to Uri
    val imageUri = Uri.fromFile(photoFile)

    // Set up image capture listener, which is triggered after photo has been taken
    imageCapture.takePicture(
        outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
            override fun onError(exc: ImageCaptureException) {
                Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
            }

            override fun onImageSaved(output: ImageCapture.OutputFileResults) {
                // TODO This never runs
                val msg = "Photo capture succeeded: $imageUri"
                Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
                Log.d(TAG, msg)
            }
        })

    // Send our image Uri back to the demo app & finish this activity
    val intent = Intent()
    intent.putExtra("ImageUri", imageUri)
    runOnUiThread {
        setResult(2, intent)
        finish()
    }
}

第一张截图

 imageCapture.takePicture(ContextCompat.getMainExecutor(requireContext()),object :
        ImageCapture.OnImageCapturedCallback() {
        override fun onCaptureSuccess(image: ImageProxy) {
            super.onCaptureSuccess(image)
            val bitmap =imageProxyToBitmap(image)
            val file  = bitmap?.let {
                AppUtils.saveImage(requireContext(),
                    it,SimpleDateFormat(CameraFragment.FILENAME_FORMAT, 
                 Locale.US).format(System.currentTimeMillis()) + ".png")
            }
            val savedUri = Uri.fromFile(file)

            if (savedUri != null) {
              // here your save image uri path 
            }

        }

        override fun onError(exception: ImageCaptureException) {
            super.onError(exception)

        }

    })

为 imageProxyToBitmap 创建函数

 private fun imageProxyToBitmap(image: ImageProxy): Bitmap {
    val planeProxy = image.planes[0]
    val buffer: ByteBuffer = planeProxy.buffer
    val bytes = ByteArray(buffer.remaining())
    buffer.get(bytes)
    return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
}

然后在 util 或任何你想要的地方创建 saveImage class

  @Throws(IOException::class)
 fun saveImage(context: Context,bitmap: Bitmap,  name: String): File? {
    val saved: Boolean
    var image : File?=null
    val fos: OutputStream? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val resolver: ContentResolver = context.contentResolver
        val contentValues = ContentValues()
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name)
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/")
        val imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
        image =File(imageUri?.let { FileUriUtils.getRealPath(context, uri = it) })
        imageUri?.let { resolver.openOutputStream(it) }
    } else {
        val imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString() + File.separator
        val file = File(imagesDir)
        if (!file.exists()) {
            file.mkdir()
        }

        image = File(imagesDir, "$name.png")
        FileOutputStream(image)
    }
    saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
    fos?.flush()
    fos?.close()

    return image
}