mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +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:name="autoStoreLocales"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
</service>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -1,7 +1,9 @@
|
|||||||
package app.myzel394.alibi.services
|
package app.myzel394.alibi.services
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.ServiceConnection
|
||||||
import android.media.AudioDeviceCallback
|
import android.media.AudioDeviceCallback
|
||||||
import android.media.AudioDeviceInfo
|
import android.media.AudioDeviceInfo
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
@ -9,12 +11,11 @@ import android.media.MediaRecorder
|
|||||||
import android.media.MediaRecorder.OnErrorListener
|
import android.media.MediaRecorder.OnErrorListener
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
import android.os.IBinder
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
|
||||||
import app.myzel394.alibi.enums.RecorderState
|
import app.myzel394.alibi.enums.RecorderState
|
||||||
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
import java.util.concurrent.Executor
|
|
||||||
|
|
||||||
class AudioRecorderService : IntervalRecorderService() {
|
class AudioRecorderService : IntervalRecorderService() {
|
||||||
var amplitudesAmount = 1000
|
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_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_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="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>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user