diff --git a/library/ui-strings/src/main/res/values/strings_sc.xml b/library/ui-strings/src/main/res/values/strings_sc.xml
index 148d267d8c..e6ef61aa06 100644
--- a/library/ui-strings/src/main/res/values/strings_sc.xml
+++ b/library/ui-strings/src/main/res/values/strings_sc.xml
@@ -241,4 +241,10 @@
⚠️ This setting by default (unless overridden by your homeserver\'s configuration) enables access to \"scalar\", Element\'s integration manager which is unfortunately proprietary, i.e. its source code is not open and can not be checked by the public or the SchildiChat developers.
+ Application errors
+ Cannot sync notifications
+ Consider setting up UnifiedPush and disabling battery restrictions for SchildiChat in your system settings.
+ Failed to start foreground service
+ You may need to exempt SchildiChat from battery restrictions in your system settings.
+
diff --git a/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt b/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt
index 3d5cb4bdb4..1f25d2d153 100644
--- a/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt
+++ b/vector-app/src/fdroid/java/im/vector/app/fdroid/service/GuardAndroidService.kt
@@ -8,6 +8,7 @@ package im.vector.app.fdroid.service
import android.content.Intent
import dagger.hilt.android.AndroidEntryPoint
+import im.vector.app.core.extensions.startForegroundCompat
import im.vector.app.core.services.VectorAndroidService
import im.vector.app.features.notifications.NotificationUtils
import im.vector.lib.strings.CommonStrings
@@ -27,7 +28,7 @@ class GuardAndroidService : VectorAndroidService() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notificationSubtitleRes = CommonStrings.notification_listening_for_notifications
val notification = notificationUtils.buildForegroundServiceNotification(notificationSubtitleRes, false)
- startForeground(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification)
+ startForegroundCompat(NotificationUtils.NOTIFICATION_ID_FOREGROUND_SERVICE, notification, errorNotificationTitle = getString(CommonStrings.notification_sync_service_failed_title), errorNotificationSummary = getString(CommonStrings.notification_sync_service_failed_summary))
return START_STICKY
}
}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Service.kt b/vector/src/main/java/im/vector/app/core/extensions/Service.kt
index 2f56b13e1a..7c4efe4f7c 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Service.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Service.kt
@@ -7,12 +7,59 @@
package im.vector.app.core.extensions
+import android.Manifest
+import android.app.ForegroundServiceStartNotAllowedException
import android.app.Notification
import android.app.Service
+import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.os.Build
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import im.vector.app.R
+import im.vector.app.features.notifications.NotificationUtils
+import im.vector.app.features.themes.ThemeUtils
+import im.vector.lib.strings.CommonStrings
+import timber.log.Timber
+/** SC wrapper around [startForegroundCompatUpstream] which catches [ForegroundServiceStartNotAllowedException].
+ * Come on Element, don't you care about these crashes spamming your rageshake inbox from FDroid users?
+ * */
fun Service.startForegroundCompat(
+ id: Int,
+ notification: Notification,
+ provideForegroundServiceType: (() -> Int)? = null,
+ errorNotificationTitle: String = getString(CommonStrings.notification_foreground_service_failed_title),
+ errorNotificationSummary: String = getString(CommonStrings.notification_foreground_service_failed_summary),
+) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ try {
+ startForegroundCompatUpstream(id, notification, provideForegroundServiceType)
+ Timber.tag("SchildiService").d("Started foreground service $id successfully on >= S")
+ } catch (e: ForegroundServiceStartNotAllowedException) {
+ Timber.tag("SchildiService").e(e, "Failed to start foreground service")
+ val notificationManager = NotificationManagerCompat.from(this)
+ val errorNotification = NotificationCompat.Builder(this, NotificationUtils.SC_APP_ERRORS_CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_status_bar_sc)
+ .setContentTitle(errorNotificationTitle)
+ .setContentText(errorNotificationSummary)
+ .setColor(ThemeUtils.getColor(this, android.R.attr.colorPrimary))
+ .setCategory(NotificationCompat.CATEGORY_ERROR)
+ .build()
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
+ Timber.tag("SchildiService").w("Not allowed to notify.")
+ } else {
+ notificationManager.notify("FAILED_FG_SERVICE_TAG", id, errorNotification)
+ }
+ }
+ } else {
+ startForegroundCompatUpstream(id, notification, provideForegroundServiceType)
+ Timber.tag("SchildiService").d("Started foreground service $id successfully on < S")
+ }
+}
+
+fun Service.startForegroundCompatUpstream(
id: Int,
notification: Notification,
provideForegroundServiceType: (() -> Int)? = null
diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt
index 9db264446b..82a2977b36 100755
--- a/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt
+++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationUtils.kt
@@ -101,6 +101,8 @@ class NotificationUtils @Inject constructor(
const val SILENT_NOTIFICATION_CHANNEL_ID = "DEFAULT_SILENT_NOTIFICATION_CHANNEL_ID_V2"
private const val CALL_NOTIFICATION_CHANNEL_ID = "CALL_NOTIFICATION_CHANNEL_ID_V2"
+ const val SC_APP_ERRORS_CHANNEL_ID = "SC_APP_ERRORS_CHANNEL_ID"
+
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
fun supportNotificationChannels() = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
@@ -208,6 +210,20 @@ class NotificationUtils @Inject constructor(
enableLights(true)
lightColor = accentColor
})
+
+ // SC
+ notificationManager.createNotificationChannel(
+ NotificationChannel(
+ SC_APP_ERRORS_CHANNEL_ID,
+ stringProvider.getString(CommonStrings.notification_channel_app_errors).ifEmpty { "Application errors" },
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+ .apply {
+ description = stringProvider.getString(CommonStrings.notification_channel_app_errors)
+ setSound(null, null)
+ enableLights(false)
+ lightColor = accentColor
+ })
}
fun getChannel(channelId: String): NotificationChannel? {