From ebfffb153606e3d2f4fcbe0af1e3f5838902dbb4 Mon Sep 17 00:00:00 2001 From: darken Date: Sun, 8 Feb 2026 14:01:23 +0100 Subject: [PATCH] fix: Replace WorkManager with ForegroundService to eliminate excessive wakelocks Replace MonitorWorker (CoroutineWorker) with MonitorService (ForegroundService) to eliminate persistent ProcessorForegroundLck wakelock reported in Android Vitals. Add BootCompletedReceiver for post-reboot auto-start. Remove WorkManager dependency entirely. --- app/build.gradle.kts | 1 - app/src/main/AndroidManifest.xml | 29 ++- app/src/main/java/eu/darken/capod/App.kt | 26 +-- .../capod/common/dagger/AndroidModule.kt | 6 - .../capod/common/worker/WorkerExtensions.kt | 31 ---- .../core/receiver/BluetoothEventReceiver.kt | 12 +- .../core/receiver/BootCompletedReceiver.kt | 26 +++ .../monitor/core/worker/MonitorControl.kt | 52 ++---- .../{MonitorWorker.kt => MonitorService.kt} | 175 +++++++++++------- .../capod/monitor/ui/MonitorNotifications.kt | 26 +-- buildSrc/src/main/java/Dependencies.kt | 10 - 11 files changed, 169 insertions(+), 225 deletions(-) delete mode 100644 app/src/main/java/eu/darken/capod/common/worker/WorkerExtensions.kt create mode 100644 app/src/main/java/eu/darken/capod/monitor/core/receiver/BootCompletedReceiver.kt rename app/src/main/java/eu/darken/capod/monitor/core/worker/{MonitorWorker.kt => MonitorService.kt} (63%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2082260f..e5ed95de 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -158,7 +158,6 @@ dependencies { implementation("androidx.core:core-splashscreen:1.0.0-alpha02") addNavigation() - addBaseWorkManager() addTesting() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ddaad4b2..64afb314 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ @@ -9,6 +8,8 @@ + + @@ -65,6 +66,14 @@ + + + + + + - - - - - - - + android:exported="false" /> \ No newline at end of file diff --git a/app/src/main/java/eu/darken/capod/App.kt b/app/src/main/java/eu/darken/capod/App.kt index 2437d337..32287d52 100644 --- a/app/src/main/java/eu/darken/capod/App.kt +++ b/app/src/main/java/eu/darken/capod/App.kt @@ -1,10 +1,7 @@ package eu.darken.capod import android.app.Application -import androidx.hilt.work.HiltWorkerFactory -import androidx.work.Configuration import dagger.hilt.android.HiltAndroidApp -import eu.darken.capod.common.BuildConfigWrap import eu.darken.capod.common.coroutine.AppScope import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter import eu.darken.capod.common.debug.logging.LogCatLogger @@ -23,13 +20,11 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch import javax.inject.Inject @HiltAndroidApp -open class App : Application(), Configuration.Provider { +open class App : Application() { - @Inject lateinit var workerFactory: HiltWorkerFactory @Inject lateinit var autoReporting: AutomaticBugReporter @Inject lateinit var monitorControl: MonitorControl @Inject lateinit var podMonitor: PodMonitor @@ -45,9 +40,7 @@ open class App : Application(), Configuration.Provider { log(TAG) { "onCreate() done! ${Exception().asLog()}" } - appScope.launch { - monitorControl.startMonitor(forceStart = true) - } + monitorControl.startMonitor(forceStart = true) podMonitor.devicesWithProfiles() .distinctUntilChanged() @@ -68,21 +61,6 @@ open class App : Application(), Configuration.Provider { .launchIn(appScope) } - - override val workManagerConfiguration: Configuration - get() = Configuration.Builder() - .setMinimumLoggingLevel( - when { - BuildConfigWrap.DEBUG -> android.util.Log.VERBOSE - BuildConfigWrap.BUILD_TYPE == BuildConfigWrap.BuildType.DEV -> android.util.Log.DEBUG - BuildConfigWrap.BUILD_TYPE == BuildConfigWrap.BuildType.BETA -> android.util.Log.INFO - BuildConfigWrap.BUILD_TYPE == BuildConfigWrap.BuildType.RELEASE -> android.util.Log.WARN - else -> android.util.Log.VERBOSE - } - ) - .setWorkerFactory(workerFactory) - .build() - companion object { internal val TAG = logTag("CAP") } diff --git a/app/src/main/java/eu/darken/capod/common/dagger/AndroidModule.kt b/app/src/main/java/eu/darken/capod/common/dagger/AndroidModule.kt index 57905e34..32ddfdfd 100644 --- a/app/src/main/java/eu/darken/capod/common/dagger/AndroidModule.kt +++ b/app/src/main/java/eu/darken/capod/common/dagger/AndroidModule.kt @@ -5,7 +5,6 @@ import android.app.NotificationManager import android.bluetooth.BluetoothManager import android.content.Context import android.media.AudioManager -import androidx.work.WorkManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -30,11 +29,6 @@ class AndroidModule { fun bluetoothManager(context: Context): BluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - @Provides - @Singleton - fun workerManager(context: Context): WorkManager = - WorkManager.getInstance(context) - @Provides @Singleton fun audioManager(context: Context): AudioManager = diff --git a/app/src/main/java/eu/darken/capod/common/worker/WorkerExtensions.kt b/app/src/main/java/eu/darken/capod/common/worker/WorkerExtensions.kt deleted file mode 100644 index 19f6127f..00000000 --- a/app/src/main/java/eu/darken/capod/common/worker/WorkerExtensions.kt +++ /dev/null @@ -1,31 +0,0 @@ -package eu.darken.capod.common.worker - -import android.os.Parcel -import android.os.Parcelable -import androidx.work.Data - -@Suppress("UNCHECKED_CAST") -inline fun Data.getParcelable(key: String): T? { - val parcel = Parcel.obtain() - try { - val bytes = getByteArray(key) ?: return null - parcel.unmarshall(bytes, 0, bytes.size) - parcel.setDataPosition(0) - val creator = T::class.java.getField("CREATOR").get(null) as Parcelable.Creator - return creator.createFromParcel(parcel) - } finally { - parcel.recycle() - } -} - - -fun Data.Builder.putParcelable(key: String, parcelable: Parcelable): Data.Builder { - val parcel = Parcel.obtain() - try { - parcelable.writeToParcel(parcel, 0) - putByteArray(key, parcel.marshall()) - } finally { - parcel.recycle() - } - return this -} diff --git a/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt index 1961c6de..f4ac545c 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BluetoothEventReceiver.kt @@ -8,21 +8,17 @@ import android.content.Context import android.content.Intent import dagger.hilt.android.AndroidEntryPoint import eu.darken.capod.common.bluetooth.hasFeature -import eu.darken.capod.common.coroutine.AppScope import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.monitor.core.worker.MonitorControl import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint class BluetoothEventReceiver : BroadcastReceiver() { @Inject lateinit var monitorControl: MonitorControl - @Inject @AppScope lateinit var appScope: CoroutineScope override fun onReceive(context: Context, intent: Intent) { log(TAG) { "onReceive($context, $intent)" } @@ -47,12 +43,8 @@ class BluetoothEventReceiver : BroadcastReceiver() { log { "Device has the following we features we support $supportedFeatures" } } - val pending = goAsync() - appScope.launch { - log(TAG) { "Starting monitor" } - monitorControl.startMonitor(bluetoothDevice, forceStart = false) - pending.finish() - } + log(TAG) { "Starting monitor" } + monitorControl.startMonitor(forceStart = false) } companion object { diff --git a/app/src/main/java/eu/darken/capod/monitor/core/receiver/BootCompletedReceiver.kt b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BootCompletedReceiver.kt new file mode 100644 index 00000000..9400c09a --- /dev/null +++ b/app/src/main/java/eu/darken/capod/monitor/core/receiver/BootCompletedReceiver.kt @@ -0,0 +1,26 @@ +package eu.darken.capod.monitor.core.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import dagger.hilt.android.AndroidEntryPoint +import eu.darken.capod.common.debug.logging.log +import eu.darken.capod.common.debug.logging.logTag +import eu.darken.capod.monitor.core.worker.MonitorControl +import javax.inject.Inject + +@AndroidEntryPoint +class BootCompletedReceiver : BroadcastReceiver() { + + @Inject lateinit var monitorControl: MonitorControl + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != Intent.ACTION_BOOT_COMPLETED) return + log(TAG) { "Boot completed, starting monitor." } + monitorControl.startMonitor(forceStart = false) + } + + companion object { + private val TAG = logTag("Monitor", "BootReceiver") + } +} diff --git a/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorControl.kt b/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorControl.kt index 19479ab3..f5ea4536 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorControl.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorControl.kt @@ -1,51 +1,39 @@ package eu.darken.capod.monitor.core.worker -import android.bluetooth.BluetoothDevice -import androidx.work.Data -import androidx.work.ExistingWorkPolicy -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkManager -import eu.darken.capod.common.BuildConfigWrap -import eu.darken.capod.common.coroutine.DispatcherProvider +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE +import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag -import kotlinx.coroutines.withContext +import eu.darken.capod.common.startServiceCompat import javax.inject.Inject import javax.inject.Singleton @Singleton class MonitorControl @Inject constructor( - private val workerManager: WorkManager, - private val dispatcherProvider: DispatcherProvider, + @ApplicationContext private val context: Context, ) { - suspend fun startMonitor( - bluetoothDevice: BluetoothDevice? = null, + fun startMonitor( forceStart: Boolean = false, - ): Unit = withContext(dispatcherProvider.IO) { - val workerData = Data.Builder().apply { + ) { + log(TAG, VERBOSE) { "startMonitor(forceStart=$forceStart)" } + try { + context.startServiceCompat(MonitorService.intent(context, forceStart)) + log(TAG) { "Monitor start request sent." } + } catch (e: IllegalStateException) { + log(TAG, WARN) { "Failed to start monitor service: ${e.message}" } + } + } - }.build() - log(TAG, VERBOSE) { "Worker data: $workerData" } - - val workRequest = OneTimeWorkRequestBuilder().apply { - setInputData(workerData) - }.build() - - log(TAG, VERBOSE) { "Worker request: $workRequest" } - - val operation = workerManager.enqueueUniqueWork( - "${BuildConfigWrap.APPLICATION_ID}.monitor.worker", - if (forceStart) ExistingWorkPolicy.REPLACE else ExistingWorkPolicy.KEEP, - workRequest, - ) - - operation.result.get() - log(TAG) { "Monitor start request send." } + fun stopMonitor() { + log(TAG, VERBOSE) { "stopMonitor()" } + context.stopService(MonitorService.intent(context)) + log(TAG) { "Monitor stop request sent." } } companion object { private val TAG = logTag("Monitor", "Control") } -} \ No newline at end of file +} diff --git a/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorWorker.kt b/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorService.kt similarity index 63% rename from app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorWorker.kt rename to app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorService.kt index aee08c35..1098c332 100644 --- a/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorWorker.kt +++ b/app/src/main/java/eu/darken/capod/monitor/core/worker/MonitorService.kt @@ -1,13 +1,13 @@ package eu.darken.capod.monitor.core.worker +import android.annotation.SuppressLint import android.app.NotificationManager +import android.app.Service import android.content.Context -import androidx.hilt.work.HiltWorker -import androidx.work.CoroutineWorker -import androidx.work.ForegroundInfo -import androidx.work.WorkerParameters -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject +import android.content.Intent +import android.content.pm.ServiceInfo +import android.os.IBinder +import dagger.hilt.android.AndroidEntryPoint import eu.darken.capod.common.bluetooth.BluetoothDevice2 import eu.darken.capod.common.bluetooth.BluetoothManager2 import eu.darken.capod.common.coroutine.DispatcherProvider @@ -19,6 +19,7 @@ import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.flow.setupCommonEventHandlers import eu.darken.capod.common.flow.throttleLatest +import eu.darken.capod.common.hasApiLevel import eu.darken.capod.main.core.GeneralSettings import eu.darken.capod.main.core.MonitorMode import eu.darken.capod.main.core.PermissionTool @@ -33,6 +34,7 @@ import eu.darken.capod.reaction.core.playpause.PlayPause import eu.darken.capod.reaction.core.popup.PopUpReaction import eu.darken.capod.reaction.ui.popup.PopUpWindow import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Job import kotlinx.coroutines.cancel import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.delay @@ -45,78 +47,87 @@ import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Inject +@AndroidEntryPoint +class MonitorService : Service() { -@HiltWorker -class MonitorWorker @AssistedInject constructor( - @Assisted private val context: Context, - @Assisted private val params: WorkerParameters, - private val dispatcherProvider: DispatcherProvider, - private val notifications: MonitorNotifications, - private val notificationManager: NotificationManager, - private val generalSettings: GeneralSettings, - private val permissionTool: PermissionTool, - private val podMonitor: PodMonitor, - private val bluetoothManager: BluetoothManager2, - private val playPause: PlayPause, - private val autoConnect: AutoConnect, - private val popUpReaction: PopUpReaction, - private val popUpWindow: PopUpWindow, - private val profilesRepo: DeviceProfilesRepo, -) : CoroutineWorker(context, params) { + @Inject lateinit var dispatcherProvider: DispatcherProvider + @Inject lateinit var notifications: MonitorNotifications + @Inject lateinit var notificationManager: NotificationManager + @Inject lateinit var generalSettings: GeneralSettings + @Inject lateinit var permissionTool: PermissionTool + @Inject lateinit var podMonitor: PodMonitor + @Inject lateinit var bluetoothManager: BluetoothManager2 + @Inject lateinit var playPause: PlayPause + @Inject lateinit var autoConnect: AutoConnect + @Inject lateinit var popUpReaction: PopUpReaction + @Inject lateinit var popUpWindow: PopUpWindow + @Inject lateinit var profilesRepo: DeviceProfilesRepo - private val workerScope = MonitorCoroutineScope() + private val monitorScope = MonitorCoroutineScope() + private var monitoringJob: Job? = null + @Volatile private var monitorGeneration = 0 - private var finishedWithError = false + @SuppressLint("InlinedApi") + override fun onCreate() { + super.onCreate() + log(TAG, VERBOSE) { "onCreate()" } - init { - log(TAG, VERBOSE) { "init(): workerId=$id" } - } - - override suspend fun getForegroundInfo(): ForegroundInfo { - return notifications.getForegroundInfo(null) - } - - override suspend fun doWork(): Result = try { - val start = System.currentTimeMillis() - log(TAG, VERBOSE) { "Executing $inputData now (runAttemptCount=$runAttemptCount)" } - - doDoWork() - - val duration = System.currentTimeMillis() - start - - log(TAG, VERBOSE) { "Execution finished after ${duration}ms, $inputData" } - - Result.success(inputData) - } catch (e: Throwable) { - if (e !is CancellationException) { - Bugs.report(tag = TAG, "Execution failed", exception = e) - finishedWithError = true - Result.failure(inputData) + val notification = notifications.getStartupNotification() + if (hasApiLevel(29)) { + startForeground( + MonitorNotifications.NOTIFICATION_ID, + notification, + ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE, + ) } else { - Result.success() + startForeground(MonitorNotifications.NOTIFICATION_ID, notification) } - } finally { - if (generalSettings.useExtraMonitorNotification.value && !generalSettings.keepConnectedNotificationAfterDisconnect.value) { + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + log(TAG, VERBOSE) { "onStartCommand(intent=$intent, flags=$flags, startId=$startId)" } + + val forceStart = intent?.getBooleanExtra(EXTRA_FORCE_START, false) ?: false + + if (monitoringJob?.isActive == true && !forceStart) { + log(TAG) { "Already monitoring and forceStart=false, keeping current session." } + return START_STICKY + } + + val generation = ++monitorGeneration + monitorScope.coroutineContext.cancelChildren() + + monitoringJob = monitorScope.launch { try { - notificationManager.cancel(MonitorNotifications.NOTIFICATION_ID_CONNECTED) + doMonitor() + } catch (e: CancellationException) { + log(TAG) { "Monitor cancelled." } } catch (e: Exception) { - log(TAG, WARN) { "Failed to cancel connected notification: ${e.message}" } + Bugs.report(tag = TAG, "Monitor failed", exception = e) + } finally { + if (monitorGeneration == generation) { + log(TAG) { "Monitor finished, stopping service." } + stopSelf() + } else { + log(TAG) { "Monitor replaced, not stopping service." } + } } } - this.workerScope.cancel("Worker finished (withError?=$finishedWithError).") + + return START_STICKY } - private suspend fun doDoWork() { + private suspend fun doMonitor() { val permissionsMissingOnStart = permissionTool.missingPermissions.first() if (permissionsMissingOnStart.isNotEmpty()) { log(TAG, WARN) { "Aborting, missing permissions: $permissionsMissingOnStart" } return } - setForeground(notifications.getForegroundInfo(null)) - val monitorJob = podMonitor.primaryDevice() .setupCommonEventHandlers(TAG) { "PodMonitor" } .distinctUntilChanged() @@ -136,13 +147,13 @@ class MonitorWorker @AssistedInject constructor( .catch { log(TAG, WARN) { "Pod Flow failed:\n${it.asLog()}" } } - .launchIn(workerScope) + .launchIn(monitorScope) permissionTool.missingPermissions .flatMapLatest { missingPermsFlow -> if (missingPermsFlow.isNotEmpty()) { log(TAG, WARN) { "Aborting, permissions are missing: $missingPermsFlow" } - workerScope.coroutineContext.cancelChildren() + monitorScope.coroutineContext.cancelChildren() emptyFlow() } else { combine( @@ -163,7 +174,6 @@ class MonitorWorker @AssistedInject constructor( @Suppress("UNCHECKED_CAST") val devices = arguments[2] as Collection - val connectedAddresses = devices.map { it.address }.toSet() val knownAddresses = profiles.mapNotNull { it.address }.toSet() log(TAG) { "Monitor mode: $monitorMode" } @@ -172,8 +182,7 @@ class MonitorWorker @AssistedInject constructor( when (monitorMode) { MonitorMode.MANUAL -> flow { - // Cancel worker, ui scans manually - workerScope.coroutineContext.cancelChildren() + monitorScope.coroutineContext.cancelChildren() } MonitorMode.ALWAYS -> emptyFlow() @@ -188,11 +197,11 @@ class MonitorWorker @AssistedInject constructor( } else -> { - log(TAG) { "No known Pods are connected, canceling worker soon." } + log(TAG) { "No known Pods are connected, stopping service soon." } delay(15 * 1000) - log(TAG) { "Canceling worker now, still no Pods connected." } + log(TAG) { "Stopping service now, still no Pods connected." } - workerScope.coroutineContext.cancelChildren() + monitorScope.coroutineContext.cancelChildren() } } } @@ -201,7 +210,7 @@ class MonitorWorker @AssistedInject constructor( .catch { log(TAG, WARN) { "MonitorMode Flow failed:\n${it.asLog()}" } } - .launchIn(workerScope) + .launchIn(monitorScope) popUpReaction.monitor() .onEach { @@ -214,24 +223,48 @@ class MonitorWorker @AssistedInject constructor( } .setupCommonEventHandlers(TAG) { "popUpReaction" } .catch { log(TAG, WARN) { "popUpReaction failed:\n${it.asLog()}" } } - .launchIn(workerScope) + .launchIn(monitorScope) playPause.monitor() .setupCommonEventHandlers(TAG) { "playPause" } .catch { log(TAG, WARN) { "playPause failed:\n${it.asLog()}" } } - .launchIn(workerScope) + .launchIn(monitorScope) autoConnect.monitor() .setupCommonEventHandlers(TAG) { "autoConnect" } .catch { log(TAG, WARN) { "autoConnect failed:\n${it.asLog()}" } } - .launchIn(workerScope) + .launchIn(monitorScope) log(TAG, VERBOSE) { "Monitor job is active" } monitorJob.join() log(TAG, VERBOSE) { "Monitor job quit" } } + override fun onDestroy() { + log(TAG, VERBOSE) { "onDestroy()" } + monitorScope.cancel("Service destroyed") + + if (generalSettings.useExtraMonitorNotification.value && !generalSettings.keepConnectedNotificationAfterDisconnect.value) { + try { + notificationManager.cancel(MonitorNotifications.NOTIFICATION_ID_CONNECTED) + } catch (e: Exception) { + log(TAG, WARN) { "Failed to cancel connected notification: ${e.message}" } + } + } + + super.onDestroy() + } + + override fun onBind(intent: Intent?): IBinder? = null + companion object { - val TAG = logTag("Monitor", "Worker") + val TAG = logTag("Monitor", "Service") + private const val EXTRA_FORCE_START = "extra.force_start" + + fun intent(context: Context, forceStart: Boolean = false): Intent { + return Intent(context, MonitorService::class.java).apply { + putExtra(EXTRA_FORCE_START, forceStart) + } + } } } diff --git a/app/src/main/java/eu/darken/capod/monitor/ui/MonitorNotifications.kt b/app/src/main/java/eu/darken/capod/monitor/ui/MonitorNotifications.kt index dcd6b9ad..4aefd09c 100644 --- a/app/src/main/java/eu/darken/capod/monitor/ui/MonitorNotifications.kt +++ b/app/src/main/java/eu/darken/capod/monitor/ui/MonitorNotifications.kt @@ -1,22 +1,18 @@ package eu.darken.capod.monitor.ui -import android.annotation.SuppressLint import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.content.pm.ServiceInfo import androidx.core.app.NotificationCompat -import androidx.work.ForegroundInfo import dagger.hilt.android.qualifiers.ApplicationContext import eu.darken.capod.R import eu.darken.capod.common.BuildConfigWrap import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag -import eu.darken.capod.common.hasApiLevel import eu.darken.capod.common.notifications.PendingIntentCompat import eu.darken.capod.main.ui.MainActivity import eu.darken.capod.pods.core.DualPodDevice @@ -157,25 +153,9 @@ class MonitorNotifications @Inject constructor( }.build() } - suspend fun getForegroundInfo(podDevice: PodDevice?): ForegroundInfo = builderLock.withLock { - getBuilder(podDevice).apply { - setChannelId(NOTIFICATION_CHANNEL_ID) - }.toForegroundInfo() - } - - @SuppressLint("InlinedApi") - private fun NotificationCompat.Builder.toForegroundInfo(): ForegroundInfo = if (hasApiLevel(29)) { - ForegroundInfo( - NOTIFICATION_ID, - this.build(), - ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE - ) - } else { - ForegroundInfo( - NOTIFICATION_ID, - this.build() - ) - } + fun getStartupNotification(): Notification = getBuilder(null).apply { + setChannelId(NOTIFICATION_CHANNEL_ID) + }.build() companion object { val TAG = logTag("Monitor", "Notifications") diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index afccc64d..64f8556e 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -76,16 +76,6 @@ fun DependencyHandlerScope.addNavigation() { androidTestImplementation("androidx.navigation:navigation-testing:${Versions.AndroidX.Navigation.core}") } -fun DependencyHandlerScope.addBaseWorkManager() { - val version = "2.9.0" - implementation("androidx.work:work-runtime:$version") - testImplementation("androidx.work:work-testing:$version") - implementation("androidx.work:work-runtime-ktx:$version") - - implementation("androidx.hilt:hilt-work:1.0.0") - kapt("androidx.hilt:hilt-compiler:1.0.0") -} - fun DependencyHandlerScope.addBaseAndroid() { implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.annotation:annotation:1.7.0")