mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
feature: adds camera preview
This commit is contained in:
parent
38fc299fc6
commit
6f8b68c7b2
@ -1,17 +1,23 @@
|
|||||||
package app.myzel394.alibi.ui.components.RecorderScreen.organisms
|
package app.myzel394.alibi.ui.components.RecorderScreen.organisms
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.camera.core.Preview
|
||||||
|
import androidx.camera.view.PreviewView
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.CameraAlt
|
import androidx.compose.material.icons.filled.CameraAlt
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
@ -26,11 +32,14 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import app.myzel394.alibi.R
|
import app.myzel394.alibi.R
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus
|
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
|
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
|
||||||
@ -38,6 +47,7 @@ import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus
|
|||||||
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||||
import app.myzel394.alibi.ui.utils.CameraInfo
|
import app.myzel394.alibi.ui.utils.CameraInfo
|
||||||
import app.myzel394.alibi.ui.utils.KeepScreenOn
|
import app.myzel394.alibi.ui.utils.KeepScreenOn
|
||||||
|
import app.myzel394.alibi.ui.utils.getCameraProvider
|
||||||
import com.valentinilk.shimmer.shimmer
|
import com.valentinilk.shimmer.shimmer
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ -79,6 +89,12 @@ fun VideoRecordingStatus(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
_VideoControls(videoRecorder)
|
_VideoControls(videoRecorder)
|
||||||
|
CameraPreview(
|
||||||
|
videoRecorder,
|
||||||
|
modifier = Modifier
|
||||||
|
.aspectRatio(5 / 2F)
|
||||||
|
.padding(horizontal = 12.dp)
|
||||||
|
)
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
_PrimitiveControls(videoRecorder)
|
_PrimitiveControls(videoRecorder)
|
||||||
}
|
}
|
||||||
@ -94,7 +110,11 @@ fun VideoRecordingStatus(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.SpaceBetween,
|
verticalArrangement = Arrangement.SpaceBetween,
|
||||||
) {
|
) {
|
||||||
Box {}
|
CameraPreview(
|
||||||
|
videoRecorder, modifier = Modifier
|
||||||
|
.padding(24.dp)
|
||||||
|
.aspectRatio(3 / 2F)
|
||||||
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
@ -120,6 +140,45 @@ fun VideoRecordingStatus(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CameraPreview(videoRecorder: VideoRecorderModel, modifier: Modifier) {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
|
||||||
|
Box(modifier = modifier.clip(RoundedCornerShape(12.dp))) {
|
||||||
|
|
||||||
|
// Video preview
|
||||||
|
AndroidView(
|
||||||
|
factory = { context ->
|
||||||
|
val previewView = PreviewView(context).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val previewUseCase = Preview.Builder()
|
||||||
|
.build()
|
||||||
|
.also { it.setSurfaceProvider(previewView.surfaceProvider) }
|
||||||
|
|
||||||
|
coroutineScope.launch {
|
||||||
|
val cameraProvider = context.getCameraProvider()
|
||||||
|
try {
|
||||||
|
cameraProvider.unbindAll()
|
||||||
|
cameraProvider.bindToLifecycle(
|
||||||
|
lifecycleOwner,
|
||||||
|
videoRecorder.cameraSelector,
|
||||||
|
previewUseCase
|
||||||
|
)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Log.e("CameraPreview", "Use case binding failed", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previewView
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun _VideoGeneralInfo(videoRecorder: VideoRecorderModel) {
|
fun _VideoGeneralInfo(videoRecorder: VideoRecorderModel) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
16
app/src/main/java/app/myzel394/alibi/ui/utils/Context.kt
Normal file
16
app/src/main/java/app/myzel394/alibi/ui/utils/Context.kt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package app.myzel394.alibi.ui.utils
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
|
suspend fun Context.getCameraProvider(): ProcessCameraProvider = suspendCoroutine { continuation ->
|
||||||
|
ProcessCameraProvider.getInstance(this).also { future ->
|
||||||
|
future.addListener({
|
||||||
|
continuation.resume(future.get())
|
||||||
|
}, ContextCompat.getMainExecutor(this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user