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
}
我正在学习一些 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
}