fix(notifications): handle FGS-not-allowed exception from background
AlwaysOnNotificationServiceManager calls NotificationRelayService.start() from a flow collector that can fire during cold-start (before the activity reaches foreground), where Android 12+ blocks startForegroundService() with ForegroundServiceStartNotAllowedException. The exception was already caught but logged as an error. - Distinguish ForegroundServiceStartNotAllowedException from real failures and log it at WARN — the other layers (boot receiver, watchdog alarm, catch-up worker) retry from contexts that have FGS exemption. - Retry the start in MainActivity.onResume() so the service comes up as soon as the user opens the app.
This commit is contained in:
+13
@@ -89,9 +89,22 @@ class NotificationRelayService : Service() {
|
||||
try {
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
} catch (e: Exception) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
||||
e is ForegroundServiceStartNotAllowedException
|
||||
) {
|
||||
// Android 12+ blocks startForegroundService() from the background unless
|
||||
// the caller has a temporary FGS exemption (e.g. broadcast receiver,
|
||||
// exact alarm, high-priority FCM). Cold-start triggered by a flow emission
|
||||
// from AlwaysOnNotificationServiceManager hits this path. The other
|
||||
// notification layers (BootCompletedReceiver, ServiceWatchdogManager,
|
||||
// NotificationCatchUpWorker) plus MainActivity.onResume retry from
|
||||
// contexts that are allowed.
|
||||
Log.w(TAG) { "Foreground service start not allowed from background; will retry from another layer" }
|
||||
} else {
|
||||
Log.e(TAG, "Failed to start foreground service", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
context.stopService(Intent(context, NotificationRelayService::class.java))
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.debugState
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.service.lang.LanguageTranslatorService
|
||||
import com.vitorpamplona.amethyst.service.notifications.NotificationRelayService
|
||||
import com.vitorpamplona.amethyst.service.playback.composable.DEFAULT_MUTED_SETTING
|
||||
import com.vitorpamplona.amethyst.service.playback.pip.BackgroundMedia
|
||||
import com.vitorpamplona.amethyst.ui.navigation.findParameterValue
|
||||
@@ -89,6 +90,13 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
// starts muted every time
|
||||
DEFAULT_MUTED_SETTING.value = true
|
||||
|
||||
// If always-on notifications are enabled but the foreground service couldn't be
|
||||
// started from the background during cold-start (Android 12+ restriction), retry
|
||||
// now that the activity is in the foreground.
|
||||
if (NotificationRelayService.isEnabled(this)) {
|
||||
NotificationRelayService.start(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
||||
Reference in New Issue
Block a user