mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
fix: Stop scope and recreate it to avoid leaks
This commit is contained in:
parent
f97c791e10
commit
a49969acda
@ -48,8 +48,8 @@ const val AMPLITUDE_UPDATE_INTERVAL = 100L
|
|||||||
class RecorderService: Service() {
|
class RecorderService: Service() {
|
||||||
private val binder = LocalBinder()
|
private val binder = LocalBinder()
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
private val job = SupervisorJob()
|
private var job = SupervisorJob()
|
||||||
private val scope = CoroutineScope(Dispatchers.IO + job)
|
private var scope = CoroutineScope(Dispatchers.IO + job)
|
||||||
|
|
||||||
private var mediaRecorder: MediaRecorder? = null
|
private var mediaRecorder: MediaRecorder? = null
|
||||||
private var onError: MediaRecorder.OnErrorListener? = null
|
private var onError: MediaRecorder.OnErrorListener? = null
|
||||||
@ -57,7 +57,8 @@ class RecorderService: Service() {
|
|||||||
|
|
||||||
private var counter = 0
|
private var counter = 0
|
||||||
|
|
||||||
lateinit var settings: Settings
|
var settings: Settings? = null
|
||||||
|
private set
|
||||||
|
|
||||||
var fileFolder: String? = null
|
var fileFolder: String? = null
|
||||||
private set
|
private set
|
||||||
@ -78,18 +79,14 @@ class RecorderService: Service() {
|
|||||||
|
|
||||||
val extension = it.extension
|
val extension = it.extension
|
||||||
|
|
||||||
extension == settings.fileExtension
|
extension == settings!!.fileExtension
|
||||||
}?.toList() ?: emptyList()
|
}?.toList() ?: emptyList()
|
||||||
|
|
||||||
override fun onBind(p0: Intent?): IBinder = binder
|
override fun onBind(p0: Intent?): IBinder = binder
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
when (intent?.action) {
|
when (intent?.action) {
|
||||||
Actions.START.toString() -> {
|
Actions.START.toString() -> start()
|
||||||
fileFolder = getRandomFileFolder(this)
|
|
||||||
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
Actions.STOP.toString() -> stop()
|
Actions.STOP.toString() -> stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,14 +103,61 @@ class RecorderService: Service() {
|
|||||||
this.onAmplitudeUpdate = onAmplitudeUpdate
|
this.onAmplitudeUpdate = onAmplitudeUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun start() {
|
||||||
|
reset()
|
||||||
|
fileFolder = getRandomFileFolder(this)
|
||||||
|
|
||||||
|
// Create folder
|
||||||
|
File(this.fileFolder!!).mkdirs()
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
dataStore.data.collectLatest { preferenceSettings ->
|
||||||
|
if (settings == null) {
|
||||||
|
settings = Settings.from(preferenceSettings.audioRecorderSettings)
|
||||||
|
recordingStart = LocalDateTime.now()
|
||||||
|
isRecording.value = true
|
||||||
|
|
||||||
|
showNotification()
|
||||||
|
startNewRecording()
|
||||||
|
updateAmplitude()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetCoroutineScope() {
|
||||||
|
// Reset `scope`
|
||||||
|
scope.cancel()
|
||||||
|
job = SupervisorJob()
|
||||||
|
scope = CoroutineScope(Dispatchers.IO + job)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stop() {
|
||||||
|
isRecording.value = false
|
||||||
|
mediaRecorder?.apply {
|
||||||
|
runCatching {
|
||||||
|
stop()
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||||
|
stopSelf()
|
||||||
|
resetCoroutineScope()
|
||||||
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
recordingStart = null
|
recordingStart = null
|
||||||
counter = 0
|
counter = 0
|
||||||
amplitudes.clear()
|
amplitudes.clear()
|
||||||
isRecording.value = false
|
isRecording.value = false
|
||||||
|
|
||||||
File(fileFolder!!).listFiles()?.forEach {
|
if (fileFolder != null) {
|
||||||
it.delete()
|
File(fileFolder!!).listFiles()?.forEach {
|
||||||
|
it.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileFolder = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +165,10 @@ class RecorderService: Service() {
|
|||||||
outputFile: File
|
outputFile: File
|
||||||
) {
|
) {
|
||||||
// Move the concatenated file to a temporary file
|
// Move the concatenated file to a temporary file
|
||||||
val rawFile = File("$fileFolder/${outputFile.nameWithoutExtension}-raw.${settings.fileExtension}")
|
val rawFile = File("$fileFolder/${outputFile.nameWithoutExtension}-raw.${settings!!.fileExtension}")
|
||||||
outputFile.renameTo(rawFile)
|
outputFile.renameTo(rawFile)
|
||||||
|
|
||||||
val command = "-sseof ${settings.maxDuration / -1000} -i $rawFile -y $outputFile"
|
val command = "-sseof ${settings!!.maxDuration / -1000} -i $rawFile -y $outputFile"
|
||||||
|
|
||||||
val session = FFmpegKit.execute(command)
|
val session = FFmpegKit.execute(command)
|
||||||
|
|
||||||
@ -150,7 +194,7 @@ class RecorderService: Service() {
|
|||||||
.toString()
|
.toString()
|
||||||
.replace(":", "-")
|
.replace(":", "-")
|
||||||
.replace(".", "_")
|
.replace(".", "_")
|
||||||
val outputFile = File("$fileFolder/$fileName.${settings.fileExtension}")
|
val outputFile = File("$fileFolder/$fileName.${settings!!.fileExtension}")
|
||||||
|
|
||||||
if (outputFile.exists() && !forceConcatenation) {
|
if (outputFile.exists() && !forceConcatenation) {
|
||||||
return outputFile
|
return outputFile
|
||||||
@ -161,8 +205,8 @@ class RecorderService: Service() {
|
|||||||
" -metadata title='$fileName' " +
|
" -metadata title='$fileName' " +
|
||||||
" -metadata date='${recordingStart!!.format(ISO_DATE_TIME)}'" +
|
" -metadata date='${recordingStart!!.format(ISO_DATE_TIME)}'" +
|
||||||
" -metadata batch_count='${filePaths.size}'" +
|
" -metadata batch_count='${filePaths.size}'" +
|
||||||
" -metadata batch_duration='${settings.intervalDuration}'" +
|
" -metadata batch_duration='${settings!!.intervalDuration}'" +
|
||||||
" -metadata max_duration='${settings.maxDuration}'" +
|
" -metadata max_duration='${settings!!.maxDuration}'" +
|
||||||
" $outputFile"
|
" $outputFile"
|
||||||
|
|
||||||
val session = FFmpegKit.execute(command)
|
val session = FFmpegKit.execute(command)
|
||||||
@ -181,8 +225,8 @@ class RecorderService: Service() {
|
|||||||
throw Exception("Failed to concatenate audios")
|
throw Exception("Failed to concatenate audios")
|
||||||
}
|
}
|
||||||
|
|
||||||
val minRequiredForPossibleInExactMaxDuration = settings.maxDuration / settings.intervalDuration
|
val minRequiredForPossibleInExactMaxDuration = settings!!.maxDuration / settings!!.intervalDuration
|
||||||
if (settings.forceExactMaxDuration && filePaths.size > minRequiredForPossibleInExactMaxDuration) {
|
if (settings!!.forceExactMaxDuration && filePaths.size > minRequiredForPossibleInExactMaxDuration) {
|
||||||
stripConcatenatedFileToExactDuration(outputFile)
|
stripConcatenatedFileToExactDuration(outputFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,11 +268,11 @@ class RecorderService: Service() {
|
|||||||
|
|
||||||
counter++
|
counter++
|
||||||
|
|
||||||
handler.postDelayed(this::startNewRecording, settings.intervalDuration)
|
handler.postDelayed(this::startNewRecording, settings!!.intervalDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteOldRecordings() {
|
private fun deleteOldRecordings() {
|
||||||
val timeMultiplier = settings.maxDuration / settings.intervalDuration
|
val timeMultiplier = settings!!.maxDuration / settings!!.intervalDuration
|
||||||
val earliestCounter = counter - timeMultiplier
|
val earliestCounter = counter - timeMultiplier
|
||||||
|
|
||||||
File(fileFolder!!).listFiles()?.forEach { file ->
|
File(fileFolder!!).listFiles()?.forEach { file ->
|
||||||
@ -248,10 +292,10 @@ class RecorderService: Service() {
|
|||||||
}.apply {
|
}.apply {
|
||||||
setAudioSource(MediaRecorder.AudioSource.MIC)
|
setAudioSource(MediaRecorder.AudioSource.MIC)
|
||||||
setOutputFile(getFilePath())
|
setOutputFile(getFilePath())
|
||||||
setOutputFormat(settings.outputFormat)
|
setOutputFormat(settings!!.outputFormat)
|
||||||
setAudioEncoder(settings.encoder)
|
setAudioEncoder(settings!!.encoder)
|
||||||
setAudioEncodingBitRate(settings.bitRate)
|
setAudioEncodingBitRate(settings!!.bitRate)
|
||||||
setAudioSamplingRate(settings.samplingRate)
|
setAudioSamplingRate(settings!!.samplingRate)
|
||||||
|
|
||||||
setOnErrorListener { mr, what, extra ->
|
setOnErrorListener { mr, what, extra ->
|
||||||
onError?.onError(mr, what, extra)
|
onError?.onError(mr, what, extra)
|
||||||
@ -261,38 +305,6 @@ class RecorderService: Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun start() {
|
|
||||||
reset()
|
|
||||||
// Create folder
|
|
||||||
File(this.fileFolder!!).mkdirs()
|
|
||||||
|
|
||||||
scope.launch {
|
|
||||||
dataStore.data.collectLatest { preferenceSettings ->
|
|
||||||
settings = Settings.from(preferenceSettings.audioRecorderSettings)
|
|
||||||
recordingStart = LocalDateTime.now()
|
|
||||||
isRecording.value = true
|
|
||||||
|
|
||||||
showNotification()
|
|
||||||
startNewRecording()
|
|
||||||
updateAmplitude()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stop() {
|
|
||||||
mediaRecorder?.apply {
|
|
||||||
runCatching {
|
|
||||||
stop()
|
|
||||||
release()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isRecording.value = false
|
|
||||||
|
|
||||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
|
||||||
stopSelf()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showNotification() {
|
private fun showNotification() {
|
||||||
if (!isRecording.value) {
|
if (!isRecording.value) {
|
||||||
return
|
return
|
||||||
@ -334,7 +346,7 @@ class RecorderService: Service() {
|
|||||||
).toInt()
|
).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFilePath(): String = "$fileFolder/$counter.${settings.fileExtension}"
|
private fun getFilePath(): String = "$fileFolder/$counter.${settings!!.fileExtension}"
|
||||||
|
|
||||||
inner class LocalBinder: Binder() {
|
inner class LocalBinder: Binder() {
|
||||||
fun getService(): RecorderService = this@RecorderService
|
fun getService(): RecorderService = this@RecorderService
|
||||||
|
Loading…
x
Reference in New Issue
Block a user