From 5ab09ac6a5a3f73bada370c0effd453cd19195bc Mon Sep 17 00:00:00 2001 From: Jag Saund Date: Sat, 18 May 2024 19:07:46 -0400 Subject: [PATCH] Wire functionality to show Postview and Processing Progress Indicator - if the device supports process indicator then show process indicator - if the device supports postview then show the postview Test: manually tested using S24 --- .../android/cameraxextensions/MainActivity.kt | 29 +++++++++++++-- .../cameraxextensions/model/CameraUiState.kt | 11 ++++++ .../viewmodel/CameraExtensionsViewModel.kt | 37 ++++++++++++++++++- .../viewstate/CameraPreviewScreenViewState.kt | 28 +++++++++++++- 4 files changed, 98 insertions(+), 7 deletions(-) diff --git a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/MainActivity.kt b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/MainActivity.kt index 45394592..c1741111 100644 --- a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/MainActivity.kt +++ b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/MainActivity.kt @@ -24,7 +24,11 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.camera.extensions.ExtensionMode import androidx.core.app.ActivityCompat -import androidx.lifecycle.* +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import com.example.android.cameraxextensions.adapter.CameraExtensionItem import com.example.android.cameraxextensions.model.CameraState import com.example.android.cameraxextensions.model.CameraUiAction @@ -203,9 +207,10 @@ class MainActivity : AppCompatActivity() { } else { PostCaptureScreenViewState.PostCaptureScreenHiddenViewState } - } - .updateCameraScreen { + }.updateCameraScreen { it.hideCameraControls() + .hideProcessProgressViewState() + .hidePostview() } ) } @@ -220,6 +225,24 @@ class MainActivity : AppCompatActivity() { it.showCameraControls() .enableCameraShutter(true) .enableSwitchLens(true) + .hideProcessProgressViewState() + .hidePostview() + } + ) + } + is CaptureState.CapturePostview -> { + captureScreenViewState.emit( + captureScreenViewState.value + .updateCameraScreen { + it.showPostview(state.bitmap) + } + ) + } + is CaptureState.CaptureProcessProgress -> { + captureScreenViewState.emit( + captureScreenViewState.value + .updateCameraScreen { + it.showProcessProgressViewState(state.progress) } ) } diff --git a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/model/CameraUiState.kt b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/model/CameraUiState.kt index e07fb2b4..94988278 100644 --- a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/model/CameraUiState.kt +++ b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/model/CameraUiState.kt @@ -16,6 +16,7 @@ package com.example.android.cameraxextensions.model +import android.graphics.Bitmap import androidx.camera.core.CameraSelector.LENS_FACING_BACK import androidx.camera.core.CameraSelector.LensFacing import androidx.camera.core.ImageCapture @@ -74,6 +75,16 @@ sealed class CaptureState { */ object CaptureStarted : CaptureState() + /** + * Capture postview is ready + */ + data class CapturePostview(val bitmap: Bitmap): CaptureState() + + /** + * Capture process progress updated with the [progress] value + */ + data class CaptureProcessProgress(val progress: Int): CaptureState() + /** * Capture completed successfully. */ diff --git a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewmodel/CameraExtensionsViewModel.kt b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewmodel/CameraExtensionsViewModel.kt index c53aa38f..8ebcbb0d 100644 --- a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewmodel/CameraExtensionsViewModel.kt +++ b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewmodel/CameraExtensionsViewModel.kt @@ -17,13 +17,13 @@ package com.example.android.cameraxextensions.viewmodel import android.app.Application +import android.graphics.Bitmap import androidx.camera.core.* import androidx.camera.core.CameraSelector.LensFacing import androidx.camera.extensions.ExtensionMode import androidx.camera.extensions.ExtensionsManager import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.view.PreviewView -import androidx.compose.ui.layout.ScaleFactor import androidx.core.net.toUri import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ViewModel @@ -58,7 +58,7 @@ class CameraExtensionsViewModel( private var camera: Camera? = null - private val imageCapture = ImageCapture.Builder() + private var imageCapture = ImageCapture.Builder() .setTargetAspectRatio(AspectRatio.RATIO_16_9) .build() @@ -142,6 +142,19 @@ class CameraExtensionsViewModel( currentCameraUiState.extensionMode ) } + + cameraProvider.unbindAll() + camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector) + + camera?.cameraInfo?.let { + val isPostviewSupported = + ImageCapture.getImageCaptureCapabilities(it).isPostviewSupported + imageCapture = ImageCapture.Builder() + .setTargetAspectRatio(AspectRatio.RATIO_16_9) + .setPostviewEnabled(isPostviewSupported) + .build() + } + val useCaseGroup = UseCaseGroup.Builder() .setViewPort(previewView.viewPort!!) .addUseCase(imageCapture) @@ -223,6 +236,14 @@ class CameraExtensionsViewModel( .setMetadata(metadata) .build() + camera?.cameraInfo?.let { + if (ImageCapture.getImageCaptureCapabilities(it).isCaptureProcessProgressSupported) { + viewModelScope.launch { + _captureUiState.emit(CaptureState.CaptureProcessProgress(0)) + } + } + } + imageCapture.takePicture( outputFileOptions, Dispatchers.Default.asExecutor(), @@ -242,6 +263,18 @@ class CameraExtensionsViewModel( _captureUiState.emit(CaptureState.CaptureFailed(exception)) } } + + override fun onCaptureProcessProgressed(progress: Int) { + viewModelScope.launch { + _captureUiState.emit(CaptureState.CaptureProcessProgress(progress)) + } + } + + override fun onPostviewBitmapAvailable(bitmap: Bitmap) { + viewModelScope.launch { + _captureUiState.emit(CaptureState.CapturePostview(bitmap)) + } + } }) } diff --git a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewstate/CameraPreviewScreenViewState.kt b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewstate/CameraPreviewScreenViewState.kt index 0badce1f..13aecb06 100644 --- a/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewstate/CameraPreviewScreenViewState.kt +++ b/CameraXExtensions/app/src/main/java/com/example/android/cameraxextensions/viewstate/CameraPreviewScreenViewState.kt @@ -16,6 +16,7 @@ package com.example.android.cameraxextensions.viewstate +import android.graphics.Bitmap import com.example.android.cameraxextensions.adapter.CameraExtensionItem /** @@ -25,7 +26,9 @@ import com.example.android.cameraxextensions.adapter.CameraExtensionItem data class CameraPreviewScreenViewState( val shutterButtonViewState: ShutterButtonViewState = ShutterButtonViewState(), val switchLensButtonViewState: SwitchLensButtonViewState = SwitchLensButtonViewState(), - val extensionsSelectorViewState: CameraExtensionSelectorViewState = CameraExtensionSelectorViewState() + val extensionsSelectorViewState: CameraExtensionSelectorViewState = CameraExtensionSelectorViewState(), + val processProgressViewState: ProcessProgressIndicatorViewState = ProcessProgressIndicatorViewState(), + val postviewViewState: PostviewViewState = PostviewViewState() ) { fun hideCameraControls(): CameraPreviewScreenViewState = copy( @@ -49,6 +52,17 @@ data class CameraPreviewScreenViewState( fun setAvailableExtensions(extensions: List): CameraPreviewScreenViewState = copy(extensionsSelectorViewState = extensionsSelectorViewState.copy(extensions = extensions)) + + fun showPostview(bitmap: Bitmap): CameraPreviewScreenViewState = + copy(postviewViewState = PostviewViewState(isVisible = true, bitmap = bitmap)) + + fun hidePostview(): CameraPreviewScreenViewState = copy(postviewViewState = PostviewViewState()) + + fun showProcessProgressViewState(progress: Int): CameraPreviewScreenViewState = + copy(processProgressViewState = ProcessProgressIndicatorViewState(isVisible = true, progress = progress)) + + fun hideProcessProgressViewState(): CameraPreviewScreenViewState = + copy(processProgressViewState = ProcessProgressIndicatorViewState()) } data class CameraExtensionSelectorViewState( @@ -64,4 +78,14 @@ data class ShutterButtonViewState( data class SwitchLensButtonViewState( val isVisible: Boolean = false, val isEnabled: Boolean = false -) \ No newline at end of file +) + +data class ProcessProgressIndicatorViewState( + val isVisible: Boolean = false, + val progress: Int = 0 +) + +data class PostviewViewState( + val isVisible: Boolean = false, + val bitmap: Bitmap? = null +)