mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
chore: Improvements
This commit is contained in:
parent
f6bdd1b345
commit
d21580b0cb
@ -52,7 +52,7 @@
|
|||||||
android:name=".services.AudioRecorderService"
|
android:name=".services.AudioRecorderService"
|
||||||
android:foregroundServiceType="microphone" />
|
android:foregroundServiceType="microphone" />
|
||||||
<service
|
<service
|
||||||
android:name=".services.VideoService"
|
android:name=".services.OldVideoService"
|
||||||
android:foregroundServiceType="camera|microphone" />
|
android:foregroundServiceType="camera|microphone" />
|
||||||
|
|
||||||
<!-- Change locale for Android <= 12 -->
|
<!-- Change locale for Android <= 12 -->
|
||||||
|
@ -10,13 +10,17 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import androidx.compose.material3.SnackbarDuration
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import app.myzel394.alibi.db.AudioRecorderSettings
|
||||||
|
import app.myzel394.alibi.db.RecordingInformation
|
||||||
import app.myzel394.alibi.enums.RecorderState
|
import app.myzel394.alibi.enums.RecorderState
|
||||||
import app.myzel394.alibi.helpers.BatchesFolder
|
import app.myzel394.alibi.helpers.BatchesFolder
|
||||||
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
class AudioRecorderService : IntervalRecorderService() {
|
class AudioRecorderService :
|
||||||
|
IntervalRecorderService<AudioRecorderService.Settings, RecordingInformation>() {
|
||||||
var amplitudesAmount = 1000
|
var amplitudesAmount = 1000
|
||||||
var selectedMicrophone: MicrophoneInfo? = null
|
var selectedMicrophone: MicrophoneInfo? = null
|
||||||
|
|
||||||
@ -27,6 +31,37 @@ class AudioRecorderService : IntervalRecorderService() {
|
|||||||
var onMicrophoneDisconnected: () -> Unit = {}
|
var onMicrophoneDisconnected: () -> Unit = {}
|
||||||
var onMicrophoneReconnected: () -> Unit = {}
|
var onMicrophoneReconnected: () -> Unit = {}
|
||||||
|
|
||||||
|
var amplitudes = mutableListOf<Int>()
|
||||||
|
private set
|
||||||
|
|
||||||
|
private val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
var onAmplitudeChange: ((List<Int>) -> Unit)? = null
|
||||||
|
|
||||||
|
private fun updateAmplitude() {
|
||||||
|
if (state !== RecorderState.RECORDING) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
amplitudes.add(getAmplitude())
|
||||||
|
onAmplitudeChange?.invoke(amplitudes)
|
||||||
|
|
||||||
|
// Delete old amplitudes
|
||||||
|
if (amplitudes.size > getAmplitudeAmount()) {
|
||||||
|
// Should be more efficient than dropping the elements, getting a new list
|
||||||
|
// clearing old list and adding new elements to it
|
||||||
|
repeat(amplitudes.size - getAmplitudeAmount()) {
|
||||||
|
amplitudes.removeAt(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.postDelayed(::updateAmplitude, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createAmplitudesTimer() {
|
||||||
|
handler.postDelayed(::updateAmplitude, 100)
|
||||||
|
}
|
||||||
|
|
||||||
/// Tell Android to use the correct bluetooth microphone, if any selected
|
/// Tell Android to use the correct bluetooth microphone, if any selected
|
||||||
private fun startAudioDevice() {
|
private fun startAudioDevice() {
|
||||||
if (selectedMicrophone == null) {
|
if (selectedMicrophone == null) {
|
||||||
@ -102,6 +137,14 @@ class AudioRecorderService : IntervalRecorderService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getRecordingInformation() = RecordingInformation(
|
||||||
|
folderPath = batchesFolder.exportFolderForSettings(),
|
||||||
|
recordingStart = recordingStart,
|
||||||
|
maxDuration = settings.maxDuration,
|
||||||
|
fileExtension = settings.fileExtension,
|
||||||
|
intervalDuration = settings.intervalDuration,
|
||||||
|
)
|
||||||
|
|
||||||
override fun startNewCycle() {
|
override fun startNewCycle() {
|
||||||
super.startNewCycle()
|
super.startNewCycle()
|
||||||
|
|
||||||
@ -123,6 +166,7 @@ class AudioRecorderService : IntervalRecorderService() {
|
|||||||
override fun start() {
|
override fun start() {
|
||||||
super.start()
|
super.start()
|
||||||
|
|
||||||
|
createAmplitudesTimer()
|
||||||
registerMicrophoneListener()
|
registerMicrophoneListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +184,14 @@ class AudioRecorderService : IntervalRecorderService() {
|
|||||||
unregisterMicrophoneListener()
|
unregisterMicrophoneListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAmplitudeAmount(): Int = amplitudesAmount
|
override fun resume() {
|
||||||
|
super.resume()
|
||||||
|
createAmplitudesTimer()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getAmplitude(): Int {
|
private fun getAmplitudeAmount(): Int = amplitudesAmount
|
||||||
|
|
||||||
|
private fun getAmplitude(): Int {
|
||||||
return try {
|
return try {
|
||||||
recorder!!.maxAmplitude
|
recorder!!.maxAmplitude
|
||||||
} catch (error: IllegalStateException) {
|
} catch (error: IllegalStateException) {
|
||||||
@ -213,4 +262,43 @@ class AudioRecorderService : IntervalRecorderService() {
|
|||||||
|
|
||||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class Settings(
|
||||||
|
override val maxDuration: Long,
|
||||||
|
override val intervalDuration: Long,
|
||||||
|
val bitRate: Int,
|
||||||
|
val samplingRate: Int,
|
||||||
|
val outputFormat: Int,
|
||||||
|
val encoder: Int,
|
||||||
|
val folder: String? = null,
|
||||||
|
) : IntervalRecorderService.Settings(
|
||||||
|
maxDuration = maxDuration,
|
||||||
|
intervalDuration = intervalDuration
|
||||||
|
) {
|
||||||
|
val fileExtension: String
|
||||||
|
get() = when (outputFormat) {
|
||||||
|
MediaRecorder.OutputFormat.AAC_ADTS -> "aac"
|
||||||
|
MediaRecorder.OutputFormat.THREE_GPP -> "3gp"
|
||||||
|
MediaRecorder.OutputFormat.MPEG_4 -> "mp4"
|
||||||
|
MediaRecorder.OutputFormat.MPEG_2_TS -> "ts"
|
||||||
|
MediaRecorder.OutputFormat.WEBM -> "webm"
|
||||||
|
MediaRecorder.OutputFormat.AMR_NB -> "amr"
|
||||||
|
MediaRecorder.OutputFormat.AMR_WB -> "awb"
|
||||||
|
MediaRecorder.OutputFormat.OGG -> "ogg"
|
||||||
|
else -> "raw"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun from(audioRecorderSettings: AudioRecorderSettings): IntervalRecorderService.Settings {
|
||||||
|
return Settings(
|
||||||
|
intervalDuration = audioRecorderSettings.intervalDuration,
|
||||||
|
bitRate = audioRecorderSettings.bitRate,
|
||||||
|
samplingRate = audioRecorderSettings.getSamplingRate(),
|
||||||
|
outputFormat = audioRecorderSettings.getOutputFormat(),
|
||||||
|
encoder = audioRecorderSettings.getEncoder(),
|
||||||
|
maxDuration = audioRecorderSettings.maxDuration,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,55 +0,0 @@
|
|||||||
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
|
|
||||||
import java.util.concurrent.ScheduledExecutorService
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
abstract class ExtraRecorderInformationService : RecorderService() {
|
|
||||||
abstract fun getAmplitudeAmount(): Int
|
|
||||||
abstract fun getAmplitude(): Int
|
|
||||||
|
|
||||||
var amplitudes = mutableListOf<Int>()
|
|
||||||
private set
|
|
||||||
|
|
||||||
private val handler = Handler(Looper.getMainLooper())
|
|
||||||
|
|
||||||
var onAmplitudeChange: ((List<Int>) -> Unit)? = null
|
|
||||||
|
|
||||||
private fun updateAmplitude() {
|
|
||||||
if (state !== RecorderState.RECORDING) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
amplitudes.add(getAmplitude())
|
|
||||||
onAmplitudeChange?.invoke(amplitudes)
|
|
||||||
|
|
||||||
// Delete old amplitudes
|
|
||||||
if (amplitudes.size > getAmplitudeAmount()) {
|
|
||||||
// Should be more efficient than dropping the elements, getting a new list
|
|
||||||
// clearing old list and adding new elements to it
|
|
||||||
repeat(amplitudes.size - getAmplitudeAmount()) {
|
|
||||||
amplitudes.removeAt(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handler.postDelayed(::updateAmplitude, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAmplitudesTimer() {
|
|
||||||
handler.postDelayed(::updateAmplitude, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
createAmplitudesTimer()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun resume() {
|
|
||||||
createAmplitudesTimer()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -19,14 +19,12 @@ import java.util.concurrent.Executors
|
|||||||
import java.util.concurrent.ScheduledExecutorService
|
import java.util.concurrent.ScheduledExecutorService
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
abstract class IntervalRecorderService : ExtraRecorderInformationService() {
|
abstract class IntervalRecorderService<S : IntervalRecorderService.Settings, I> :
|
||||||
private var job = SupervisorJob()
|
RecorderService() {
|
||||||
private var scope = CoroutineScope(Dispatchers.IO + job)
|
|
||||||
|
|
||||||
protected var counter = 0L
|
protected var counter = 0L
|
||||||
private set
|
private set
|
||||||
|
|
||||||
lateinit var settings: Settings
|
lateinit var settings: S
|
||||||
|
|
||||||
private lateinit var cycleTimer: ScheduledExecutorService
|
private lateinit var cycleTimer: ScheduledExecutorService
|
||||||
|
|
||||||
@ -34,13 +32,7 @@ abstract class IntervalRecorderService : ExtraRecorderInformationService() {
|
|||||||
|
|
||||||
var onCustomOutputFolderNotAccessible: () -> Unit = {}
|
var onCustomOutputFolderNotAccessible: () -> Unit = {}
|
||||||
|
|
||||||
fun getRecordingInformation(): RecordingInformation = RecordingInformation(
|
abstract fun getRecordingInformation(): I
|
||||||
folderPath = batchesFolder.exportFolderForSettings(),
|
|
||||||
recordingStart = recordingStart,
|
|
||||||
maxDuration = settings.maxDuration,
|
|
||||||
fileExtension = settings.fileExtension,
|
|
||||||
intervalDuration = settings.intervalDuration,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Make overrideable
|
// Make overrideable
|
||||||
open fun startNewCycle() {
|
open fun startNewCycle() {
|
||||||
@ -62,8 +54,6 @@ abstract class IntervalRecorderService : ExtraRecorderInformationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
super.start()
|
|
||||||
|
|
||||||
batchesFolder.initFolders()
|
batchesFolder.initFolders()
|
||||||
if (!batchesFolder.checkIfFolderIsAccessible()) {
|
if (!batchesFolder.checkIfFolderIsAccessible()) {
|
||||||
batchesFolder =
|
batchesFolder =
|
||||||
@ -81,10 +71,6 @@ abstract class IntervalRecorderService : ExtraRecorderInformationService() {
|
|||||||
|
|
||||||
override fun resume() {
|
override fun resume() {
|
||||||
createTimer()
|
createTimer()
|
||||||
|
|
||||||
// We first want to start our timers, so the `ExtraRecorderInformationService` can fetch
|
|
||||||
// amplitudes
|
|
||||||
super.resume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
@ -96,45 +82,14 @@ abstract class IntervalRecorderService : ExtraRecorderInformationService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
batchesFolder.deleteOldRecordings(earliestCounter)
|
batchesFolder.deleteOldRecordings(earliestCounter)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Settings(
|
abstract class Settings(
|
||||||
val maxDuration: Long,
|
open val maxDuration: Long,
|
||||||
val intervalDuration: Long,
|
open val intervalDuration: Long,
|
||||||
val bitRate: Int,
|
|
||||||
val samplingRate: Int,
|
|
||||||
val outputFormat: Int,
|
|
||||||
val encoder: Int,
|
|
||||||
val folder: String? = null,
|
|
||||||
) {
|
|
||||||
val fileExtension: String
|
|
||||||
get() = when (outputFormat) {
|
|
||||||
MediaRecorder.OutputFormat.AAC_ADTS -> "aac"
|
|
||||||
MediaRecorder.OutputFormat.THREE_GPP -> "3gp"
|
|
||||||
MediaRecorder.OutputFormat.MPEG_4 -> "mp4"
|
|
||||||
MediaRecorder.OutputFormat.MPEG_2_TS -> "ts"
|
|
||||||
MediaRecorder.OutputFormat.WEBM -> "webm"
|
|
||||||
MediaRecorder.OutputFormat.AMR_NB -> "amr"
|
|
||||||
MediaRecorder.OutputFormat.AMR_WB -> "awb"
|
|
||||||
MediaRecorder.OutputFormat.OGG -> "ogg"
|
|
||||||
else -> "raw"
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun from(audioRecorderSettings: AudioRecorderSettings): Settings {
|
|
||||||
return Settings(
|
|
||||||
intervalDuration = audioRecorderSettings.intervalDuration,
|
|
||||||
bitRate = audioRecorderSettings.bitRate,
|
|
||||||
samplingRate = audioRecorderSettings.getSamplingRate(),
|
|
||||||
outputFormat = audioRecorderSettings.getOutputFormat(),
|
|
||||||
encoder = audioRecorderSettings.getEncoder(),
|
|
||||||
maxDuration = audioRecorderSettings.maxDuration,
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -3,26 +3,16 @@ package app.myzel394.alibi.services
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.pm.ServiceInfo
|
import android.content.pm.ServiceInfo
|
||||||
import android.graphics.SurfaceTexture
|
|
||||||
import android.hardware.Camera
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.view.Surface
|
|
||||||
import android.view.TextureView
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.camera.core.CameraProvider
|
|
||||||
import androidx.camera.core.CameraSelector
|
import androidx.camera.core.CameraSelector
|
||||||
import androidx.camera.core.Preview
|
|
||||||
import androidx.camera.core.Preview.SurfaceProvider
|
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
import androidx.camera.video.MediaStoreOutputOptions
|
import androidx.camera.video.MediaStoreOutputOptions
|
||||||
import androidx.camera.video.PendingRecording
|
|
||||||
import androidx.camera.video.Quality
|
import androidx.camera.video.Quality
|
||||||
import androidx.camera.video.QualitySelector
|
import androidx.camera.video.QualitySelector
|
||||||
import androidx.camera.video.Recorder
|
import androidx.camera.video.Recorder
|
||||||
import androidx.camera.video.Recording
|
import androidx.camera.video.Recording
|
||||||
import androidx.camera.video.VideoCapture.withOutput
|
import androidx.camera.video.VideoCapture.withOutput
|
||||||
import androidx.camera.video.VideoRecordEvent
|
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -31,13 +21,15 @@ import app.myzel394.alibi.NotificationHelper
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.ScheduledExecutorService
|
import java.util.concurrent.ScheduledExecutorService
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class VideoService : LifecycleService() {
|
|
||||||
|
class VideoService : IntervalRecorderService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class OldVideoService : LifecycleService() {
|
||||||
private var job = SupervisorJob()
|
private var job = SupervisorJob()
|
||||||
private var scope = CoroutineScope(Dispatchers.IO + job)
|
private var scope = CoroutineScope(Dispatchers.IO + job)
|
||||||
|
|
||||||
@ -88,7 +80,7 @@ class VideoService : LifecycleService() {
|
|||||||
// Used to bind the lifecycle of cameras to the lifecycle owner
|
// Used to bind the lifecycle of cameras to the lifecycle owner
|
||||||
val cameraProvider = cameraProviderFuture.get()
|
val cameraProvider = cameraProviderFuture.get()
|
||||||
val recorder = Recorder.Builder()
|
val recorder = Recorder.Builder()
|
||||||
.setQualitySelector(QualitySelector.from(Quality.HIGHEST))
|
.setQualitySelector(QualitySelector.from(Quality.LOWEST))
|
||||||
.build()
|
.build()
|
||||||
val videoCapture = withOutput(recorder)
|
val videoCapture = withOutput(recorder)
|
||||||
// Select back camera as a default
|
// Select back camera as a default
|
||||||
@ -98,7 +90,7 @@ class VideoService : LifecycleService() {
|
|||||||
cameraProvider?.unbindAll()
|
cameraProvider?.unbindAll()
|
||||||
// Bind use cases to camera
|
// Bind use cases to camera
|
||||||
cameraProvider?.bindToLifecycle(
|
cameraProvider?.bindToLifecycle(
|
||||||
this@VideoService,
|
this@OldVideoService,
|
||||||
cameraSelector,
|
cameraSelector,
|
||||||
videoCapture
|
videoCapture
|
||||||
)
|
)
|
||||||
@ -108,7 +100,7 @@ class VideoService : LifecycleService() {
|
|||||||
cycleTimer = Executors.newSingleThreadScheduledExecutor().also {
|
cycleTimer = Executors.newSingleThreadScheduledExecutor().also {
|
||||||
it.scheduleAtFixedRate(
|
it.scheduleAtFixedRate(
|
||||||
{
|
{
|
||||||
val mainHandler = ContextCompat.getMainExecutor(this@VideoService)
|
val mainHandler = ContextCompat.getMainExecutor(this@OldVideoService)
|
||||||
|
|
||||||
mainHandler.execute {
|
mainHandler.execute {
|
||||||
runCatching {
|
runCatching {
|
||||||
@ -116,11 +108,11 @@ class VideoService : LifecycleService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val r =
|
val r =
|
||||||
videoCapture.output.prepareRecording(this@VideoService, options)
|
videoCapture.output.prepareRecording(this@OldVideoService, options)
|
||||||
.withAudioEnabled()
|
.withAudioEnabled()
|
||||||
|
|
||||||
recording =
|
recording =
|
||||||
r.start(ContextCompat.getMainExecutor(this@VideoService), {})
|
r.start(ContextCompat.getMainExecutor(this@OldVideoService), {})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0,
|
0,
|
@ -10,6 +10,7 @@ import android.os.Build
|
|||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.app.ServiceCompat
|
import androidx.core.app.ServiceCompat
|
||||||
|
import androidx.lifecycle.LifecycleService
|
||||||
import app.myzel394.alibi.NotificationHelper
|
import app.myzel394.alibi.NotificationHelper
|
||||||
import app.myzel394.alibi.enums.RecorderState
|
import app.myzel394.alibi.enums.RecorderState
|
||||||
import app.myzel394.alibi.ui.utils.PermissionHelper
|
import app.myzel394.alibi.ui.utils.PermissionHelper
|
||||||
@ -20,7 +21,7 @@ import java.util.concurrent.ScheduledExecutorService
|
|||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
abstract class RecorderService : Service() {
|
abstract class RecorderService : LifecycleService() {
|
||||||
private val binder = RecorderBinder()
|
private val binder = RecorderBinder()
|
||||||
|
|
||||||
private var isPaused: Boolean = false
|
private var isPaused: Boolean = false
|
||||||
@ -44,7 +45,10 @@ abstract class RecorderService : Service() {
|
|||||||
protected abstract fun resume()
|
protected abstract fun resume()
|
||||||
protected abstract fun stop()
|
protected abstract fun stop()
|
||||||
|
|
||||||
override fun onBind(p0: Intent?): IBinder? = binder
|
override fun onBind(intent: Intent): IBinder? {
|
||||||
|
super.onBind(intent)
|
||||||
|
return 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) {
|
||||||
|
@ -3,22 +3,27 @@ package app.myzel394.alibi.ui.screens
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import app.myzel394.alibi.services.VideoService
|
import app.myzel394.alibi.services.OldVideoService
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun POCVideo() {
|
fun POCVideo() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(64.dp)
|
||||||
|
) {
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
val intent = Intent(context, VideoService::class.java)
|
val intent = Intent(context, OldVideoService::class.java)
|
||||||
ContextCompat.startForegroundService(context, intent)
|
ContextCompat.startForegroundService(context, intent)
|
||||||
}) {
|
}) {
|
||||||
Text("Start")
|
Text("Start")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user