Skip to content

Commit

Permalink
Use CameraXViewfinder from new camerax-compose artifact
Browse files Browse the repository at this point in the history
  • Loading branch information
JolandaVerhoef committed Nov 14, 2024
1 parent 67d823a commit 371e9f8
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 185 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ secrets {

android {
namespace = "com.google.android.samples.socialite"
compileSdk = 34
compileSdk = 35

defaultConfig {
applicationId = "com.google.android.samples.socialite"
Expand Down Expand Up @@ -125,10 +125,10 @@ dependencies {
implementation(libs.concurrent.kts)

implementation(libs.camera.core)
implementation(libs.camera.compose)
implementation(libs.camera2)
implementation(libs.camera.lifecycle)
implementation(libs.camera.view)
implementation(libs.camera.viewfinder.compose)

implementation(libs.media3.common)
implementation(libs.media3.effect)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ fun Camera(
}

val viewFinderState by viewModel.viewFinderState.collectAsStateWithLifecycle()
val surfaceRequest by viewModel.surfaceRequest.collectAsStateWithLifecycle()
var rotation by remember { mutableStateOf(Surface.ROTATION_0) }

DisposableEffect(lifecycleOwner, context) {
Expand All @@ -126,40 +127,31 @@ fun Camera(

rotationProvider.addListener(Dispatchers.Main.asExecutor(), rotationListener)

viewModel.startPreview(lifecycleOwner, captureMode, cameraSelector, rotation)

onDispose {
rotationProvider.removeListener(rotationListener)
}
}

val onPreviewSurfaceProviderReady: (Preview.SurfaceProvider) -> Unit = {
surfaceProvider = it
viewModel.startPreview(lifecycleOwner, it, captureMode, cameraSelector, rotation)
}

fun setCaptureMode(mode: CaptureMode) {
captureMode = mode
surfaceProvider?.let { provider ->
viewModel.startPreview(
lifecycleOwner,
provider,
captureMode,
cameraSelector,
rotation,
)
}
viewModel.startPreview(
lifecycleOwner,
captureMode,
cameraSelector,
rotation,
)
}

fun setCameraSelector(selector: CameraSelector) {
cameraSelector = selector
surfaceProvider?.let { provider ->
viewModel.startPreview(
lifecycleOwner,
provider,
captureMode,
cameraSelector,
rotation,
)
}
viewModel.startPreview(
lifecycleOwner,
captureMode,
cameraSelector,
rotation,
)
}

@SuppressLint("MissingPermission")
Expand Down Expand Up @@ -249,7 +241,7 @@ fun Camera(
) {
ViewFinder(
viewFinderState.cameraState,
onPreviewSurfaceProviderReady,
surfaceRequest,
viewModel::setZoomScale,
)
}
Expand All @@ -262,7 +254,7 @@ fun Camera(
) {
ViewFinder(
viewFinderState.cameraState,
onPreviewSurfaceProviderReady,
surfaceRequest,
viewModel::setZoomScale,
)
}
Expand Down Expand Up @@ -311,7 +303,11 @@ fun Camera(
}

@Composable
fun CameraControls(captureMode: CaptureMode, onPhotoButtonClick: () -> Unit, onVideoButtonClick: () -> Unit) {
fun CameraControls(
captureMode: CaptureMode,
onPhotoButtonClick: () -> Unit,
onVideoButtonClick: () -> Unit,
) {
val activeButtonColor =
ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
val inactiveButtonColor =
Expand All @@ -335,7 +331,12 @@ fun CameraControls(captureMode: CaptureMode, onPhotoButtonClick: () -> Unit, onV
}

@Composable
fun ShutterButton(captureMode: CaptureMode, onPhotoCapture: () -> Unit, onVideoRecordingStart: () -> Unit, onVideoRecordingFinish: () -> Unit) {
fun ShutterButton(
captureMode: CaptureMode,
onPhotoCapture: () -> Unit,
onVideoRecordingStart: () -> Unit,
onVideoRecordingFinish: () -> Unit,
) {
Box(modifier = Modifier.padding(25.dp, 0.dp)) {
if (captureMode == CaptureMode.PHOTO) {
Button(
Expand Down Expand Up @@ -370,15 +371,21 @@ fun ShutterButton(captureMode: CaptureMode, onPhotoCapture: () -> Unit, onVideoR
}

@Composable
fun CameraSwitcher(captureMode: CaptureMode, cameraSelector: CameraSelector, setCameraSelector: KFunction1<CameraSelector, Unit>) {
fun CameraSwitcher(
captureMode: CaptureMode,
cameraSelector: CameraSelector,
setCameraSelector: KFunction1<CameraSelector, Unit>,
) {
if (captureMode != CaptureMode.VIDEO_RECORDING) {
IconButton(onClick = {
if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
setCameraSelector(CameraSelector.DEFAULT_FRONT_CAMERA)
} else {
setCameraSelector(CameraSelector.DEFAULT_BACK_CAMERA)
}
}) {
IconButton(
onClick = {
if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
setCameraSelector(CameraSelector.DEFAULT_FRONT_CAMERA)
} else {
setCameraSelector(CameraSelector.DEFAULT_BACK_CAMERA)
}
},
) {
Icon(
imageVector = Icons.Default.Autorenew,
contentDescription = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.camera.core.FocusMeteringAction
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.core.SurfaceRequest
import androidx.camera.core.UseCaseGroup
import androidx.camera.core.resolutionselector.AspectRatioStrategy
import androidx.camera.core.resolutionselector.ResolutionSelector
Expand All @@ -60,6 +61,7 @@ import java.text.SimpleDateFormat
import java.util.Locale
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

private const val TAG = "CameraViewModel"
Expand All @@ -84,9 +86,17 @@ class CameraViewModel @Inject constructor(
.setAspectRatioStrategy(aspectRatioStrategy)
.build()

private val _surfaceRequest = MutableStateFlow<SurfaceRequest?>(null)
val surfaceRequest: StateFlow<SurfaceRequest?> = _surfaceRequest

private val previewUseCase = Preview.Builder()
.setResolutionSelector(resolutionSelector)
.build()
.build().apply {
setSurfaceProvider { newSurfaceRequest ->
Log.d("JOLO", "New surface request")
_surfaceRequest.value = newSurfaceRequest
}
}

private val imageCaptureUseCase = ImageCapture.Builder()
.setResolutionSelector(resolutionSelector)
Expand Down Expand Up @@ -141,7 +151,6 @@ class CameraViewModel @Inject constructor(

fun startPreview(
lifecycleOwner: LifecycleOwner,
surfaceProvider: Preview.SurfaceProvider,
captureMode: CaptureMode,
cameraSelector: CameraSelector,
rotation: Int,
Expand All @@ -156,9 +165,7 @@ class CameraViewModel @Inject constructor(
}
var extensionsCameraSelector: CameraSelector? = null
val useCaseGroupBuilder = UseCaseGroup.Builder()

previewUseCase.setSurfaceProvider(surfaceProvider)
useCaseGroupBuilder.addUseCase(previewUseCase)
.addUseCase(previewUseCase)

if (captureMode == CaptureMode.PHOTO) {
try {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

package com.google.android.samples.socialite.ui.camera

import androidx.camera.core.Preview
import androidx.camera.compose.CameraXViewfinder
import androidx.camera.core.SurfaceRequest
import androidx.camera.viewfinder.surface.ImplementationMode
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.rememberTransformableState
Expand All @@ -31,7 +32,7 @@ import androidx.compose.ui.graphics.Color
@Composable
fun ViewFinder(
cameraState: CameraState,
onSurfaceProviderReady: (Preview.SurfaceProvider) -> Unit = {},
surfaceRequest: SurfaceRequest?,
onZoomChange: (Float) -> Unit,
) {
val transformableState = rememberTransformableState(
Expand All @@ -49,11 +50,13 @@ fun ViewFinder(
modifier = Modifier
.transformable(state = transformableState),
) {
CameraXViewfinder(
modifier = Modifier.fillMaxSize(),
implementationMode = ImplementationMode.PERFORMANCE,
onSurfaceProviderReady = onSurfaceProviderReady,
)
surfaceRequest?.let {
CameraXViewfinder(
modifier = Modifier.fillMaxSize(),
implementationMode = ImplementationMode.EXTERNAL,
surfaceRequest = surfaceRequest,
)
}
}
}
}
2 changes: 1 addition & 1 deletion baselineprofile/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {

android {
namespace = "com.google.android.samples.socialite.baselineprofile"
compileSdk = 34
compileSdk = 35

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
Loading

0 comments on commit 371e9f8

Please sign in to comment.