diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0954ec8d..594c1b4c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,8 +6,6 @@
-
-
@@ -63,10 +61,6 @@
tools:node="remove">
-
-
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/App.kt b/app/src/main/kotlin/at/bitfire/davdroid/App.kt
index 5a5674cf..fedf98c2 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/App.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/App.kt
@@ -97,9 +97,6 @@ class App: Application(), Thread.UncaughtExceptionHandler, Configuration.Provide
// watch for account changes/deletions
accountsUpdatedListener.listen()
- // foreground service (possible workaround for devices which prevent DAVx5 from being started)
- ForegroundService.startOrStop(this)
-
// watch storage because low storage means synchronization is stopped
storageLowReceiver.listen()
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ForegroundService.kt b/app/src/main/kotlin/at/bitfire/davdroid/ForegroundService.kt
deleted file mode 100644
index 9c1ef3df..00000000
--- a/app/src/main/kotlin/at/bitfire/davdroid/ForegroundService.kt
+++ /dev/null
@@ -1,116 +0,0 @@
-/***************************************************************************************************
- * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
- **************************************************************************************************/
-
-package at.bitfire.davdroid
-
-import android.app.PendingIntent
-import android.app.Service
-import android.content.Context
-import android.content.Intent
-import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
-import android.os.Build
-import android.os.PowerManager
-import androidx.core.app.NotificationCompat
-import androidx.core.app.NotificationManagerCompat
-import androidx.core.app.ServiceCompat
-import androidx.core.content.getSystemService
-import at.bitfire.davdroid.settings.Settings
-import at.bitfire.davdroid.settings.SettingsManager
-import at.bitfire.davdroid.ui.AppSettingsActivity
-import at.bitfire.davdroid.ui.NotificationUtils
-import at.bitfire.davdroid.ui.NotificationUtils.notifyIfPossible
-import dagger.hilt.EntryPoint
-import dagger.hilt.InstallIn
-import dagger.hilt.android.EntryPointAccessors
-import dagger.hilt.components.SingletonComponent
-
-class ForegroundService : Service() {
-
- companion object {
-
- @EntryPoint
- @InstallIn(SingletonComponent::class)
- interface ForegroundServiceEntryPoint {
- fun settingsManager(): SettingsManager
- }
-
- /**
- * Whether the app is currently exempted from battery optimization.
- * @return true if battery optimization is not applied to the current app; false if battery optimization is applied
- */
- private fun batteryOptimizationWhitelisted(context: Context) =
- context.getSystemService()!!.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID)
-
- /**
- * Whether the foreground service is enabled (checked) in the app settings.
- *
- * @return true: foreground service enabled; false: foreground service not enabled
- */
- private fun shouldBeActive(context: Context): Boolean {
- val settingsManager = EntryPointAccessors.fromApplication(context, ForegroundServiceEntryPoint::class.java).settingsManager()
- return settingsManager.getBooleanOrNull(Settings.FOREGROUND_SERVICE) == true
- }
-
- /**
- * Starts the foreground service when enabled in the app settings and applicable.
- * Stops a potentially running foreground service when disabled in the app settings.
- */
- fun startOrStop(context: Context) {
- val foregroundServiceIntent = Intent(Intent.ACTION_DEFAULT, null, context, ForegroundService::class.java)
- if (shouldBeActive(context)) {
- if (batteryOptimizationWhitelisted(context)) {
- if (Build.VERSION.SDK_INT >= 26)
- // After the next call, we have 5 seconds to call startForeground()
- // [https://developer.android.com/about/versions/oreo/android-8.0-changes.html#back-all]
- context.startForegroundService(foregroundServiceIntent)
- else
- context.startService(foregroundServiceIntent)
- } else
- notifyBatteryOptimization(context)
- } else
- try {
- context.stopService(foregroundServiceIntent)
- } catch (ignored: Exception) { }
- }
-
- private fun notifyBatteryOptimization(context: Context) {
- val settingsIntent = Intent(context, AppSettingsActivity::class.java).apply {
- putExtra(AppSettingsActivity.EXTRA_SCROLL_TO, Settings.BATTERY_OPTIMIZATION)
- }
- val pendingSettingsIntent = PendingIntent.getActivity(context, 0, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
- val builder =
- NotificationCompat.Builder(context, NotificationUtils.CHANNEL_DEBUG)
- .setSmallIcon(R.drawable.ic_warning_notify)
- .setContentTitle(context.getString(R.string.battery_optimization_notify_title))
- .setContentText(context.getString(R.string.battery_optimization_notify_text))
- .setContentIntent(pendingSettingsIntent)
- .setCategory(NotificationCompat.CATEGORY_ERROR)
-
- val nm = NotificationManagerCompat.from(context)
- nm.notifyIfPossible(NotificationUtils.NOTIFY_BATTERY_OPTIMIZATION, builder.build())
- }
- }
-
-
- override fun onCreate() {
- super.onCreate()
-
- val settingsIntent = Intent(this, AppSettingsActivity::class.java).apply {
- putExtra(AppSettingsActivity.EXTRA_SCROLL_TO, Settings.FOREGROUND_SERVICE)
- }
- val builder = NotificationCompat.Builder(this, NotificationUtils.CHANNEL_STATUS)
- .setSmallIcon(R.drawable.ic_foreground_notify)
- .setContentTitle(getString(R.string.foreground_service_notify_title))
- .setContentText(getString(R.string.foreground_service_notify_text))
- .setStyle(NotificationCompat.BigTextStyle())
- .setContentIntent(PendingIntent.getActivity(this, 0, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
- .setCategory(NotificationCompat.CATEGORY_STATUS)
- ServiceCompat.startForeground(this, NotificationUtils.NOTIFY_FOREGROUND, builder.build(), FOREGROUND_SERVICE_TYPE_DATA_SYNC)
- }
-
- override fun onBind(intent: Intent?): Nothing? = null
-
- override fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_STICKY
-
-}
\ No newline at end of file
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/RefreshCollectionsWorker.kt b/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/RefreshCollectionsWorker.kt
index 2077cc06..2a970bcd 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/RefreshCollectionsWorker.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/servicedetection/RefreshCollectionsWorker.kt
@@ -238,6 +238,9 @@ class RefreshCollectionsWorker @AssistedInject constructor(
return Result.success()
}
+ /**
+ * Used by WorkManager to show a foreground service notification for expedited jobs on Android <12.
+ */
override suspend fun getForegroundInfo(): ForegroundInfo {
val notification = NotificationUtils.newBuilder(applicationContext, NotificationUtils.CHANNEL_STATUS)
.setSmallIcon(R.drawable.ic_foreground_notify)
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt b/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt
index cbdfa2c6..c9461166 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt
@@ -9,7 +9,6 @@ import androidx.appcompat.app.AppCompatDelegate
object Settings {
const val BATTERY_OPTIMIZATION = "battery_optimization"
- const val FOREGROUND_SERVICE = "foreground_service"
const val DISTRUST_SYSTEM_CERTIFICATES = "distrust_system_certs"
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncWorker.kt b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncWorker.kt
index 7bb186ed..48ab609c 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncWorker.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/syncadapter/SyncWorker.kt
@@ -426,6 +426,9 @@ class SyncWorker @AssistedInject constructor(
return@withContext Result.success()
}
+ /**
+ * Used by WorkManager to show a foreground service notification for expedited jobs on Android <12.
+ */
override suspend fun getForegroundInfo(): ForegroundInfo {
val notification = NotificationUtils.newBuilder(applicationContext, NotificationUtils.CHANNEL_STATUS)
.setSmallIcon(R.drawable.ic_foreground_notify)
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt
index 70d60544..705fa0fb 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsActivity.kt
@@ -23,7 +23,6 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import at.bitfire.cert4android.CustomCertStore
import at.bitfire.davdroid.BuildConfig
-import at.bitfire.davdroid.ForegroundService
import at.bitfire.davdroid.R
import at.bitfire.davdroid.resource.TaskUtils
import at.bitfire.davdroid.settings.Settings
@@ -167,16 +166,6 @@ class AppSettingsActivity: AppCompatActivity() {
}
}
- findPreference(Settings.FOREGROUND_SERVICE)!!.apply {
- isChecked = settings.getBooleanOrNull(Settings.FOREGROUND_SERVICE) == true
- isEnabled = settings.getBooleanOrNull(Settings.BATTERY_OPTIMIZATION) == true
- onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
- settings.putBoolean(Settings.FOREGROUND_SERVICE, newValue as Boolean)
- ForegroundService.startOrStop(requireActivity())
- false
- }
- }
-
// connection settings
val proxyType = settings.getInt(Settings.PROXY_TYPE)
findPreference(Settings.PROXY_TYPE)!!.apply {
diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt
index e41544d5..940b8b4c 100644
--- a/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt
+++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/NotificationUtils.kt
@@ -24,13 +24,10 @@ object NotificationUtils {
// notification IDs
const val NOTIFY_VERBOSE_LOGGING = 1
const val NOTIFY_REFRESH_COLLECTIONS = 2
- const val NOTIFY_FOREGROUND = 3
const val NOTIFY_DATABASE_CORRUPTED = 4
- const val NOTIFY_BATTERY_OPTIMIZATION = 5
const val NOTIFY_SYNC_ERROR = 10
const val NOTIFY_INVALID_RESOURCE = 11
const val NOTIFY_WEBDAV_ACCESS = 12
- // const val NOTIFY_LOW_STORAGE = 13
const val NOTIFY_SYNC_EXPEDITED = 14
const val NOTIFY_TASKS_PROVIDER_TOO_OLD = 20
const val NOTIFY_PERMISSIONS = 21
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dbd6e5c5..f9b0e971 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -158,11 +158,7 @@
Service detection failed
Couldn\'t refresh collection list
-
- Can not run in foreground
- Battery optimization whitelisting required
-
-
+
Running in foreground
On some devices, this is necessary for automatic synchronization.
@@ -177,8 +173,6 @@
Battery optimization
App is whitelisted (recommended)
App is not whitelisted (not recommended)
- Keep in foreground
- May help if your device prevents automatic synchronization
Connection
Proxy type
diff --git a/app/src/main/res/xml/settings_app.xml b/app/src/main/res/xml/settings_app.xml
index 275a0628..97acad11 100644
--- a/app/src/main/res/xml/settings_app.xml
+++ b/app/src/main/res/xml/settings_app.xml
@@ -26,11 +26,6 @@
android:summaryOn="@string/app_settings_battery_optimization_whitelisted"
android:summaryOff="@string/app_settings_battery_optimization_not_whitelisted"/>
-
-