mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Adding QuickSettings tile; Added tile to reflect current recording / non-recording state
This commit is contained in:
parent
fd07d04502
commit
7bdae55876
@ -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>
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
10
app/src/main/res/drawable/tile_icon.xml
Normal file
10
app/src/main/res/drawable/tile_icon.xml
Normal 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>
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user