From b02367c288bab5a0a9fac388b3105165ad2692fe Mon Sep 17 00:00:00 2001 From: ujizin Date: Sat, 9 Dec 2023 18:36:26 +0000 Subject: [PATCH] fix image analysis use case to camera hardware under level 3 --- .../extensions/CameraManagerExtensions.kt | 16 ++++++++++ .../ujizin/camposer/helper/CameraHelper.kt | 14 ++++++++ .../com/ujizin/camposer/state/CameraState.kt | 32 +++++++++++++++++-- 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 camposer/src/main/java/com/ujizin/camposer/extensions/CameraManagerExtensions.kt create mode 100644 camposer/src/main/java/com/ujizin/camposer/helper/CameraHelper.kt diff --git a/camposer/src/main/java/com/ujizin/camposer/extensions/CameraManagerExtensions.kt b/camposer/src/main/java/com/ujizin/camposer/extensions/CameraManagerExtensions.kt new file mode 100644 index 0000000..372d2d6 --- /dev/null +++ b/camposer/src/main/java/com/ujizin/camposer/extensions/CameraManagerExtensions.kt @@ -0,0 +1,16 @@ +package com.ujizin.camposer.extensions + +import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraManager +import com.ujizin.camposer.helper.CameraHelper + +internal fun CameraManager.isImageAnalysisSupported(lensFacing: Int?): Boolean { + val cameraId = cameraIdList.firstOrNull { + getCameraCharacteristics(it).get(CameraCharacteristics.LENS_FACING) == lensFacing + } ?: return false + + val level = getCameraCharacteristics(cameraId) + .get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ?: 0 + + return level >= CameraHelper.compatHardwareLevel3 +} diff --git a/camposer/src/main/java/com/ujizin/camposer/helper/CameraHelper.kt b/camposer/src/main/java/com/ujizin/camposer/helper/CameraHelper.kt new file mode 100644 index 0000000..e0aba3d --- /dev/null +++ b/camposer/src/main/java/com/ujizin/camposer/helper/CameraHelper.kt @@ -0,0 +1,14 @@ +package com.ujizin.camposer.helper + +import android.hardware.camera2.CameraCharacteristics +import android.os.Build + +internal object CameraHelper { + + private const val COMPAT_HARDWARE_LEVEL_3 = 3 + + internal val compatHardwareLevel3: Int = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 + else -> COMPAT_HARDWARE_LEVEL_3 + } +} diff --git a/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt b/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt index cd8795e..504b1fb 100644 --- a/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt +++ b/camposer/src/main/java/com/ujizin/camposer/state/CameraState.kt @@ -1,8 +1,10 @@ package com.ujizin.camposer.state +import android.annotation.SuppressLint import android.content.ContentResolver import android.content.ContentValues import android.content.Context +import android.hardware.camera2.CameraManager import android.net.Uri import android.provider.MediaStore import android.util.Log @@ -26,6 +28,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.ujizin.camposer.extensions.compatMainExecutor +import com.ujizin.camposer.extensions.isImageAnalysisSupported import java.io.File import java.util.concurrent.Executor @@ -216,11 +219,24 @@ public class CameraState(context: Context) { * */ private val useCases: MutableSet = mutableSetOf(IMAGE_ANALYSIS) + private val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as? CameraManager + + /** + * Check if image analysis is supported by camera hardware level. + * */ + public var isImageAnalysisSupported: Boolean by mutableStateOf(isImageAnalysisSupported(camSelector)) + private set + /** * Enable/Disable Image analysis from the camera. * */ - internal var isImageAnalysisEnabled: Boolean = true + internal var isImageAnalysisEnabled: Boolean = isImageAnalysisSupported set(value) { + if (!isImageAnalysisSupported) { + Log.e(TAG, "Image analysis is not supported") + return + } + if (value != field) { if (value) useCases += IMAGE_ANALYSIS else useCases -= IMAGE_ANALYSIS updateUseCases() @@ -229,7 +245,12 @@ public class CameraState(context: Context) { } private fun updateUseCases() { - controller.setEnabledUseCases(useCases.sumOr(captureMode.value)) + try { + controller.setEnabledUseCases(useCases.sumOr(captureMode.value)) + } catch (exception: IllegalStateException) { + Log.e(TAG, "Use case Image Analysis not supported") + controller.setEnabledUseCases(captureMode.value) + } } /** @@ -303,6 +324,7 @@ public class CameraState(context: Context) { /** * Return true if it's recording. * */ + @ExperimentalVideo public var isRecording: Boolean by mutableStateOf(controller.isRecording) private set @@ -523,6 +545,7 @@ public class CameraState(context: Context) { private fun resetCamera() { hasFlashUnit = controller.cameraInfo?.hasFlashUnit() ?: false + isImageAnalysisSupported = isImageAnalysisSupported(camSelector) startZoom() startExposure() } @@ -531,6 +554,11 @@ public class CameraState(context: Context) { acc or current } + @SuppressLint("RestrictedApi") + private fun isImageAnalysisSupported( + cameraSelector: CamSelector + ): Boolean = cameraManager?.isImageAnalysisSupported(cameraSelector.selector.lensFacing) ?: false + /** * Update all values from camera state. * */