Мои коды следующие: :
Код: Выделить всё
package com.android.wounddet.camera
import android.*
import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
import android.content.pm.*
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CaptureRequest
import android.media.ImageReader
import android.os.*
import android.provider.MediaStore
import android.util.Log
import android.util.Size
import android.view.*
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.*
import androidx.compose.ui.platform.*
import androidx.compose.ui.unit.*
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.*
import java.lang.Exception
@Composable
fun CamPreview(
onImageCaptured: (Bitmap) -> Unit,
onImageDCaptured: (ByteArray) -> Unit,
onDismiss: () -> Unit
) {
var captureSession: CameraCaptureSession? = null
var cameraDevice: CameraDevice? = null
var imageReader: ImageReader? = null
var depthImageReader: ImageReader? = null
var handlerThread: HandlerThread? = null
var handler: Handler? = null
var errorMessage by remember {mutableStateOf(null)}
var supportsDep: Boolean = false
Box(modifier = Modifier.fillMaxSize()) {
// Preview Window
AndroidView(
factory = {context ->
TextureView(context).apply {
surfaceTextureListener = object: TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(
surfaceTexture: SurfaceTexture,
width: Int,
height: Int
) {
handlerThread = HandlerThread("CameraThread").apply {start()}
handler = Handler(handlerThread!!.looper)
val camManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
val camID = getDepSupportedCamID(camManager)
val characteristics = camID?.let {camManager.getCameraCharacteristics(it)}
val capabilities =
characteristics?.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
supportsDep =
(capabilities?.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) == true)
if(supportsDep) {
showError("No DEPTH16 supported camera found.")
Log.d("CamPreview", "No DEPTH16 supported camera found.")
onDismiss()
return
}
if(camID == null) {
showError("No camera found.")
Log.d("CamPreview", "No camera found.")
onDismiss()
return
}
if(ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
camManager.openCamera(camID, object: CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
cameraDevice = camera
val characteristics = camID?.let {camManager.getCameraCharacteristics(it)}
val map =
characteristics?.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
val previewSize =
map?.getOutputSizes(SurfaceHolder::class.java)
?.maxByOrNull {it.width * it.height} ?: Size(640, 480)
val width = previewSize.width
val height = previewSize.height
val surface = android.view.Surface(surfaceTexture)
imageReader =
ImageReader.newInstance(width, height, ImageFormat.JPEG, 5).apply {
setOnImageAvailableListener({reader ->
val image = reader.acquireNextImage()
val buffer = image.planes[0].buffer
val data = ByteArray(buffer.remaining())
buffer.get(data)
image.close()
Log.d("CamPreview", "I'm here!")
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
onImageCaptured(bitmap)
}, handler)
}
depthImageReader =
ImageReader.newInstance(width, height, ImageFormat.DEPTH16, 5).apply {
setOnImageAvailableListener({reader ->
val image = reader.acquireNextImage()
val buffer = image.planes[0].buffer
val data = ByteArray(buffer.remaining())
buffer.get(data)
onImageDCaptured(data)
image.close()
}, handler)
}
val surfaces: List
if(supportsDep) surfaces =
listOf(surface, imageReader!!.surface, depthImageReader!!.surface)
else surfaces = listOf(surface, imageReader!!.surface)
camera.createCaptureSession(
surfaces,
object: CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
captureSession = session
session.setRepeatingRequest(
camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
.apply {
addTarget(surface)
}.build(),
null,
handler
)
}
override fun onConfigureFailed(session: CameraCaptureSession) {
showError("Camera configuration failed.")
Log.d("CamPreview", "Camera configuration failed.")
onDismiss()
}
},
handler
)
}
override fun onDisconnected(camera: CameraDevice) {
cameraDevice?.close()
}
override fun onError(camera: CameraDevice, error: Int) {
showError("Camera error: $error")
Log.d("CamPreview", "Camera error: $error")
onDismiss()
}
}, handler)
}
}
fun getDepSupportedCamID(camManager: CameraManager): String? {
for(cameraId in camManager.cameraIdList) {
val characteristics = camManager.getCameraCharacteristics(cameraId)
// Check the camera's facing direction
val facing = characteristics.get(CameraCharacteristics.LENS_FACING)
// Check if the device supports DEPTH16 format
val capabilities =
characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
if(capabilities?.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) == true) {
// Prefer rear-facing camera
if(facing == CameraCharacteristics.LENS_FACING_BACK) {
return cameraId
}
}
}
// If no rear-facing camera found, return another camera ID that supports DEPTH16
for(cameraId in camManager.cameraIdList) {
val characteristics = camManager.getCameraCharacteristics(cameraId)
val capabilities =
characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
if(capabilities?.contains(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT) == true) {
return cameraId
}
}
// If no camera supports DEPTH16, return rear-facing camera ID
for(cameraId in camManager.cameraIdList) {
val characteristics = camManager.getCameraCharacteristics(cameraId)
val facing = characteristics.get(CameraCharacteristics.LENS_FACING)
if(facing == CameraCharacteristics.LENS_FACING_BACK) {
return cameraId
}
}
return null
}
fun showError(message: String) {
errorMessage = message
}
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
return true
}
}
}
},
modifier = Modifier.fillMaxSize()
)
errorMessage?.let {message ->
AlertDialog(
onDismissRequest = {errorMessage = null;},
title = {Text("Tip")},
text = {Text(message)},
confirmButton = {
Button(onClick = {errorMessage = null;}) {Text("OK")}
}
)
}
Button(
onClick = {
cameraDevice?.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)?.apply {
addTarget(imageReader!!.surface)
if(supportsDep) addTarget(depthImageReader!!.surface)
}?.build()?.let {
captureSession?.capture(it, null, handler)
}
onDismiss()
},
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(16.dp)
) {
Text("Capture")
}
}
// Releasing Resources
DisposableEffect(Unit) {
onDispose {
captureSession?.close()
cameraDevice?.close()
imageReader?.close()
depthImageReader?.close()
handlerThread?.quitSafely()
}
}
}
Что может быть причиной того, что ImageReader.setOnImageAvailableListener() пропускает выполнение своего кода блокировать, и какие шаги я могу предпринять для дальнейшего устранения этой проблемы? Есть ли что-то особенное в настройке CaptureRequest или ImageReader камеры 2, которое я, возможно, упустил из виду?
Кстати, я пробовал запускать это приложение на разных типах телефонов, и я уверен, что они должны поддерживают вывод данных о глубине, но ни один из них не ответил с поддержкой изображений DEPTH16. Я не знаю, действительно ли эти телефоны не поддерживают изображения такого типа, или что-то не так с тем, как я их запрашиваю.
Спасибо за помощь!< /p>
Ответ на комментарий dev.bmax: Я попробовал изменить свой код на более новую версию, но он по-прежнему не работает. Не могли бы вы дать еще несколько более четких предложений? спасибо
Обновление: я пытался сделать это другим методом, но столкнулся с той же проблемой. Код и вопрос выше были обновлены до более новой версии. пожалуйста, помогите.
Подробнее здесь: https://stackoverflow.com/questions/791 ... not-execut
Мобильная версия