Nag F-Droid users on recent Android versions to setup UnifiedPush

Android > 15 keeps killing the background sync service

Change-Id: If33b96ae8aee1f999023b8a3866b69ed7ed636eb
This commit is contained in:
SpiritCroc 2025-10-26 16:07:32 +01:00
parent d72fa85bad
commit ffec9057ab
5 changed files with 56 additions and 5 deletions

View File

@ -247,4 +247,9 @@
<string name="notification_foreground_service_failed_title">Failed to start foreground service</string> <string name="notification_foreground_service_failed_title">Failed to start foreground service</string>
<string name="notification_foreground_service_failed_summary">You may need to exempt SchildiChat from battery restrictions in your system settings.</string> <string name="notification_foreground_service_failed_summary">You may need to exempt SchildiChat from battery restrictions in your system settings.</string>
<string name="prompt_unified_push_title">Background sync is enabled</string>
<string name="prompt_unified_push_description">You\'re using the background sync service to receive notifications. This approach does not work reliably and causes crashes on recent Android versions. Please consider setting up UnifiedPush instead.</string>
<string name="recommend_unified_push_title">UnifiedPush recommended</string>
<string name="recommend_unified_push_description">Background sync service does not work reliably and causes crashes on recent Android versions. Please use UnifiedPush or install a SchildiChat variant that supports FCM if you have Google Play Services installed.</string>
</resources> </resources>

View File

@ -11,6 +11,7 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.view.Menu import android.view.Menu
@ -38,10 +39,8 @@ import im.vector.app.core.extensions.validateBackPressed
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorMenuProvider import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.pushers.UnifiedPushHelper
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.core.utils.startSharePlainTextIntent
import im.vector.app.core.utils.toast
import im.vector.app.databinding.ActivityHomeBinding import im.vector.app.databinding.ActivityHomeBinding
import im.vector.app.features.MainActivity import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs import im.vector.app.features.MainActivityArgs
@ -62,6 +61,9 @@ import im.vector.app.features.permalink.NavigationInterceptor
import im.vector.app.features.permalink.PermalinkHandler import im.vector.app.features.permalink.PermalinkHandler
import im.vector.app.features.permalink.PermalinkHandler.Companion.MATRIX_TO_CUSTOM_SCHEME_URL_BASE import im.vector.app.features.permalink.PermalinkHandler.Companion.MATRIX_TO_CUSTOM_SCHEME_URL_BASE
import im.vector.app.features.permalink.PermalinkHandler.Companion.ROOM_LINK_PREFIX import im.vector.app.features.permalink.PermalinkHandler.Companion.ROOM_LINK_PREFIX
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_MATRIX_TO_CUSTOM_SCHEME_URL_BASE
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_ROOM_LINK_PREFIX
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_USER_LINK_PREFIX
import im.vector.app.features.permalink.PermalinkHandler.Companion.USER_LINK_PREFIX import im.vector.app.features.permalink.PermalinkHandler.Companion.USER_LINK_PREFIX
import im.vector.app.features.popup.DefaultVectorAlert import im.vector.app.features.popup.DefaultVectorAlert
import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.PopupAlertManager
@ -78,9 +80,6 @@ import im.vector.app.features.spaces.share.ShareSpaceBottomSheet
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.usercode.UserCodeActivity import im.vector.app.features.usercode.UserCodeActivity
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_MATRIX_TO_CUSTOM_SCHEME_URL_BASE
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_ROOM_LINK_PREFIX
import im.vector.app.features.permalink.PermalinkHandler.Companion.SC_USER_LINK_PREFIX
import im.vector.lib.core.utils.compat.getParcelableExtraCompat import im.vector.lib.core.utils.compat.getParcelableExtraCompat
import im.vector.lib.strings.CommonStrings import im.vector.lib.strings.CommonStrings
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -139,6 +138,7 @@ class HomeActivity :
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager @Inject lateinit var notificationPermissionManager: NotificationPermissionManager
private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed private var isNewAppLayoutEnabled: Boolean = false // delete once old app layout is removed
private var hasComplainedAboutBackgroundSync = false
private val createSpaceResultLauncher = registerStartForActivityResult { activityResult -> private val createSpaceResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) { if (activityResult.resultCode == Activity.RESULT_OK) {
@ -442,6 +442,15 @@ class HomeActivity :
else -> { else -> {
// Idle or Incremental sync status // Idle or Incremental sync status
views.waitingView.root.isVisible = false views.waitingView.root.isVisible = false
// Android 15 is very strict with background sync service usage and likes to shoot us when we take too long, making the app crash.
// Complain first time when starting the app after initial sync is done
if (status !is SyncRequestState.InitialSyncRequestState) {
if (!hasComplainedAboutBackgroundSync && Build.VERSION.SDK_INT > 35 && buildMeta.flavorDescription == "FDroid" && vectorPreferences.isBackgroundSyncEnabled()) {
hasComplainedAboutBackgroundSync = true
promptNeedsPushEvent()
}
}
} }
} }
} }
@ -575,6 +584,25 @@ class HomeActivity :
) )
} }
private fun promptNeedsPushEvent() {
popupAlertManager.postVectorAlert(
DefaultVectorAlert(
uid = PopupAlertManager.SC_REQUIRES_PUSH_UID,
title = getString(im.vector.lib.strings.R.string.prompt_unified_push_title),
description = getString(im.vector.lib.strings.R.string.prompt_unified_push_description),
iconId = null,
).apply {
colorInt = ThemeUtils.getColor(this@HomeActivity, com.google.android.material.R.attr.colorPrimary)
contentAction = Runnable {
(weakCurrentActivity?.get() as? VectorBaseActivity<*>)?.let {
it.navigator.openSettings(it, VectorSettingsActivity.EXTRA_DIRECT_ACCESS_NOTIFICATIONS)
}
}
dismissedAction = Runnable {}
}
)
}
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent) super.onNewIntent(intent)
val parcelableExtra = intent.getParcelableExtraCompat<HomeActivityArgs>(Mavericks.KEY_ARG) val parcelableExtra = intent.getParcelableExtraCompat<HomeActivityArgs>(Mavericks.KEY_ARG)

View File

@ -52,6 +52,7 @@ class PopupAlertManager @Inject constructor(
const val UPGRADE_SECURITY_UID = "upgrade_security" const val UPGRADE_SECURITY_UID = "upgrade_security"
const val VERIFY_SESSION_UID = "verify_session" const val VERIFY_SESSION_UID = "verify_session"
const val ENABLE_PUSH_UID = "enable_push" const val ENABLE_PUSH_UID = "enable_push"
const val SC_REQUIRES_PUSH_UID = "sc_requires_push"
} }
private var weakCurrentActivity: WeakReference<Activity>? = null private var weakCurrentActivity: WeakReference<Activity>? = null

View File

@ -12,11 +12,13 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.RingtoneManager import android.media.RingtoneManager
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.core.net.toUri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -36,6 +38,7 @@ import im.vector.app.core.pushers.EnsureFcmTokenIsRetrievedUseCase
import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.FcmHelper
import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.pushers.UnifiedPushHelper
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.services.GuardServiceStarter import im.vector.app.core.services.GuardServiceStarter
import im.vector.app.core.utils.combineLatest import im.vector.app.core.utils.combineLatest
import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.isIgnoringBatteryOptimizations
@ -79,6 +82,7 @@ class VectorSettingsNotificationFragment :
@Inject lateinit var vectorFeatures: VectorFeatures @Inject lateinit var vectorFeatures: VectorFeatures
@Inject lateinit var notificationPermissionManager: NotificationPermissionManager @Inject lateinit var notificationPermissionManager: NotificationPermissionManager
@Inject lateinit var ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase @Inject lateinit var ensureFcmTokenIsRetrievedUseCase: EnsureFcmTokenIsRetrievedUseCase
@Inject lateinit var buildMeta: BuildMeta
override var titleRes: Int = CommonStrings.settings_notifications override var titleRes: Int = CommonStrings.settings_notifications
override val preferenceXmlRes = R.xml.vector_settings_notifications override val preferenceXmlRes = R.xml.vector_settings_notifications
@ -148,6 +152,14 @@ class VectorSettingsNotificationFragment :
} }
// SC addition // SC addition
findPreference<Preference>("SC_SETTINGS_PROMPT_UNIFIED_PUSH_TITLE")?.let {
it.isVisible = Build.VERSION.SDK_INT > 35 && buildMeta.flavorDescription == "FDroid"
it.onPreferenceClickListener = Preference.OnPreferenceClickListener {
startActivity(Intent(Intent.ACTION_VIEW, "https://unifiedpush.org/".toUri()))
true
}
}
findPreference<SwitchPreference>(VectorPreferences.SETTINGS_FORCE_ALLOW_BACKGROUND_SYNC)?.let { findPreference<SwitchPreference>(VectorPreferences.SETTINGS_FORCE_ALLOW_BACKGROUND_SYNC)?.let {
it.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked -> it.setTransactionalSwitchChangeListener(lifecycleScope) { isChecked ->
if (isChecked) { if (isChecked) {

View File

@ -2,6 +2,11 @@
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
android:key="SC_SETTINGS_PROMPT_UNIFIED_PUSH_TITLE"
android:title="@string/recommend_unified_push_title"
android:summary="@string/recommend_unified_push_description" />
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_notifications"> <im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/settings_notifications">
<im.vector.app.core.preference.VectorSwitchPreference <im.vector.app.core.preference.VectorSwitchPreference