feat: Adding QuickSettings tile; Added tile to reflect current recording / non-recording state

This commit is contained in:
Myzel394 2023-10-28 15:06:35 +02:00
parent fd07d04502
commit 7bdae55876
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
5 changed files with 194 additions and 3 deletions

View File

@ -56,6 +56,17 @@
android:name="autoStoreLocales"
android:value="true" />
</service>
<service
android:name=".services.AudioRecorderTileService"
android:label="@string/tile_label"
android:icon="@drawable/tile_icon"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
</application>
</manifest>

View File

@ -1,7 +1,9 @@
package app.myzel394.alibi.services
import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.media.AudioDeviceCallback
import android.media.AudioDeviceInfo
import android.media.AudioManager
@ -9,12 +11,11 @@ import android.media.MediaRecorder
import android.media.MediaRecorder.OnErrorListener
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import androidx.core.content.ContextCompat.getSystemService
import app.myzel394.alibi.enums.RecorderState
import app.myzel394.alibi.ui.utils.MicrophoneInfo
import java.lang.IllegalStateException
import java.util.concurrent.Executor
class AudioRecorderService : IntervalRecorderService() {
var amplitudesAmount = 1000

View File

@ -0,0 +1,168 @@
package app.myzel394.alibi.services
import android.app.ActivityManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import androidx.core.content.ContextCompat
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.enums.RecorderState
import app.myzel394.alibi.helpers.AudioRecorderExporter
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
class AudioRecorderTileService : TileService() {
private var job = SupervisorJob()
private var scope = CoroutineScope(Dispatchers.IO + job)
private var connection: ServiceConnection? = null
override fun onStartListening() {
super.onStartListening()
println("Before start")
scope.launch {
println("Getting recorder...")
val state = getRecorderState()
println("All right updating")
updateTile(state)
}
}
override fun onStopListening() {
runCatching {
connection?.let { unbindService(it) }
connection = null
}
super.onStopListening()
}
private fun startRecording() {
scope.launch {
dataStore.data.collectLatest { appSettings ->
val notificationDetails = appSettings.notificationSettings?.let {
RecorderNotificationHelper.NotificationDetails.fromNotificationSettings(
this@AudioRecorderTileService,
it,
)
}
val intent =
Intent(this@AudioRecorderTileService, AudioRecorderService::class.java).apply {
action = "init"
if (notificationDetails != null) {
putExtra(
"notificationDetails",
Json.encodeToString(
RecorderNotificationHelper.NotificationDetails.serializer(),
notificationDetails,
),
)
}
}
ContextCompat.startForegroundService(this@AudioRecorderTileService, intent)
}
}
}
override fun onClick() {
super.onClick()
scope.launch {
val state = getRecorderState()
when (state) {
RecorderState.IDLE -> {
AudioRecorderExporter.clearAllRecordings(this@AudioRecorderTileService)
startRecording()
}
RecorderState.RECORDING -> {
}
RecorderState.PAUSED -> {
}
}
}
}
private fun isAudioRecorderRunning(): Boolean {
val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
if (AudioRecorderService::class.java.name == service.service.className) {
return true
}
}
return false
}
private suspend fun getRecorder(): AudioRecorderService? {
if (!isAudioRecorderRunning()) {
return null
}
val completer = CompletableDeferred<AudioRecorderService?>()
connection = object : ServiceConnection {
override fun onServiceConnected(p0: ComponentName?, binder: IBinder?) {
completer.complete((binder as RecorderService.RecorderBinder).getService() as AudioRecorderService)
}
override fun onServiceDisconnected(p0: ComponentName?) {
unbindService(this)
connection = null
}
override fun onNullBinding(name: ComponentName?) {
unbindService(this)
connection = null
completer.complete(null)
}
}
bindService(
Intent(this, AudioRecorderService::class.java),
connection!!,
0,
)
return completer.await()
}
private suspend fun getRecorderState(): RecorderState {
return getRecorder()?.state ?: RecorderState.IDLE
}
fun updateTile(state: RecorderState) {
when (state) {
RecorderState.RECORDING -> {
qsTile.label = getString(R.string.ui_audioRecorder_action_save_label)
qsTile.state = Tile.STATE_ACTIVE
}
RecorderState.IDLE -> {
qsTile.label = getString(R.string.ui_audioRecorder_action_start_label)
qsTile.state = Tile.STATE_INACTIVE
}
RecorderState.PAUSED -> {
}
}
println("Applying upäit naow")
qsTile.updateTile()
}
}

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="250"
android:viewportHeight="250">
<path
android:pathData="M191,125C191,161.45 161.45,191 125,191C88.55,191 59,161.45 59,125C59,88.55 88.55,59 125,59C161.45,59 191,88.55 191,125ZM110,137C110,142.52 105.52,147 100,147C94.48,147 90,142.52 90,137C90,131.48 94.48,127 100,127C105.52,127 110,131.48 110,137ZM150,147C155.52,147 160,142.52 160,137C160,131.48 155.52,127 150,127C144.48,127 140,131.48 140,137C140,142.52 144.48,147 150,147Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</vector>

View File

@ -109,4 +109,5 @@
<string name="ui_about_contribute_donation_githubSponsors">Become a GitHub Sponsor</string>
<string name="ui_settings_option_deleteRecordingsImmediately_title">Delete Recordings Immediately</string>
<string name="ui_settings_option_deleteRecordingsImmediately_description">If enabled, Alibi will immediately delete recordings after you have saved the file.</string>
<string name="tile_label">Start Alibi Recording</string>
</resources>