diff --git a/app/src/main/java/io/heckel/ntfy/data/Repository.kt b/app/src/main/java/io/heckel/ntfy/data/Repository.kt index 89f955c..43d7cd1 100644 --- a/app/src/main/java/io/heckel/ntfy/data/Repository.kt +++ b/app/src/main/java/io/heckel/ntfy/data/Repository.kt @@ -177,6 +177,16 @@ class Repository(private val sharedPrefs: SharedPreferences, private val subscri .apply() } + fun getWakelockEnabled(): Boolean { + return sharedPrefs.getBoolean(SHARED_PREFS_WAKELOCK_ENABLED, true) // Enabled by default + } + + fun setWakelockEnabled(enabled: Boolean) { + sharedPrefs.edit() + .putBoolean(SHARED_PREFS_WAKELOCK_ENABLED, enabled) + .apply() + } + fun getBroadcastEnabled(): Boolean { return sharedPrefs.getBoolean(SHARED_PREFS_BROADCAST_ENABLED, true) // Enabled by default } @@ -308,6 +318,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val subscri const val SHARED_PREFS_MUTED_UNTIL_TIMESTAMP = "MutedUntil" const val SHARED_PREFS_MIN_PRIORITY = "MinPriority" const val SHARED_PREFS_AUTO_DOWNLOAD_MAX_SIZE = "AutoDownload" + const val SHARED_PREFS_WAKELOCK_ENABLED = "WakelockEnabled" const val SHARED_PREFS_BROADCAST_ENABLED = "BroadcastEnabled" const val SHARED_PREFS_UNIFIED_PUSH_ENABLED = "UnifiedPushEnabled" const val SHARED_PREFS_UNIFIED_PUSH_BASE_URL = "UnifiedPushBaseURL" diff --git a/app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt b/app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt index 54ff6b2..06e2587 100644 --- a/app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt +++ b/app/src/main/java/io/heckel/ntfy/service/SubscriberService.kt @@ -4,10 +4,7 @@ import android.app.* import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.Build -import android.os.IBinder -import android.os.PowerManager -import android.os.SystemClock +import android.os.* import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat @@ -92,6 +89,7 @@ class SubscriberService : Service() { override fun onDestroy() { Log.d(TAG, "Subscriber service has been destroyed") + stopService() sendBroadcast(Intent(this, AutoRestartReceiver::class.java)) // Restart it if necessary! super.onDestroy() } @@ -105,9 +103,10 @@ class SubscriberService : Service() { isServiceStarted = true saveServiceState(this, ServiceState.STARTED) wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG).apply { - acquire() - } + newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG) + } + if (repository.getWakelockEnabled()) { + wakeLock?.acquire() } refreshConnections() } @@ -122,10 +121,12 @@ class SubscriberService : Service() { // Releasing wake-lock and stopping ourselves try { wakeLock?.let { - if (it.isHeld) { + // Release all acquire() + while (it.isHeld) { it.release() } } + wakeLock = null stopForeground(true) stopSelf() } catch (e: Exception) { @@ -201,6 +202,12 @@ class SubscriberService : Service() { } private fun onNotificationReceived(subscription: Subscription, notification: io.heckel.ntfy.data.Notification) { + // If permanent wakelock is not enabled, still take the wakelock while notifications are being dispatched + if (!repository.getWakelockEnabled()) { + // Wakelocks are reference counted by default so that should work neatly here + wakeLock?.acquire(10*60*1000L /*10 minutes*/) + } + val url = topicUrl(subscription.baseUrl, subscription.topic) Log.d(TAG, "[$url] Received notification: $notification") GlobalScope.launch(Dispatchers.IO) { @@ -208,6 +215,14 @@ class SubscriberService : Service() { Log.d(TAG, "[$url] Dispatching notification $notification") dispatcher.dispatch(subscription, notification) } + + if (!repository.getWakelockEnabled()) { + wakeLock?.let { + if (it.isHeld) { + it.release() + } + } + } } } diff --git a/app/src/main/java/io/heckel/ntfy/ui/SettingsActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/SettingsActivity.kt index 559aa51..f0f1cb4 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/SettingsActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/SettingsActivity.kt @@ -1,9 +1,7 @@ package io.heckel.ntfy.ui import android.Manifest -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context +import android.content.* import android.content.pm.PackageManager import android.os.Build import android.os.Bundle @@ -20,6 +18,7 @@ import io.heckel.ntfy.BuildConfig import io.heckel.ntfy.R import io.heckel.ntfy.app.Application import io.heckel.ntfy.data.Repository +import io.heckel.ntfy.service.SubscriberService import io.heckel.ntfy.util.formatBytes import io.heckel.ntfy.util.formatDateShort import io.heckel.ntfy.util.toPriorityString @@ -149,6 +148,31 @@ class SettingsActivity : AppCompatActivity() { } } + // Permanent wakelock enabled + val wakelockEnabledPrefId = context?.getString(R.string.settings_advanced_wakelock_key) ?: return + val wakelockEnabled: SwitchPreference? = findPreference(wakelockEnabledPrefId) + wakelockEnabled?.isChecked = repository.getWakelockEnabled() + wakelockEnabled?.preferenceDataStore = object : PreferenceDataStore() { + override fun putBoolean(key: String?, value: Boolean) { + repository.setWakelockEnabled(value) + val context = this@SettingsFragment.context + Intent(context, SubscriberService::class.java).also { intent -> + // Service will autorestart + context?.stopService(intent) + } + } + override fun getBoolean(key: String?, defValue: Boolean): Boolean { + return repository.getWakelockEnabled() + } + } + wakelockEnabled?.summaryProvider = Preference.SummaryProvider { pref -> + if (pref.isChecked) { + getString(R.string.settings_advanced_wakelock_summary_enabled) + } else { + getString(R.string.settings_advanced_wakelock_summary_disabled) + } + } + // Broadcast enabled val broadcastEnabledPrefId = context?.getString(R.string.settings_advanced_broadcast_key) ?: return val broadcastEnabled: SwitchPreference? = findPreference(broadcastEnabledPrefId) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e6ed19d..0e91b5d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -216,6 +216,10 @@ Server URL %1$s (default) Advanced + WakelockEnabled + Permanent wakelock + Prevents app from sleeping to ensure timely notification delivery. This consumes a lot of battery, but some devices require this. + Allows app to enter sleep mode. This may negatively impact notification delivery. It depends on the device. BroadcastEnabled Broadcast messages Apps can receive incoming notifications as broadcasts diff --git a/app/src/main/res/xml/main_preferences.xml b/app/src/main/res/xml/main_preferences.xml index bc0a169..c7239ca 100644 --- a/app/src/main/res/xml/main_preferences.xml +++ b/app/src/main/res/xml/main_preferences.xml @@ -34,6 +34,10 @@ app:dependency="@string/settings_unified_push_enabled_key"/> +