From e1d85f19a1c1fbfeb003b89a04e037efc525e06c Mon Sep 17 00:00:00 2001 From: Konstantin Pastbin Date: Sun, 20 Jul 2025 15:58:31 +0700 Subject: [PATCH] [android] Handle exceptions when starting foreground services Signed-off-by: Konstantin Pastbin --- .../downloader/DownloaderService.java | 23 ++++++++++++++---- .../location/TrackRecordingService.java | 24 +++++++++++++++---- .../routing/NavigationService.java | 24 +++++++++++++++---- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/java/app/organicmaps/downloader/DownloaderService.java b/android/app/src/main/java/app/organicmaps/downloader/DownloaderService.java index e85f01f36..225ae9411 100644 --- a/android/app/src/main/java/app/organicmaps/downloader/DownloaderService.java +++ b/android/app/src/main/java/app/organicmaps/downloader/DownloaderService.java @@ -3,6 +3,7 @@ package app.organicmaps.downloader; import static android.Manifest.permission.POST_NOTIFICATIONS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import android.app.ForegroundServiceStartNotAllowedException; import android.app.Service; import android.content.Intent; import android.content.pm.ServiceInfo; @@ -42,10 +43,24 @@ public class DownloaderService extends Service implements MapManager.StorageCall var notification = mNotifier.buildProgressNotification(); Logger.i(TAG, "Starting Downloader Foreground Service"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - ServiceCompat.startForeground(this, DownloaderNotifier.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC); - else - ServiceCompat.startForeground(this, DownloaderNotifier.NOTIFICATION_ID, notification, 0); + try + { + int type = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + type = ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC; + ServiceCompat.startForeground(this, DownloaderNotifier.NOTIFICATION_ID, notification, type); + } + catch (Exception e) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + e instanceof ForegroundServiceStartNotAllowedException) + { + // App not in a valid state to start foreground service (e.g started from bg) + Logger.e(TAG, "Not in a valid state to start foreground service", e); + } + else + Logger.e(TAG, "Failed to promote the service to foreground", e); + } return START_NOT_STICKY; } diff --git a/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java b/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java index ef9f496bb..dc2d564db 100644 --- a/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java +++ b/android/app/src/main/java/app/organicmaps/location/TrackRecordingService.java @@ -1,5 +1,6 @@ package app.organicmaps.location; +import android.app.ForegroundServiceStartNotAllowedException; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -160,10 +161,25 @@ public class TrackRecordingService extends Service implements LocationListener } Logger.i(TAG, "Starting Track Recording Foreground service"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - ServiceCompat.startForeground(this, TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); - else - ServiceCompat.startForeground(this, TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build(), 0); + + try + { + int type = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + type = ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; + ServiceCompat.startForeground(this, TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build(), type); + } + catch (Exception e) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + e instanceof ForegroundServiceStartNotAllowedException) + { + // App not in a valid state to start foreground service (e.g started from bg) + Logger.e(TAG, "Not in a valid state to start foreground service", e); + } + else + Logger.e(TAG, "Failed to promote the service to foreground", e); + } final LocationHelper locationHelper = LocationHelper.from(this); diff --git a/android/app/src/main/java/app/organicmaps/routing/NavigationService.java b/android/app/src/main/java/app/organicmaps/routing/NavigationService.java index ac92486f9..4bec7926d 100644 --- a/android/app/src/main/java/app/organicmaps/routing/NavigationService.java +++ b/android/app/src/main/java/app/organicmaps/routing/NavigationService.java @@ -7,6 +7,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static app.organicmaps.util.Constants.Vendor.XIAOMI; import android.annotation.SuppressLint; +import android.app.ForegroundServiceStartNotAllowedException; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; @@ -226,10 +227,25 @@ public class NavigationService extends Service implements LocationListener } Logger.i(TAG, "Starting Navigation Foreground service"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) - ServiceCompat.startForeground(this, NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION); - else - ServiceCompat.startForeground(this, NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build(), 0); + + try + { + int type = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) + type = ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION; + ServiceCompat.startForeground(this, NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build(), type); + } + catch (Exception e) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + e instanceof ForegroundServiceStartNotAllowedException) + { + // App not in a valid state to start foreground service (e.g started from bg) + Logger.e(TAG, "Not in a valid state to start foreground service", e); + } + else + Logger.e(TAG, "Failed to promote the service to foreground", e); + } final LocationHelper locationHelper = LocationHelper.from(this);