feat: Add cameraID and enableAudio pass from UI to VideoRecorderService

This commit is contained in:
Myzel394 2023-12-04 18:56:29 +01:00
parent 60f53f3649
commit add9c8cde5
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
7 changed files with 78 additions and 40 deletions

View File

@ -1,8 +1,10 @@
package app.myzel394.alibi.services package app.myzel394.alibi.services
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.util.Range import android.util.Range
import androidx.camera.core.Camera import androidx.camera.core.Camera
import androidx.camera.core.CameraControl
import androidx.camera.core.CameraSelector import androidx.camera.core.CameraSelector
import androidx.camera.core.TorchState import androidx.camera.core.TorchState
import androidx.camera.lifecycle.ProcessCameraProvider import androidx.camera.lifecycle.ProcessCameraProvider
@ -27,6 +29,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlin.properties.Delegates
const val CAMERA_CLOSE_TIMEOUT = 20000L const val CAMERA_CLOSE_TIMEOUT = 20000L
@ -49,11 +52,23 @@ class VideoRecorderService :
// Absolute last completer that can be awaited to ensure that the camera is closed // Absolute last completer that can be awaited to ensure that the camera is closed
private var _cameraCloserListener = CompletableDeferred<Unit>() private var _cameraCloserListener = CompletableDeferred<Unit>()
private var selectedCamera: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA private lateinit var selectedCamera: CameraSelector
private var enableAudio by Delegates.notNull<Boolean>()
var cameraControl: CameraControl? = null var cameraControl: CameraControl? = null
private set private set
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.action == "init") {
selectedCamera = CameraSelector.Builder().requireLensFacing(
intent.getIntExtra("cameraID", CameraSelector.LENS_FACING_BACK)
).build()
enableAudio = intent.getBooleanExtra("enableAudio", true)
}
return super.onStartCommand(intent, flags, startId)
}
override fun start() { override fun start() {
super.start() super.start()
@ -189,7 +204,13 @@ class VideoRecorderService :
private fun prepareVideoRecording() = private fun prepareVideoRecording() =
videoCapture!!.output videoCapture!!.output
.prepareRecording(this, settings.getOutputOptions(this)) .prepareRecording(this, settings.getOutputOptions(this))
.withAudioEnabled() .run {
if (enableAudio) {
return@run withAudioEnabled()
}
this
}
override fun getRecordingInformation(): RecordingInformation = RecordingInformation( override fun getRecordingInformation(): RecordingInformation = RecordingInformation(
folderPath = batchesFolder.exportFolderForSettings(), folderPath = batchesFolder.exportFolderForSettings(),

View File

@ -8,13 +8,13 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel import app.myzel394.alibi.ui.models.VideoRecorderModel
import app.myzel394.alibi.ui.utils.CameraInfo import app.myzel394.alibi.ui.utils.CameraInfo
@Composable @Composable
fun CamerasSelection( fun CamerasSelection(
cameras: Iterable<CameraInfo>, cameras: Iterable<CameraInfo>,
videoSettings: VideoRecorderSettingsModel videoSettings: VideoRecorderModel,
) { ) {
val CAMERA_LENS_TEXT_MAP = mapOf( val CAMERA_LENS_TEXT_MAP = mapOf(
CameraInfo.Lens.BACK to stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label), CameraInfo.Lens.BACK to stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label),

View File

@ -38,7 +38,9 @@ import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
@ -53,19 +55,20 @@ import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraPreview
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
import app.myzel394.alibi.ui.components.atoms.PermissionRequester import app.myzel394.alibi.ui.components.atoms.PermissionRequester
import app.myzel394.alibi.ui.effects.rememberPrevious import app.myzel394.alibi.ui.effects.rememberPrevious
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel import app.myzel394.alibi.ui.models.VideoRecorderModel
import app.myzel394.alibi.ui.utils.CameraInfo import app.myzel394.alibi.ui.utils.CameraInfo
import kotlin.math.abs
@OptIn( @OptIn(
ExperimentalMaterial3Api::class, ExperimentalMaterial3Api::class,
) )
@Composable @Composable
fun VideoRecorderPreparationSheet( fun VideoRecorderPreparationSheet(
showPreview: Boolean,
videoSettings: VideoRecorderModel,
onDismiss: () -> Unit, onDismiss: () -> Unit,
videoSettings: VideoRecorderSettingsModel = viewModel(),
onPreviewVisible: () -> Unit, onPreviewVisible: () -> Unit,
onPreviewHidden: () -> Unit, onPreviewHidden: () -> Unit,
showPreview: Boolean,
onStartRecording: () -> Unit, onStartRecording: () -> Unit,
) { ) {
val sheetState = rememberModalBottomSheetState(true) { sheetValue -> val sheetState = rememberModalBottomSheetState(true) { sheetValue ->
@ -87,7 +90,7 @@ fun VideoRecorderPreparationSheet(
Unit Unit
else else
BottomSheetDefaults.DragHandle() BottomSheetDefaults.DragHandle()
} },
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -184,6 +187,9 @@ fun VideoRecorderPreparationSheet(
onLongPress = { onLongPress = {
onPreviewVisible() onPreviewVisible()
}, },
onTap = {
onStartRecording()
}
) )
}, },
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,

View File

@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
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.material.icons.filled.Mic
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -27,6 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.components.atoms.PermissionRequester import app.myzel394.alibi.ui.components.atoms.PermissionRequester
@ -48,12 +48,13 @@ fun VideoRecordingStart(
if (showSheet) { if (showSheet) {
VideoRecorderPreparationSheet( VideoRecorderPreparationSheet(
showPreview = showPreview,
videoSettings = videoRecorder,
onDismiss = { onDismiss = {
showSheet = false showSheet = false
}, },
onPreviewVisible = onHideAudioRecording, onPreviewVisible = onHideAudioRecording,
onPreviewHidden = onShowAudioRecording, onPreviewHidden = onShowAudioRecording,
showPreview = showPreview,
onStartRecording = { onStartRecording = {
videoRecorder.startRecording(context, appSettings) videoRecorder.startRecording(context, appSettings)
}, },

View File

@ -90,8 +90,13 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
recordingTime = null recordingTime = null
} }
protected open fun handleIntent(intent: Intent) = intent
// If override, call `super` AFTER setting the settings // If override, call `super` AFTER setting the settings
open fun startRecording(context: Context, settings: AppSettings) { open fun startRecording(
context: Context,
settings: AppSettings,
) {
this.settings = settings this.settings = settings
runCatching { runCatching {
@ -121,7 +126,7 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
), ),
) )
} }
} }.let(::handleIntent)
ContextCompat.startForegroundService(context, intent) ContextCompat.startForegroundService(context, intent)
context.bindService(intent, connection, Context.BIND_AUTO_CREATE) context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
} }

View File

@ -1,14 +1,36 @@
package app.myzel394.alibi.ui.models package app.myzel394.alibi.ui.models
import android.Manifest
import android.content.Context
import android.content.Intent
import androidx.camera.core.CameraSelector
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.db.RecordingInformation import app.myzel394.alibi.db.RecordingInformation
import app.myzel394.alibi.helpers.VideoBatchesFolder import app.myzel394.alibi.helpers.VideoBatchesFolder
import app.myzel394.alibi.services.VideoRecorderService import app.myzel394.alibi.services.VideoRecorderService
import app.myzel394.alibi.ui.utils.CameraInfo
import app.myzel394.alibi.ui.utils.PermissionHelper
class VideoRecorderModel : class VideoRecorderModel :
BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService, VideoBatchesFolder?>() { BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService, VideoBatchesFolder?>() {
override var batchesFolder: VideoBatchesFolder? = null override var batchesFolder: VideoBatchesFolder? = null
override val intentClass = VideoRecorderService::class.java override val intentClass = VideoRecorderService::class.java
var enableAudio by mutableStateOf(true)
var cameraID by mutableIntStateOf(CameraInfo.Lens.BACK.androidValue)
val cameraSelector: CameraSelector
get() = CameraSelector.Builder().requireLensFacing(cameraID).build()
fun init(context: Context) {
enableAudio = PermissionHelper.hasGranted(context, Manifest.permission.RECORD_AUDIO)
cameraID = CameraInfo.Lens.BACK.androidValue
}
override fun onServiceConnected(service: VideoRecorderService) { override fun onServiceConnected(service: VideoRecorderService) {
service.settings = VideoRecorderService.Settings.from(settings) service.settings = VideoRecorderService.Settings.from(settings)
@ -18,4 +40,15 @@ class VideoRecorderModel :
recorderState = service.state recorderState = service.state
recordingTime = service.recordingTime recordingTime = service.recordingTime
} }
override fun handleIntent(intent: Intent) =
intent.apply {
putExtra("cameraID", cameraID)
putExtra("enableAudio", enableAudio)
}
override fun startRecording(context: Context, settings: AppSettings) {
super.startRecording(context, settings)
}
} }

View File

@ -1,28 +0,0 @@
package app.myzel394.alibi.ui.models
import android.Manifest
import android.Manifest.permission.RECORD_AUDIO
import android.content.Context
import android.graphics.Camera
import android.hardware.camera2.CameraManager
import androidx.camera.core.CameraSelector
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import app.myzel394.alibi.ui.utils.CameraInfo
import app.myzel394.alibi.ui.utils.PermissionHelper
class VideoRecorderSettingsModel : ViewModel() {
var enableAudio by mutableStateOf(true)
var cameraID by mutableIntStateOf(CameraInfo.Lens.BACK.androidValue)
val cameraSelector: CameraSelector
get() = CameraSelector.Builder().requireLensFacing(cameraID).build()
fun init(context: Context) {
enableAudio = PermissionHelper.hasGranted(context, Manifest.permission.RECORD_AUDIO)
cameraID = CameraInfo.Lens.BACK.androidValue
}
}