feat: Add recording error handling

This commit is contained in:
Myzel394 2023-08-09 23:57:14 +02:00
parent 7620a065b4
commit 66b1d8a88d
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
7 changed files with 84 additions and 13 deletions

View File

@ -336,6 +336,9 @@ data class AudioRecorderSettings(
7 to "OPUS",
)
val ENCODER_SUPPORTED_OUTPUT_FORMATS_MAP: Map<Int, Array<Int>> = mutableMapOf(
MediaRecorder.AudioEncoder.DEFAULT to arrayOf(
MediaRecorder.OutputFormat.DEFAULT,
),
MediaRecorder.AudioEncoder.AAC to arrayOf(
MediaRecorder.OutputFormat.THREE_GPP,
MediaRecorder.OutputFormat.MPEG_4,

View File

@ -1,13 +1,16 @@
package app.myzel394.alibi.services
import android.media.MediaRecorder
import android.media.MediaRecorder.OnErrorListener
import android.os.Build
import java.lang.IllegalStateException
class AudioRecorderService: IntervalRecorderService() {
var amplitudesAmount = 1000
var recorder: MediaRecorder? = null
private set
var onError: () -> Unit = {}
val filePath: String
get() = "$folder/$counter.${settings!!.fileExtension}"
@ -24,6 +27,9 @@ class AudioRecorderService: IntervalRecorderService() {
setAudioEncoder(settings!!.encoder)
setAudioEncodingBitRate(settings!!.bitRate)
setAudioSamplingRate(settings!!.samplingRate)
setOnErrorListener(OnErrorListener { _, _, _ ->
onError()
})
}
}
@ -45,8 +51,12 @@ class AudioRecorderService: IntervalRecorderService() {
resetRecorder()
newRecorder.start()
recorder = newRecorder
try {
recorder = newRecorder
newRecorder.start()
} catch (error: RuntimeException) {
onError()
}
}
override fun pause() {

View File

@ -131,6 +131,7 @@ abstract class RecorderService: Service() {
onStateChange?.invoke(newState)
}
// Must be immediately called after creating the service!
fun startRecording() {
recordingStart = LocalDateTime.now()
@ -141,12 +142,6 @@ abstract class RecorderService: Service() {
changeState(RecorderState.RECORDING)
}
override fun onCreate() {
super.onCreate()
startRecording()
}
override fun onDestroy() {
super.onDestroy()

View File

@ -33,6 +33,7 @@ import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -200,7 +201,9 @@ fun RecordingStatus(
contentDescription = label
},
onClick = {
audioRecorder.stopRecording(context)
runCatching {
audioRecorder.stopRecording(context)
}
audioRecorder.onRecordingSave()
},
) {

View File

@ -4,6 +4,7 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.media.MediaRecorder
import android.os.IBinder
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -44,6 +45,7 @@ class AudioRecorderModel: ViewModel() {
private set
var onRecordingSave: () -> Unit = {}
var onError: () -> Unit = {}
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
@ -58,10 +60,17 @@ class AudioRecorderModel: ViewModel() {
amplitudes = amps
onAmplitudeChange()
}
recorder.onError = {
recorderService!!.createLastRecording()
onError()
}
}.also {
it.startRecording()
recorderState = it.state
recordingTime = it.recordingTime
amplitudes = it.amplitudes
}
recorderState = recorderService!!.state
recordingTime = recorderService!!.recordingTime
amplitudes = recorderService!!.amplitudes
}
override fun onServiceDisconnected(arg0: ComponentName) {

View File

@ -10,7 +10,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Memory
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@ -45,13 +48,15 @@ fun AudioRecorder(
navController: NavController,
audioRecorder: AudioRecorderModel,
) {
val context = LocalContext.current
val settings = rememberSettings()
val saveFile = rememberFileSaverDialog(settings.audioRecorderSettings.getMimeType())
val scope = rememberCoroutineScope()
var isProcessingAudio by remember { mutableStateOf(false) }
var showRecorderError by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
DisposableEffect(Unit) {
audioRecorder.onRecordingSave = {
scope.launch {
isProcessingAudio = true
@ -67,6 +72,16 @@ fun AudioRecorder(
}
}
}
audioRecorder.onError = {
// No need to save last recording as it's done automatically on error
audioRecorder.stopRecording(context, saveAsLastRecording = false)
showRecorderError = true
}
onDispose {
audioRecorder.onRecordingSave = {}
audioRecorder.onError = {}
}
}
if (isProcessingAudio)
@ -96,6 +111,40 @@ fun AudioRecorder(
},
confirmButton = {}
)
if (showRecorderError)
AlertDialog(
onDismissRequest = { showRecorderError = false },
icon = {
Icon(
Icons.Default.Warning,
contentDescription = null,
)
},
title = {
Text(stringResource(R.string.ui_audioRecorder_error_recording_title))
},
text = {
Text(stringResource(R.string.ui_audioRecorder_error_recording_description))
},
dismissButton = {
Button(
onClick = { showRecorderError = false },
colors = ButtonDefaults.textButtonColors(),
) {
Text(stringResource(R.string.dialog_close_cancel_label))
}
},
confirmButton = {
Button(
onClick = {
audioRecorder.onRecordingSave()
},
colors = ButtonDefaults.textButtonColors(),
) {
Text(stringResource(R.string.ui_audioRecorder_action_save_label))
}
}
)
Scaffold(
topBar = {
TopAppBar(

View File

@ -60,4 +60,6 @@
<string name="ui_settings_value_auto_label">Auto</string>
<string name="ui_audioRecorder_state_paused_title">Recording paused</string>
<string name="ui_audioRecorder_state_paused_description">Audio Recording has been paused</string>
<string name="ui_audioRecorder_error_recording_title">An error occured</string>
<string name="ui_audioRecorder_error_recording_description">Alibi encountered an error during recording. Would you like to try saving the recording?</string>
</resources>