diff --git a/app/build.gradle b/app/build.gradle
index d3c9db3f1..b5d105696 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ plugins {
android {
namespace 'app.myzel394.alibi'
- compileSdk 34
+ compileSdk 33
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
@@ -34,7 +34,7 @@ android {
multiDexEnabled true
applicationId "app.myzel394.alibi"
minSdk 24
- targetSdk 34
+ targetSdk 33
versionCode 7
versionName "0.3.0"
@@ -42,6 +42,13 @@ android {
vectorDrawables {
useSupportLibrary true
}
+
+ configurations.all {
+ resolutionStrategy {
+ force("androidx.emoji2:emoji2-views-helper:1.3.0")
+ force("androidx.emoji2:emoji2:1.3.0")
+ }
+ }
}
signingConfigs {
@@ -91,16 +98,16 @@ android {
}
dependencies {
- implementation 'androidx.core:core-ktx:1.12.0'
+ implementation 'androidx.core:core-ktx:1.10.0'
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
- implementation 'androidx.activity:activity-compose:1.7.2'
+ implementation 'androidx.activity:activity-compose:1.0.0'
implementation platform('androidx.compose:compose-bom:2022.10.00')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
- implementation "androidx.compose.material:material-icons-extended:1.5.1"
+ implementation "androidx.compose.material:material-icons-extended:1.5.4"
implementation 'androidx.appcompat:appcompat:1.6.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
@@ -110,7 +117,7 @@ dependencies {
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
- implementation "androidx.navigation:navigation-compose:2.7.2"
+ implementation "androidx.navigation:navigation-compose:2.5.0"
implementation 'com.google.dagger:hilt-android:2.46.1'
annotationProcessor 'com.google.dagger:hilt-compiler:2.46.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8f67b7cd0..32cc19fb9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,6 +13,8 @@
+
+
@@ -56,6 +59,14 @@
android:name="autoStoreLocales"
android:value="true" />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/NotificationHelper.kt b/app/src/main/java/app/myzel394/alibi/NotificationHelper.kt
index 679cee744..c34c221f0 100644
--- a/app/src/main/java/app/myzel394/alibi/NotificationHelper.kt
+++ b/app/src/main/java/app/myzel394/alibi/NotificationHelper.kt
@@ -9,18 +9,30 @@ import androidx.annotation.RequiresApi
object NotificationHelper {
const val RECORDER_CHANNEL_ID = "recorder"
const val RECORDER_CHANNEL_NOTIFICATION_ID = 1
+ const val BOOT_CHANNEL_ID = "boot"
+ const val BOOT_CHANNEL_NOTIFICATION_ID = 2
@RequiresApi(Build.VERSION_CODES.O)
fun createChannels(context: Context) {
- val channel = NotificationChannel(
- RECORDER_CHANNEL_ID,
- context.resources.getString(R.string.notificationChannels_recorder_name),
- android.app.NotificationManager.IMPORTANCE_LOW,
- )
- channel.description = context.resources.getString(R.string.notificationChannels_recorder_description)
-
val notificationManager = context.getSystemService(NotificationManager::class.java)
- notificationManager.createNotificationChannel(channel)
+ notificationManager.createNotificationChannel(
+ NotificationChannel(
+ RECORDER_CHANNEL_ID,
+ context.getString(R.string.notificationChannels_recorder_name),
+ NotificationManager.IMPORTANCE_LOW,
+ ).apply {
+ description = context.getString(R.string.notificationChannels_recorder_description)
+ }
+ )
+ notificationManager.createNotificationChannel(
+ NotificationChannel(
+ BOOT_CHANNEL_ID,
+ context.getString(R.string.notificationChannels_boot_name),
+ NotificationManager.IMPORTANCE_LOW,
+ ).apply {
+ description = context.getString(R.string.notificationChannels_boot_description)
+ }
+ )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt
index 505f1a7b3..328f73841 100644
--- a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt
+++ b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt
@@ -19,6 +19,7 @@ data class AppSettings(
val showAdvancedSettings: Boolean = false,
val theme: Theme = Theme.SYSTEM,
val lastRecording: RecordingInformation? = null,
+ val bootBehavior: BootBehavior? = BootBehavior.CONTINUE_RECORDING,
) {
fun setShowAdvancedSettings(showAdvancedSettings: Boolean): AppSettings {
return copy(showAdvancedSettings = showAdvancedSettings)
@@ -44,12 +45,27 @@ data class AppSettings(
return copy(lastRecording = lastRecording)
}
+ fun setBootBehavior(bootBehavior: BootBehavior?): AppSettings {
+ return copy(bootBehavior = bootBehavior)
+ }
+
enum class Theme {
SYSTEM,
LIGHT,
DARK,
}
+ enum class BootBehavior {
+ // Always start recording, no matter if it was interrupted or not
+ START_RECORDING,
+
+ // Only start recording if it was interrupted
+ CONTINUE_RECORDING,
+
+ // Show a notification if interrupted
+ SHOW_NOTIFICATION,
+ }
+
fun exportToString(): String {
return Json.encodeToString(serializer(), this)
}
diff --git a/app/src/main/java/app/myzel394/alibi/receivers/BootReceiver.kt b/app/src/main/java/app/myzel394/alibi/receivers/BootReceiver.kt
new file mode 100644
index 000000000..c12ef8f5c
--- /dev/null
+++ b/app/src/main/java/app/myzel394/alibi/receivers/BootReceiver.kt
@@ -0,0 +1,128 @@
+package app.myzel394.alibi.receivers
+
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.IBinder
+import androidx.core.app.NotificationCompat
+import androidx.core.content.ContextCompat
+import app.myzel394.alibi.MainActivity
+import app.myzel394.alibi.NotificationHelper
+import app.myzel394.alibi.R
+import app.myzel394.alibi.dataStore
+import app.myzel394.alibi.db.AppSettings
+import app.myzel394.alibi.helpers.AudioRecorderExporter
+import app.myzel394.alibi.services.AudioRecorderService
+import app.myzel394.alibi.services.RecorderNotificationHelper
+import app.myzel394.alibi.services.RecorderService
+import app.myzel394.alibi.ui.enums.Screen
+import app.myzel394.alibi.ui.models.AudioRecorderModel
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
+import kotlinx.serialization.json.Json
+
+class BootReceiver : BroadcastReceiver() {
+ private var job = SupervisorJob()
+ private var scope = CoroutineScope(Dispatchers.IO + job)
+
+ private fun startRecording(context: Context, settings: AppSettings) {
+ val connection = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, service: IBinder) {
+ ((service as RecorderService.RecorderBinder).getService() as AudioRecorderService).also { recorder ->
+ recorder.startRecording()
+ }
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ }
+ }
+
+ println("BootReceiver.startRecording()")
+ val intent = Intent(context, AudioRecorderService::class.java).apply {
+ action = "init"
+
+ putExtra(
+ "startImmediately",
+ true,
+ )
+
+ if (settings.notificationSettings != null) {
+ putExtra(
+ "notificationDetails",
+ Json.encodeToString(
+ RecorderNotificationHelper.NotificationDetails.serializer(),
+ RecorderNotificationHelper.NotificationDetails.fromNotificationSettings(
+ context,
+ settings.notificationSettings
+ )
+ ),
+ )
+ }
+ }
+ ContextCompat.startForegroundService(context, intent)
+ }
+
+ private fun showNotification(context: Context) {
+ if (!AudioRecorderExporter.hasRecordingsAvailable(context)) {
+ // Nothing interrupted, so no notification needs to be shown
+ return
+ }
+
+ val notification = NotificationCompat.Builder(context, NotificationHelper.BOOT_CHANNEL_ID)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ .setCategory(NotificationCompat.CATEGORY_REMINDER)
+ .setSmallIcon(R.drawable.launcher_monochrome_noopacity)
+ .setContentIntent(
+ PendingIntent.getActivity(
+ context,
+ 0,
+ Intent(context, MainActivity::class.java),
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
+ )
+ )
+ .setOnlyAlertOnce(true)
+ .setContentTitle(context.getString(R.string.notification_boot_title))
+ .setContentText(context.getString(R.string.notification_boot_message))
+ .build()
+
+ val notificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ notificationManager.notify(NotificationHelper.BOOT_CHANNEL_NOTIFICATION_ID, notification)
+ }
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+ if (intent?.action != Intent.ACTION_BOOT_COMPLETED || context == null) {
+ return
+ }
+
+ println("BootReceiver.onReceive()")
+
+ scope.launch {
+ context.dataStore.data.collectLatest { settings ->
+ println("BootBehavior: ${settings.bootBehavior}")
+ when (settings.bootBehavior) {
+ AppSettings.BootBehavior.CONTINUE_RECORDING -> {
+ if (AudioRecorderExporter.hasRecordingsAvailable(context)) {
+ startRecording(context, settings)
+ }
+ }
+
+ AppSettings.BootBehavior.START_RECORDING -> startRecording(context, settings)
+ AppSettings.BootBehavior.SHOW_NOTIFICATION -> showNotification(context)
+ null -> {
+ // Nothing to do
+ }
+ }
+ }
+ }
+ }
+}
\ 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 88d2bca0a..56183f9b6 100644
--- a/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/IntervalRecorderService.kt
@@ -1,5 +1,6 @@
package app.myzel394.alibi.services
+import android.media.MediaMetadataRetriever
import android.media.MediaRecorder
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AudioRecorderSettings
@@ -58,10 +59,45 @@ abstract class IntervalRecorderService : ExtraRecorderInformationService() {
}
}
+ private fun fetchCounterValue() {
+ val files = outputFolder.listFiles()?.filter {
+ val name = it.nameWithoutExtension
+
+ name.toIntOrNull() != null
+ }?.toList() ?: emptyList()
+
+ counter = files.size
+ }
+
+ private fun fetchRecordingTime() {
+ var oldAmount = 0L
+
+ for (file in outputFolder.listFiles() ?: emptyArray()) {
+ if (file.nameWithoutExtension.toIntOrNull() == null) {
+ continue
+ }
+
+ // It's better to at least get an approximate value, than to crash
+ runCatching {
+ val amount = MediaMetadataRetriever().run {
+ setDataSource(file.absolutePath)
+ extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toIntOrNull()
+ ?: 0
+ }
+
+ oldAmount += amount
+ }
+ }
+
+ recordingTime = oldAmount
+ }
+
override fun start() {
super.start()
outputFolder.mkdirs()
+ fetchCounterValue()
+ fetchRecordingTime()
scope.launch {
dataStore.data.collectLatest { preferenceSettings ->
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 02b579794..b3cd09a49 100644
--- a/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt
+++ b/app/src/main/java/app/myzel394/alibi/services/RecorderService.kt
@@ -34,7 +34,7 @@ abstract class RecorderService : Service() {
var onStateChange: ((RecorderState) -> Unit)? = null
var recordingTime = 0L
- private set
+ protected set
private lateinit var recordingTimeTimer: ScheduledExecutorService
var onRecordingTimeChange: ((Long) -> Unit)? = null
var notificationDetails: RecorderNotificationHelper.NotificationDetails? = null
@@ -55,6 +55,10 @@ abstract class RecorderService : Service() {
it
)
}
+
+ if (intent.getBooleanExtra("startImmediately", false)) {
+ startRecording()
+ }
}
"changeState" -> {
@@ -142,16 +146,22 @@ abstract class RecorderService : Service() {
fun startRecording() {
recordingStart = LocalDateTime.now()
- ServiceCompat.startForeground(
- this,
- NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID,
- getNotificationHelper().buildStartingNotification(),
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
- } else {
- 0
- },
- )
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ startForeground(
+ NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID,
+ getNotificationHelper().buildStartingNotification(),
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
+ } else {
+ 0
+ },
+ )
+ } else {
+ startForeground(
+ NotificationHelper.RECORDER_CHANNEL_NOTIFICATION_ID,
+ getNotificationHelper().buildStartingNotification(),
+ )
+ }
// Start
changeState(RecorderState.RECORDING)
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 985e79d56..f55e4acf2 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/Navigation.kt
@@ -60,15 +60,6 @@ fun Navigation(
}
composable(
Screen.AudioRecorder.route,
- enterTransition = {
- when (initialState.destination.route) {
- Screen.Welcome.route -> null
- else -> scaleIn(initialScale = SCALE_IN) + fadeIn()
- }
- },
- exitTransition = {
- scaleOut(targetScale = SCALE_IN) + fadeOut(tween(durationMillis = 150))
- }
) {
AudioRecorderScreen(
navController = navController,
@@ -77,12 +68,6 @@ fun Navigation(
}
composable(
Screen.Settings.route,
- enterTransition = {
- scaleIn(initialScale = 1 / SCALE_IN) + fadeIn()
- },
- exitTransition = {
- scaleOut(targetScale = 1 / SCALE_IN) + fadeOut(tween(durationMillis = 150))
- }
) {
SettingsScreen(
navController = navController,
@@ -91,16 +76,6 @@ fun Navigation(
}
composable(
Screen.CustomRecordingNotifications.route,
- enterTransition = {
- slideInHorizontally(
- initialOffsetX = { it -> it / 2 }
- ) + fadeIn()
- },
- exitTransition = {
- slideOutHorizontally(
- targetOffsetX = { it -> it / 2 }
- ) + fadeOut(tween(150))
- }
) {
CustomRecordingNotificationsScreen(
navController = navController,
@@ -108,12 +83,6 @@ fun Navigation(
}
composable(
Screen.About.route,
- enterTransition = {
- scaleIn()
- },
- exitTransition = {
- scaleOut() + fadeOut(tween(150))
- }
) {
AboutScreen(
navController = navController,
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 72f2f42e5..4111fca7d 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
@@ -82,6 +82,10 @@ fun StartRecording(
)
}
+ runCatching {
+ audioRecorder.stopRecording(context)
+ }
+
AudioRecorderExporter.clearAllRecordings(context)
audioRecorder.startRecording(context)
diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/BootBehaviorTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/BootBehaviorTile.kt
new file mode 100644
index 000000000..9982f5bb4
--- /dev/null
+++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/BootBehaviorTile.kt
@@ -0,0 +1,124 @@
+package app.myzel394.alibi.ui.components.SettingsScreen.atoms
+
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.CheckCircle
+import androidx.compose.material.icons.filled.Smartphone
+import androidx.compose.material.icons.filled.Translate
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.core.os.LocaleListCompat
+import app.myzel394.alibi.R
+import app.myzel394.alibi.SUPPORTED_LOCALES
+import app.myzel394.alibi.dataStore
+import app.myzel394.alibi.db.AppSettings
+import app.myzel394.alibi.ui.components.atoms.SettingsTile
+import app.myzel394.alibi.ui.utils.IconResource
+import com.maxkeppeker.sheets.core.models.base.ButtonStyle
+import com.maxkeppeker.sheets.core.models.base.Header
+import com.maxkeppeker.sheets.core.models.base.IconSource
+import com.maxkeppeker.sheets.core.models.base.SelectionButton
+import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
+import com.maxkeppeler.sheets.list.ListDialog
+import com.maxkeppeler.sheets.list.models.ListOption
+import com.maxkeppeler.sheets.list.models.ListSelection
+import kotlinx.coroutines.launch
+import java.util.Locale
+
+val BOOT_BEHAVIOR_TITLE_MAP = mapOf(
+ AppSettings.BootBehavior.SHOW_NOTIFICATION to R.string.ui_settings_bootBehavior_values_SHOW_NOTIFICATION_title,
+ AppSettings.BootBehavior.START_RECORDING to R.string.ui_settings_bootBehavior_values_START_RECORDING_title,
+ AppSettings.BootBehavior.CONTINUE_RECORDING to R.string.ui_settings_bootBehavior_values_CONTINUE_RECORDING_title,
+)
+val BOOT_BEHAVIOR_DESCRIPTION_MAP = mapOf(
+ AppSettings.BootBehavior.SHOW_NOTIFICATION to R.string.ui_settings_bootBehavior_values_SHOW_NOTIFICATION_description,
+ AppSettings.BootBehavior.START_RECORDING to R.string.ui_settings_bootBehavior_values_START_RECORDING_description,
+ AppSettings.BootBehavior.CONTINUE_RECORDING to R.string.ui_settings_bootBehavior_values_CONTINUE_RECORDING_description,
+)
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun BootBehaviorTile(
+ settings: AppSettings,
+) {
+ val scope = rememberCoroutineScope()
+ val showDialog = rememberUseCaseState()
+ val dataStore = LocalContext.current.dataStore
+
+ fun updateValue(behavior: AppSettings.BootBehavior?) {
+ scope.launch {
+ dataStore.updateData {
+ it.setBootBehavior(
+ behavior
+ )
+ }
+ }
+ }
+
+ ListDialog(
+ state = showDialog,
+ header = Header.Default(
+ title = stringResource(R.string.ui_settings_bootBehavior_help),
+ icon = IconSource(
+ painter = IconResource.fromImageVector(Icons.Default.Smartphone)
+ .asPainterResource(),
+ contentDescription = null,
+ )
+ ),
+ selection = ListSelection.Single(
+ showRadioButtons = true,
+ options = AppSettings.BootBehavior.entries.map {
+ ListOption(
+ titleText = stringResource(
+ BOOT_BEHAVIOR_TITLE_MAP[it]!!
+ ),
+ subtitleText = stringResource(
+ BOOT_BEHAVIOR_DESCRIPTION_MAP[it]!!
+ ),
+ selected = settings.bootBehavior == it,
+ )
+ }.toList() + listOf(
+ ListOption(
+ titleText = stringResource(R.string.ui_settings_bootBehavior_values_nothing_title),
+ )
+ ),
+ positiveButton = SelectionButton(
+ icon = IconSource(
+ painter = IconResource.fromImageVector(Icons.Default.CheckCircle)
+ .asPainterResource(),
+ contentDescription = null,
+ ),
+ text = stringResource(android.R.string.ok),
+ type = ButtonStyle.TEXT,
+ )
+ ) { index, _ ->
+ val behavior = AppSettings.BootBehavior.values().getOrNull(index)
+ updateValue(behavior)
+ },
+ )
+ SettingsTile(
+ firstModifier = Modifier
+ .fillMaxHeight()
+ .clickable {
+ showDialog.show()
+ },
+ title = stringResource(R.string.ui_settings_bootBehavior_title),
+ description = stringResource(
+ BOOT_BEHAVIOR_TITLE_MAP[settings.bootBehavior] ?: R.string.ui_settings_bootBehavior_help
+ ),
+ leading = {
+ Icon(
+ Icons.Default.Smartphone,
+ contentDescription = null,
+ )
+ },
+ )
+}
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 7c9724af8..da3f1d721 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
@@ -125,7 +125,7 @@ class AudioRecorderModel : ViewModel() {
}
}
ContextCompat.startForegroundService(context, intent)
- context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
+ context.bindService(intent, connection, 0)
}
fun stopRecording(context: Context) {
diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorderScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorderScreen.kt
index ce3cff6d5..687a29fdc 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorderScreen.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/screens/AudioRecorderScreen.kt
@@ -94,6 +94,7 @@ fun AudioRecorderScreen(
delay(100)
try {
+ audioRecorder.stopRecording(context)
val file = AudioRecorderExporter(
audioRecorder.recorderService?.getRecordingInformation()
?: settings.lastRecording
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 0a1b4f96d..f28bafa2a 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
@@ -41,6 +41,7 @@ import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.AboutTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile
+import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BootBehaviorTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.CustomNotificationTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.DeleteRecordingsImmediatelyTile
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile
@@ -149,6 +150,7 @@ fun SettingsScreen(
InAppLanguagePicker()
DeleteRecordingsImmediatelyTile(settings = settings)
CustomNotificationTile(navController = navController, settings = settings)
+ BootBehaviorTile(settings = settings)
AboutTile(navController = navController)
AnimatedVisibility(visible = settings.showAdvancedSettings) {
Column(
diff --git a/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt b/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt
index c36c91bf5..2a435ddd7 100644
--- a/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt
+++ b/app/src/main/java/app/myzel394/alibi/ui/utils/available-microphones.kt
@@ -16,10 +16,13 @@ val ALLOWED_MICROPHONE_TYPES =
AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
AudioDeviceInfo.TYPE_IP,
AudioDeviceInfo.TYPE_DOCK,
+ /*
+ Currently unavailable due to targetSDK 33
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
AudioDeviceInfo.TYPE_DOCK_ANALOG
} else {
},
+ */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
AudioDeviceInfo.TYPE_BLE_HEADSET
} else {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a1328ef00..945137157 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -109,4 +109,17 @@
Become a GitHub Sponsor
Delete Recordings Immediately
If enabled, Alibi will immediately delete recordings after you have saved the file.
+ Boot Behavior
+ Show a notification
+ Boot notification
+ If enabled, you\'ll be informed that your recording was interrupted
+ Alibi was interrupted
+ Your device restarted and your recording has been interrupted
+ Always start recording
+ Continue recording
+ Show a notification if recording has been interrupted
+ Continue recording, if interrupted, otherwise start a new recording
+ If recording has been interrupted, continue it
+ Do nothing
+ What should Alibi do when your phone boots up?
\ No newline at end of file