diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b8f2dbc..fccf7db 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -37,7 +37,7 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
index 273431d..02d2bce 100644
--- a/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/AudioRecorderService.kt
@@ -4,11 +4,13 @@ import android.media.MediaRecorder
import android.os.Build
class AudioRecorderService: IntervalRecorderService() {
+ var amplitudesAmount = 1000
+
var recorder: MediaRecorder? = null
private set
val filePath: String
- get() = "$folder/$counter.${settings.fileExtension}"
+ get() = "$folder/$counter.${settings!!.fileExtension}"
private fun createRecorder(): MediaRecorder {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -18,10 +20,10 @@ class AudioRecorderService: IntervalRecorderService() {
}.apply {
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFile(filePath)
- setOutputFormat(settings.outputFormat)
- setAudioEncoder(settings.encoder)
- setAudioEncodingBitRate(settings.bitRate)
- setAudioSamplingRate(settings.samplingRate)
+ setOutputFormat(settings!!.outputFormat)
+ setAudioEncoder(settings!!.encoder)
+ setAudioEncodingBitRate(settings!!.bitRate)
+ setAudioSamplingRate(settings!!.samplingRate)
}
}
@@ -47,9 +49,13 @@ class AudioRecorderService: IntervalRecorderService() {
recorder = newRecorder
}
- override fun getAmplitudeAmount(): Int {
- return 100
+ override fun stop() {
+ super.stop()
+
+ resetRecorder()
}
+ override fun getAmplitudeAmount(): Int = amplitudesAmount
+
override fun getAmplitude(): Int = recorder?.maxAmplitude ?: 0
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/services/ExtraRecorderInformationService.kt b/app/src/main/java/app/myzel394/alibi/services/ExtraRecorderInformationService.kt
index 784ea5f..2d70e54 100644
--- a/app/src/main/java/app/myzel394/alibi/services/ExtraRecorderInformationService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/ExtraRecorderInformationService.kt
@@ -2,6 +2,7 @@ package app.myzel394.alibi.services
import android.os.Handler
import android.os.Looper
+import app.myzel394.alibi.enums.RecorderState
import java.util.Timer
import java.util.TimerTask
import java.util.concurrent.Executors
@@ -12,12 +13,12 @@ abstract class ExtraRecorderInformationService: RecorderService() {
abstract fun getAmplitudeAmount(): Int
abstract fun getAmplitude(): Int
- private var recordingTime = 0L
+ var recordingTime = 0L
+ private set
private lateinit var recordingTimeTimer: ScheduledExecutorService
var amplitudes = mutableListOf()
private set
- private lateinit var amplitudesTimer: Timer
private val handler = Handler(Looper.getMainLooper())
@@ -29,6 +30,7 @@ abstract class ExtraRecorderInformationService: RecorderService() {
it.scheduleAtFixedRate(
{
recordingTime += 1000
+ onRecordingTimeChange?.invoke(recordingTime)
},
0,
1000,
@@ -38,7 +40,12 @@ abstract class ExtraRecorderInformationService: RecorderService() {
}
private fun updateAmplitude() {
+ if (state !== RecorderState.RECORDING) {
+ return
+ }
+
amplitudes.add(getAmplitude())
+ onAmplitudeChange?.invoke(amplitudes)
// Delete old amplitudes
if (amplitudes.size > getAmplitudeAmount()) {
@@ -49,17 +56,7 @@ abstract class ExtraRecorderInformationService: RecorderService() {
}
private fun createAmplitudesTimer() {
- amplitudesTimer = Timer().also {
- it.scheduleAtFixedRate(
- object: TimerTask() {
- override fun run() {
- updateAmplitude()
- }
- },
- 0,
- 100,
- )
- }
+ handler.postDelayed(::updateAmplitude, 100)
}
override fun start() {
@@ -69,7 +66,6 @@ abstract class ExtraRecorderInformationService: RecorderService() {
override fun pause() {
recordingTimeTimer.shutdown()
- amplitudesTimer.cancel()
}
override fun resume() {
@@ -79,7 +75,6 @@ abstract class ExtraRecorderInformationService: RecorderService() {
override fun stop() {
recordingTimeTimer.shutdown()
- amplitudesTimer.cancel()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt
index cdb0063..1004adf 100644
--- a/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt
@@ -1,21 +1,33 @@
package app.myzel394.alibi.services
+import android.content.Context
import android.media.MediaRecorder
+import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AudioRecorderSettings
import app.myzel394.alibi.db.LastRecording
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
import java.io.File
+import java.time.LocalDateTime
import java.util.Timer
import java.util.TimerTask
+import java.util.UUID
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
abstract class IntervalRecorderService: ExtraRecorderInformationService() {
+ private var job = SupervisorJob()
+ private var scope = CoroutineScope(Dispatchers.IO + job)
+
protected var counter = 0
private set
protected lateinit var folder: File
- lateinit var settings: Settings
+ var settings: Settings? = null
protected set
private lateinit var cycleTimer: ScheduledExecutorService
@@ -23,10 +35,10 @@ abstract class IntervalRecorderService: ExtraRecorderInformationService() {
fun createLastRecording(): LastRecording = LastRecording(
folderPath = folder.absolutePath,
recordingStart = recordingStart,
- maxDuration = settings.maxDuration,
- fileExtension = settings.fileExtension,
- intervalDuration = settings.intervalDuration,
- forceExactMaxDuration = settings.forceExactMaxDuration,
+ maxDuration = settings!!.maxDuration,
+ fileExtension = settings!!.fileExtension,
+ intervalDuration = settings!!.intervalDuration,
+ forceExactMaxDuration = settings!!.forceExactMaxDuration,
)
// Make overrideable
@@ -41,32 +53,53 @@ abstract class IntervalRecorderService: ExtraRecorderInformationService() {
startNewCycle()
},
0,
- settings.intervalDuration,
+ settings!!.intervalDuration,
TimeUnit.MILLISECONDS
)
}
}
+ private fun getRandomFileFolder(): String {
+ // uuid
+ val folder = UUID.randomUUID().toString()
+
+ return "${externalCacheDir!!.absolutePath}/$folder"
+ }
+
override fun start() {
+ super.start()
+
+ folder = File(getRandomFileFolder())
folder.mkdirs()
- createTimer()
+ scope.launch {
+ dataStore.data.collectLatest { preferenceSettings ->
+ if (settings == null) {
+ settings = Settings.from(preferenceSettings.audioRecorderSettings)
+
+ createTimer()
+ }
+ }
+ }
}
override fun pause() {
+ super.pause()
cycleTimer.shutdown()
}
override fun resume() {
+ super.resume()
createTimer()
}
override fun stop() {
+ super.stop()
cycleTimer.shutdown()
}
private fun deleteOldRecordings() {
- val timeMultiplier = settings.maxDuration / settings.intervalDuration
+ val timeMultiplier = settings!!.maxDuration / settings!!.intervalDuration
val earliestCounter = counter - timeMultiplier
folder.listFiles()?.forEach { file ->
diff --git a/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt b/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt
index f881948..86b800b 100644
--- a/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt
@@ -26,7 +26,7 @@ abstract class RecorderService: Service() {
lateinit var recordingStart: LocalDateTime
private set
- var state = RecorderState.RECORDING
+ var state = RecorderState.IDLE
private set
var onStateChange: ((RecorderState) -> Unit)? = null
@@ -60,28 +60,34 @@ abstract class RecorderService: Service() {
pause()
isPaused = true
}
- else -> throw IllegalStateException("$newState is not a valid state. Destroy or recreate the service instead.")
+ RecorderState.IDLE -> stop()
}
state = newState
onStateChange?.invoke(newState)
}
+ // Must be called immediately after the service is created
+ fun startRecording() {
+ recordingStart = LocalDateTime.now()
+
+ val notification = buildNotification()
+ startForeground(NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID, notification)
+
+ // Start
+ changeState(RecorderState.RECORDING)
+ }
+
override fun onCreate() {
super.onCreate()
- val notification = buildNotification()
-
- startForeground(NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID, notification)
-
- recordingStart = LocalDateTime.now()
- start()
+ startRecording()
}
override fun onDestroy() {
super.onDestroy()
- stop()
+ changeState(RecorderState.IDLE)
stopForeground(STOP_FOREGROUND_REMOVE)
stopSelf()
diff --git a/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt b/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt
index a88aa9b..7dc6ffb 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt
@@ -11,11 +11,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
+import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.ui.enums.Screen
+import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.screens.AudioRecorder
import app.myzel394.alibi.ui.screens.SettingsScreen
import app.myzel394.alibi.ui.screens.WelcomeScreen
@@ -23,7 +25,9 @@ import app.myzel394.alibi.ui.screens.WelcomeScreen
const val SCALE_IN = 1.25f
@Composable
-fun Navigation() {
+fun Navigation(
+ audioRecorder: AudioRecorderModel = viewModel()
+) {
val navController = rememberNavController()
val context = LocalContext.current
val settings = context
@@ -32,6 +36,8 @@ fun Navigation() {
.collectAsState(initial = null)
.value ?: return
+ audioRecorder.BindToService(context)
+
NavHost(
modifier = Modifier
.background(MaterialTheme.colorScheme.background),
@@ -53,7 +59,10 @@ fun Navigation() {
scaleOut(targetScale = SCALE_IN) + fadeOut(tween(durationMillis = 150))
}
) {
- AudioRecorder(navController = navController)
+ AudioRecorder(
+ navController = navController,
+ audioRecorder = audioRecorder,
+ )
}
composable(
Screen.Settings.route,
@@ -64,7 +73,10 @@ fun Navigation() {
scaleOut(targetScale = 1 / SCALE_IN) + fadeOut(tween(durationMillis = 150))
}
) {
- SettingsScreen(navController = navController)
+ SettingsScreen(
+ navController = navController,
+ audioRecorder = audioRecorder,
+ )
}
}
}
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/RealTimeAudioVisualizer.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/RealTimeAudioVisualizer.kt
index aeeaa86..7d35b35 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/RealTimeAudioVisualizer.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/RealTimeAudioVisualizer.kt
@@ -21,6 +21,7 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.services.RecorderService
import app.myzel394.alibi.ui.MAX_AMPLITUDE
+import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.clamp
import kotlinx.coroutines.launch
import kotlin.math.ceil
@@ -34,10 +35,10 @@ private const val GROW_END = BOX_DIFF * 4
@Composable
fun RealtimeAudioVisualizer(
- service: RecorderService,
+ audioRecorder: AudioRecorderModel,
) {
val scope = rememberCoroutineScope()
- val amplitudes = service.amplitudes
+ val amplitudes = audioRecorder.amplitudes!!
val primary = MaterialTheme.colorScheme.primary
val primaryMuted = primary.copy(alpha = 0.3f)
@@ -47,7 +48,7 @@ fun RealtimeAudioVisualizer(
val animationProgress = remember { Animatable(0f) }
LaunchedEffect(Unit) {
- service.setOnAmplitudeUpdateListener {
+ audioRecorder.onAmplitudeChange = {
scope.launch {
animationProgress.snapTo(0f)
animationProgress.animateTo(
@@ -66,7 +67,7 @@ fun RealtimeAudioVisualizer(
LaunchedEffect(screenWidth) {
// Add 1 to allow the visualizer to overflow the screen
- service.maxAmplitudes = ceil(screenWidth.toInt() / BOX_DIFF).toInt() + 1
+ audioRecorder.setMaxAmplitudesAmount(ceil(screenWidth.toInt() / BOX_DIFF).toInt() + 1)
}
Canvas(
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/SaveRecordingButton.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/SaveRecordingButton.kt
index 550e2e4..1933c68 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/SaveRecordingButton.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/atoms/SaveRecordingButton.kt
@@ -88,13 +88,9 @@ fun SaveRecordingButton(
.then(modifier),
onClick = {
isProcessingAudio = true
- RecorderService.stopService(context)
scope.launch {
try {
- val file = service.concatenateFiles()
-
- onSaveFile(file)
} catch (error: Exception) {
Log.getStackTraceString(error)
} finally {
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/RecordingStatus.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/RecordingStatus.kt
index 2648d8f..19aa303 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/RecordingStatus.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/RecordingStatus.kt
@@ -47,6 +47,7 @@ import app.myzel394.alibi.ui.components.AudioRecorder.atoms.ConfirmDeletionDialo
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisualizer
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.SaveRecordingButton
import app.myzel394.alibi.ui.components.atoms.Pulsating
+import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.KeepScreenOn
import app.myzel394.alibi.ui.utils.formatDuration
import kotlinx.coroutines.delay
@@ -57,15 +58,12 @@ import java.time.ZoneId
@Composable
fun RecordingStatus(
- service: RecorderService,
- onSaveFile: (File) -> Unit,
+ audioRecorder: AudioRecorderModel,
) {
val context = LocalContext.current
var now by remember { mutableStateOf(LocalDateTime.now()) }
- val progress = service.recordingTime.value!! / (service.settings!!.maxDuration / 1000f)
-
LaunchedEffect(Unit) {
while (true) {
now = LocalDateTime.now()
@@ -74,7 +72,7 @@ fun RecordingStatus(
}
// Only show animation when the recording has just started
- val recordingJustStarted = service.recordingTime.value!! < 1
+ val recordingJustStarted = audioRecorder.recordingTime!! <= 1000L
var progressVisible by remember { mutableStateOf(!recordingJustStarted) }
LaunchedEffect(Unit) {
progressVisible = true
@@ -89,7 +87,7 @@ fun RecordingStatus(
verticalArrangement = Arrangement.SpaceBetween,
) {
Box {}
- RealtimeAudioVisualizer(service = service)
+ RealtimeAudioVisualizer(audioRecorder = audioRecorder)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
@@ -97,7 +95,7 @@ fun RecordingStatus(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
- val distance = Duration.between(service.recordingStart!!, now).toMillis()
+ val distance = Duration.between(audioRecorder.recorderService!!.recordingStart, now).toMillis()
Pulsating {
Box(
@@ -121,7 +119,7 @@ fun RecordingStatus(
)
) {
LinearProgressIndicator(
- progress = progress,
+ progress = audioRecorder.progress,
modifier = Modifier
.width(300.dp)
)
@@ -137,8 +135,7 @@ fun RecordingStatus(
},
onConfirm = {
showDeleteDialog = false
- RecorderService.stopService(context)
- service.reset()
+ audioRecorder.stopRecording(context)
},
)
}
@@ -163,11 +160,5 @@ fun RecordingStatus(
}
}
val alpha by animateFloatAsState(if (progressVisible) 1f else 0f, tween(1000))
- SaveRecordingButton(
- modifier = Modifier
- .alpha(alpha),
- service = service,
- onSaveFile = onSaveFile,
- )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/StartRecording.kt b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/StartRecording.kt
index fd5446b..b8cd59d 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/StartRecording.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/AudioRecorder/molecules/StartRecording.kt
@@ -34,6 +34,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.autoSaver
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -52,15 +53,14 @@ import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.AudioVisualizer
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.SaveRecordingButton
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
+import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
@Composable
fun StartRecording(
- connection: ServiceConnection,
- service: RecorderService? = null,
- onStart: () -> Unit,
+ audioRecorder: AudioRecorderModel,
) {
val context = LocalContext.current
val saveFile = rememberFileSaverDialog("audio/*")
@@ -80,17 +80,7 @@ fun StartRecording(
)
},
onPermissionAvailable = {
- RecorderService.startService(context, connection)
-
- if (service == null) {
- onStart()
- } else {
- // To avoid any leaks from the previous recording, we need to wait until it
- // fully started
- service.setOnStartedListener {
- onStart()
- }
- }
+ audioRecorder.startRecording(context)
},
) { trigger ->
val label = stringResource(R.string.ui_audioRecorder_action_start_label)
@@ -140,21 +130,12 @@ fun StartRecording(
.fillMaxWidth(),
textAlign = TextAlign.Center,
)
- if (service?.hasRecordingAvailable == true)
+ if (false)
Column(
modifier = Modifier.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Bottom,
) {
- SaveRecordingButton(
- service = service,
- onSaveFile = saveFile,
- label = stringResource(
- R.string.ui_audioRecorder_action_saveOldRecording_label,
- DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(service.recordingStart),
- ),
-
- )
}
else
Spacer(modifier = Modifier.weight(1f))
diff --git a/app/src/main/java/app/myzel394/alibi/ui/models/AudioRecorderModel.kt b/app/src/main/java/app/myzel394/alibi/ui/models/AudioRecorderModel.kt
index f5ca99a..17c3763 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/models/AudioRecorderModel.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/models/AudioRecorderModel.kt
@@ -5,6 +5,8 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
@@ -19,11 +21,20 @@ class AudioRecorderModel: ViewModel() {
private set
var recordingTime by mutableStateOf(null)
private set
- var amplitudes by mutableStateOf?>(null)
+ var amplitudes by mutableStateOf>(emptyList())
private set
+ var onAmplitudeChange: () -> Unit = {}
+
+ val isInRecording: Boolean
+ get() = recorderState !== RecorderState.IDLE && recordingTime != null
+
+ val progress: Float
+ get() = (recordingTime!! / recorderService!!.settings!!.maxDuration).toFloat()
+
private var intent: Intent? = null
- private var recorderService: RecorderService? = null
+ var recorderService: AudioRecorderService? = null
+ private set
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
@@ -36,8 +47,12 @@ class AudioRecorderModel: ViewModel() {
}
recorder.onAmplitudeChange = { amps ->
amplitudes = amps
+ onAmplitudeChange()
}
}
+ recorderState = recorderService!!.state
+ recordingTime = recorderService!!.recordingTime
+ amplitudes = recorderService!!.amplitudes
}
override fun onServiceDisconnected(arg0: ComponentName) {
@@ -49,7 +64,7 @@ class AudioRecorderModel: ViewModel() {
fun reset() {
recorderState = RecorderState.IDLE
recordingTime = null
- amplitudes = null
+ amplitudes = emptyList()
}
fun startRecording(context: Context) {
@@ -57,13 +72,30 @@ class AudioRecorderModel: ViewModel() {
context.unbindService(connection)
}
- val intent = Intent(context, AudioRecorderService::class.java)
- ContextCompat.startForegroundService(context, intent)
- context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
+ intent = Intent(context, AudioRecorderService::class.java)
+ ContextCompat.startForegroundService(context, intent!!)
+ context.bindService(intent!!, connection, Context.BIND_AUTO_CREATE)
}
fun stopRecording(context: Context) {
- context.stopService(intent)
- context.unbindService(connection)
+ runCatching {
+ context.unbindService(connection)
+ context.stopService(intent)
+ }
+
+ reset()
+ }
+
+ fun setMaxAmplitudesAmount(amount: Int) {
+ recorderService?.amplitudesAmount = amount
+ }
+
+ @Composable
+ fun BindToService(context: Context) {
+ LaunchedEffect(Unit) {
+ Intent(context, AudioRecorderService::class.java).also { intent ->
+ context.bindService(intent, connection, 0)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorder.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorder.kt
index c5877f4..3736f0c 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorder.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorder.kt
@@ -14,26 +14,25 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
-import app.myzel394.alibi.services.bindToRecorderService
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.RecordingStatus
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.StartRecording
import app.myzel394.alibi.ui.enums.Screen
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
import app.myzel394.alibi.R
+import app.myzel394.alibi.ui.models.AudioRecorderModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AudioRecorder(
navController: NavController,
+ audioRecorder: AudioRecorderModel
) {
+ val context = LocalContext.current
val saveFile = rememberFileSaverDialog("audio/aac")
- val (connection, service) = bindToRecorderService()
-
- var showRecorderStatus by remember {
- mutableStateOf(service?.isRecording ?: false)
- }
Scaffold(
topBar = {
@@ -61,22 +60,12 @@ fun AudioRecorder(
.fillMaxSize()
.padding(padding),
) {
- if (showRecorderStatus && service?.recordingTime?.value != null)
+ if (audioRecorder.isInRecording)
RecordingStatus(
- service = service,
- onSaveFile = {
- saveFile(it)
- showRecorderStatus = false
- }
+ audioRecorder = audioRecorder,
)
else
- StartRecording(
- connection = connection,
- service = service,
- onStart = {
- showRecorderStatus = true
- }
- )
+ StartRecording(audioRecorder = audioRecorder)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt
index f47ed32..2a92a54 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt
@@ -32,7 +32,6 @@ import androidx.navigation.NavController
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
-import app.myzel394.alibi.services.bindToRecorderService
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ForceExactMaxDurationTile
@@ -43,15 +42,15 @@ import app.myzel394.alibi.ui.components.SettingsScreen.atoms.SamplingRateTile
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
import app.myzel394.alibi.ui.components.atoms.MessageBox
import app.myzel394.alibi.ui.components.atoms.MessageType
+import app.myzel394.alibi.ui.models.AudioRecorderModel
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(
- navController: NavController
+ navController: NavController,
+ audioRecorder: AudioRecorderModel,
) {
- val (_, service) = bindToRecorderService()
- val isRecording = service?.isRecording ?: false
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
rememberTopAppBarState()
)
@@ -91,7 +90,7 @@ fun SettingsScreen(
.value
// Show alert
- if (isRecording)
+ if (audioRecorder.isInRecording)
Box(
modifier = Modifier
.padding(16.dp)