mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Add boot notification
This commit is contained in:
parent
60fc16f2c4
commit
2e9f1c7ade
@ -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)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -19,7 +19,7 @@ data class AppSettings(
|
||||
val showAdvancedSettings: Boolean = false,
|
||||
val theme: Theme = Theme.SYSTEM,
|
||||
val lastRecording: RecordingInformation? = null,
|
||||
val bootBehavior: BootBehavior? = BootBehavior.START_RECORDING,
|
||||
val bootBehavior: BootBehavior? = BootBehavior.SHOW_NOTIFICATION,
|
||||
) {
|
||||
fun setShowAdvancedSettings(showAdvancedSettings: Boolean): AppSettings {
|
||||
return copy(showAdvancedSettings = showAdvancedSettings)
|
||||
@ -56,7 +56,13 @@ data class AppSettings(
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
|
@ -1,42 +1,118 @@
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
val intent = Intent(context, AudioRecorderService::class.java).apply {
|
||||
action = "init"
|
||||
if (settings.notificationSettings != null) {
|
||||
putExtra(
|
||||
"notificationDetails",
|
||||
Json.encodeToString(
|
||||
RecorderNotificationHelper.NotificationDetails.serializer(),
|
||||
RecorderNotificationHelper.NotificationDetails.fromNotificationSettings(
|
||||
context,
|
||||
settings.notificationSettings
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
context.bindService(intent, connection, 0)
|
||||
}
|
||||
|
||||
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?) {
|
||||
println("Received new intent: ${intent?.action}")
|
||||
if (intent?.action != Intent.ACTION_BOOT_COMPLETED || context == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||
println("Starting service")
|
||||
scope.launch {
|
||||
context.dataStore.data.collectLatest { settings ->
|
||||
when (settings.bootBehavior) {
|
||||
AppSettings.BootBehavior.CONTINUE_RECORDING -> {
|
||||
if (AudioRecorderExporter.hasRecordingsAvailable(context)) {
|
||||
startRecording(context, settings)
|
||||
}
|
||||
}
|
||||
|
||||
val connection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
((service as RecorderService.RecorderBinder).getService() as AudioRecorderService).also { recorder ->
|
||||
recorder.startRecording()
|
||||
AppSettings.BootBehavior.START_RECORDING -> startRecording(context, settings)
|
||||
AppSettings.BootBehavior.SHOW_NOTIFICATION -> showNotification(context)
|
||||
null -> {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(arg0: ComponentName) {
|
||||
}
|
||||
}
|
||||
|
||||
val intent = Intent(context, AudioRecorderService::class.java).apply {
|
||||
action = "initStart"
|
||||
}
|
||||
println("Starting service checking context")
|
||||
if (context != null) {
|
||||
println("Starting service with context")
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -111,4 +111,8 @@
|
||||
<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_bootBehavior_title">Boot Behavior</string>
|
||||
<string name="ui_settings_bootBehavior_values_SHOW_NOTIFICATION_title">Show a notification</string>
|
||||
<string name="notificationChannels_boot_name">Boot notification</string>
|
||||
<string name="notificationChannels_boot_description">If enabled, you\'ll be informed that your recording was interrupted</string>
|
||||
<string name="notification_boot_title">Alibi was interrupted</string>
|
||||
<string name="notification_boot_message">Your device restarted and your recording has been interrupted</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user