【问题标题】:Android CameraX image capture onImageSaved never runsAndroid CameraX 图像捕获 onImageSaved 永远不会运行
【发布时间】:2022-01-06 21:17:53
【问题描述】:

我正在关注一些 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()
    }
}

【问题讨论】:

  • 你好,伙计,我面临着同样的问题,它发生在 android 10 中,在 adnroid 11 中它的工作非常适合你可以点击 a=image 然后保存位图 int 文件

标签: android android-studio kotlin android-camerax


【解决方案1】:

第一张图片

 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 类

  @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
}

【讨论】:

  • 这一行:image =File(imageUri?.let { FileUriUtils.getRealPath(context, uri = it) }) 需要你在 utils 中有另一个名为 getRealPath 的方法,否则这是一个很好的答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 2015-05-31
  • 2019-10-10
  • 1970-01-01
  • 2014-11-06
相关资源
最近更新 更多