mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Add microphone selection
This commit is contained in:
parent
862de21436
commit
df1d7ce8ff
@ -9,11 +9,12 @@ import android.media.MediaRecorder
|
|||||||
import android.media.MediaRecorder.OnErrorListener
|
import android.media.MediaRecorder.OnErrorListener
|
||||||
import android.media.MediaRecorder.getAudioSourceMax
|
import android.media.MediaRecorder.getAudioSourceMax
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
class AudioRecorderService: IntervalRecorderService() {
|
class AudioRecorderService: IntervalRecorderService() {
|
||||||
var amplitudesAmount = 1000
|
var amplitudesAmount = 1000
|
||||||
var selectedDevice: AudioDeviceInfo? = null
|
var selectedDevice: MicrophoneInfo? = null
|
||||||
|
|
||||||
var recorder: MediaRecorder? = null
|
var recorder: MediaRecorder? = null
|
||||||
private set
|
private set
|
||||||
@ -29,7 +30,7 @@ class AudioRecorderService: IntervalRecorderService() {
|
|||||||
if (selectedDevice == null) {
|
if (selectedDevice == null) {
|
||||||
audioManger.clearCommunicationDevice()
|
audioManger.clearCommunicationDevice()
|
||||||
} else {
|
} else {
|
||||||
audioManger.setCommunicationDevice(selectedDevice!!)
|
audioManger.setCommunicationDevice(selectedDevice!!.deviceInfo)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (selectedDevice == null) {
|
if (selectedDevice == null) {
|
||||||
@ -116,30 +117,4 @@ class AudioRecorderService: IntervalRecorderService() {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
||||||
if (intent?.action == "changeAudioDevice") {
|
|
||||||
selectedDevice = intent.getStringExtra("deviceID")!!.let {
|
|
||||||
if (it == "null") {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
val audioManager = getSystemService(AUDIO_SERVICE)!! as AudioManager
|
|
||||||
audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS).find { device ->
|
|
||||||
device.id == it.toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onStartCommand(intent, flags, startId)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun changeAudioDevice(deviceID: String?, context: Context) {
|
|
||||||
val intent = Intent("changeAudioDevice").apply {
|
|
||||||
putExtra("deviceID", deviceID ?: "null")
|
|
||||||
}
|
|
||||||
context.startService(intent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package app.myzel394.alibi.ui.components.AudioRecorder.atoms
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import app.myzel394.alibi.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MicrophoneSelectionButton(
|
||||||
|
microphone: MicrophoneInfo? = null,
|
||||||
|
selected: Boolean = false,
|
||||||
|
onSelect: () -> Unit,
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = onSelect,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(64.dp),
|
||||||
|
colors = if (selected) ButtonDefaults.buttonColors(
|
||||||
|
) else ButtonDefaults.textButtonColors(),
|
||||||
|
) {
|
||||||
|
MicrophoneTypeInfo(
|
||||||
|
type = microphone?.type ?: MicrophoneInfo.MicrophoneType.PHONE,
|
||||||
|
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
||||||
|
Text(
|
||||||
|
text = microphone?.name
|
||||||
|
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone),
|
||||||
|
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package app.myzel394.alibi.ui.components.AudioRecorder.atoms
|
||||||
|
|
||||||
|
import android.R
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.BluetoothAudio
|
||||||
|
import androidx.compose.material.icons.filled.Memory
|
||||||
|
import androidx.compose.material.icons.filled.Mic
|
||||||
|
import androidx.compose.material.icons.filled.MicExternalOn
|
||||||
|
import androidx.compose.material.icons.filled.Settings
|
||||||
|
import androidx.compose.material.icons.filled.Smartphone
|
||||||
|
import androidx.compose.material.icons.filled.Warning
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MicrophoneTypeInfo(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
type: MicrophoneInfo.MicrophoneType,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = when (type) {
|
||||||
|
MicrophoneInfo.MicrophoneType.BLUETOOTH -> Icons.Filled.BluetoothAudio
|
||||||
|
MicrophoneInfo.MicrophoneType.WIRED -> Icons.Filled.MicExternalOn
|
||||||
|
MicrophoneInfo.MicrophoneType.PHONE -> Icons.Filled.Smartphone
|
||||||
|
MicrophoneInfo.MicrophoneType.OTHER -> Icons.Filled.Mic
|
||||||
|
},
|
||||||
|
modifier = modifier,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
package app.myzel394.alibi.ui.components.AudioRecorder.molecules
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import app.myzel394.alibi.R
|
||||||
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneSelectionButton
|
||||||
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneTypeInfo
|
||||||
|
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MicrophoneSelection(
|
||||||
|
audioRecorder: AudioRecorderModel,
|
||||||
|
microphones: List<MicrophoneInfo>,
|
||||||
|
) {
|
||||||
|
var showSelection by rememberSaveable {
|
||||||
|
mutableStateOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showSelection) {
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = {
|
||||||
|
showSelection = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.padding(bottom = 24.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedBy(48.dp),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.ui_audioRecorder_info_microphone_changeExplanation),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
)
|
||||||
|
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 32.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
MicrophoneSelectionButton(
|
||||||
|
selected = audioRecorder.recorderService!!.selectedDevice == null,
|
||||||
|
onSelect = {
|
||||||
|
audioRecorder.changeMicrophone(null)
|
||||||
|
showSelection = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
items(microphones.size) {
|
||||||
|
val microphone = microphones[it]
|
||||||
|
|
||||||
|
MicrophoneSelectionButton(
|
||||||
|
microphone = microphone,
|
||||||
|
selected = audioRecorder.recorderService!!.selectedDevice == microphone,
|
||||||
|
onSelect = {
|
||||||
|
audioRecorder.changeMicrophone(microphone)
|
||||||
|
showSelection = false
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
showSelection = true
|
||||||
|
},
|
||||||
|
colors = ButtonDefaults.textButtonColors(),
|
||||||
|
) {
|
||||||
|
MicrophoneTypeInfo(
|
||||||
|
type = audioRecorder.recorderService!!.selectedDevice?.type
|
||||||
|
?: MicrophoneInfo.MicrophoneType.PHONE,
|
||||||
|
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
||||||
|
Text(
|
||||||
|
text = audioRecorder.recorderService!!.selectedDevice.let {
|
||||||
|
it?.name
|
||||||
|
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
package app.myzel394.alibi.ui.components.AudioRecorder.molecules
|
package app.myzel394.alibi.ui.components.AudioRecorder.organisms
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.expandHorizontally
|
import androidx.compose.animation.expandHorizontally
|
||||||
import androidx.compose.animation.fadeIn
|
|
||||||
import androidx.compose.animation.fadeOut
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@ -26,14 +24,12 @@ import androidx.compose.material.icons.filled.PlayArrow
|
|||||||
import androidx.compose.material.icons.filled.Save
|
import androidx.compose.material.icons.filled.Save
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.LargeFloatingActionButton
|
import androidx.compose.material3.LargeFloatingActionButton
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -50,20 +46,17 @@ import androidx.compose.ui.semantics.contentDescription
|
|||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.myzel394.alibi.R
|
import app.myzel394.alibi.R
|
||||||
import app.myzel394.alibi.services.RecorderService
|
|
||||||
import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE
|
import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.ConfirmDeletionDialog
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.ConfirmDeletionDialog
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisualizer
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisualizer
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.SaveRecordingButton
|
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.MicrophoneSelection
|
||||||
import app.myzel394.alibi.ui.components.atoms.Pulsating
|
import app.myzel394.alibi.ui.components.atoms.Pulsating
|
||||||
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
||||||
import app.myzel394.alibi.ui.utils.KeepScreenOn
|
import app.myzel394.alibi.ui.utils.KeepScreenOn
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
import app.myzel394.alibi.ui.utils.formatDuration
|
import app.myzel394.alibi.ui.utils.formatDuration
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import java.io.File
|
|
||||||
import java.time.Duration
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RecordingStatus(
|
fun RecordingStatus(
|
||||||
@ -215,5 +208,14 @@ fun RecordingStatus(
|
|||||||
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
||||||
Text(stringResource(R.string.ui_audioRecorder_action_save_label))
|
Text(stringResource(R.string.ui_audioRecorder_action_save_label))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val microphones = MicrophoneInfo.fetchDeviceMicrophones(context)
|
||||||
|
|
||||||
|
if (microphones.isNotEmpty()) {
|
||||||
|
MicrophoneSelection(
|
||||||
|
audioRecorder = audioRecorder,
|
||||||
|
microphones = microphones
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,10 +4,7 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.media.MediaRecorder
|
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@ -17,6 +14,7 @@ import app.myzel394.alibi.db.LastRecording
|
|||||||
import app.myzel394.alibi.enums.RecorderState
|
import app.myzel394.alibi.enums.RecorderState
|
||||||
import app.myzel394.alibi.services.AudioRecorderService
|
import app.myzel394.alibi.services.AudioRecorderService
|
||||||
import app.myzel394.alibi.services.RecorderService
|
import app.myzel394.alibi.services.RecorderService
|
||||||
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
|
|
||||||
class AudioRecorderModel: ViewModel() {
|
class AudioRecorderModel: ViewModel() {
|
||||||
var recorderState by mutableStateOf(RecorderState.IDLE)
|
var recorderState by mutableStateOf(RecorderState.IDLE)
|
||||||
@ -121,6 +119,10 @@ class AudioRecorderModel: ViewModel() {
|
|||||||
recorderService?.amplitudesAmount = amount
|
recorderService?.amplitudesAmount = amount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun changeMicrophone(microphone: MicrophoneInfo?) {
|
||||||
|
recorderService!!.selectedDevice = microphone
|
||||||
|
}
|
||||||
|
|
||||||
fun bindToService(context: Context) {
|
fun bindToService(context: Context) {
|
||||||
Intent(context, AudioRecorderService::class.java).also { intent ->
|
Intent(context, AudioRecorderService::class.java).also { intent ->
|
||||||
context.bindService(intent, connection, 0)
|
context.bindService(intent, connection, 0)
|
||||||
|
@ -28,16 +28,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.RecordingStatus
|
import app.myzel394.alibi.ui.components.AudioRecorder.organisms.RecordingStatus
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.StartRecording
|
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.StartRecording
|
||||||
import app.myzel394.alibi.ui.enums.Screen
|
import app.myzel394.alibi.ui.enums.Screen
|
||||||
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
|
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
|
||||||
import app.myzel394.alibi.R
|
import app.myzel394.alibi.R
|
||||||
import app.myzel394.alibi.dataStore
|
|
||||||
import app.myzel394.alibi.db.AppSettings
|
|
||||||
import app.myzel394.alibi.db.LastRecording
|
|
||||||
import app.myzel394.alibi.ui.effects.rememberSettings
|
import app.myzel394.alibi.ui.effects.rememberSettings
|
||||||
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package app.myzel394.alibi.ui.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.AudioDeviceInfo
|
||||||
|
import android.media.AudioManager
|
||||||
|
|
||||||
|
data class MicrophoneInfo(
|
||||||
|
val deviceInfo: AudioDeviceInfo,
|
||||||
|
) {
|
||||||
|
val name: String
|
||||||
|
get() = deviceInfo.productName.toString()
|
||||||
|
|
||||||
|
val type: MicrophoneType
|
||||||
|
get() = when (deviceInfo.type) {
|
||||||
|
AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> MicrophoneType.BLUETOOTH
|
||||||
|
AudioDeviceInfo.TYPE_WIRED_HEADSET -> MicrophoneType.WIRED
|
||||||
|
AudioDeviceInfo.TYPE_BUILTIN_MIC -> MicrophoneType.PHONE
|
||||||
|
else -> MicrophoneType.OTHER
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromDeviceInfo(deviceInfo: AudioDeviceInfo): MicrophoneInfo {
|
||||||
|
return MicrophoneInfo(deviceInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
fun fetchDeviceMicrophones(context: Context): List<MicrophoneInfo> {
|
||||||
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE)!! as AudioManager
|
||||||
|
return audioManager.availableCommunicationDevices.let {
|
||||||
|
it.subList(2, it.size)
|
||||||
|
}.map(::fromDeviceInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum class MicrophoneType {
|
||||||
|
BLUETOOTH,
|
||||||
|
WIRED,
|
||||||
|
PHONE,
|
||||||
|
OTHER,
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
|
||||||
<string name="app_name">Alibi</string>
|
<string name="app_name">Alibi</string>
|
||||||
|
|
||||||
<string name="dialog_close_cancel_label">Cancel</string>
|
<string name="dialog_close_cancel_label">Cancel</string>
|
||||||
@ -64,4 +63,6 @@
|
|||||||
<string name="ui_audioRecorder_error_recording_description">Alibi encountered an error during recording. Would you like to try saving the recording?</string>
|
<string name="ui_audioRecorder_error_recording_description">Alibi encountered an error during recording. Would you like to try saving the recording?</string>
|
||||||
<string name="ui_settings_language_title">Language</string>
|
<string name="ui_settings_language_title">Language</string>
|
||||||
<string name="ui_settings_language_update_label">Change</string>
|
<string name="ui_settings_language_update_label">Change</string>
|
||||||
|
<string name="ui_audioRecorder_info_microphone_deviceMicrophone">Device Microphone</string>
|
||||||
|
<string name="ui_audioRecorder_info_microphone_changeExplanation">The selected microphone will be immediately activated</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user