Repository navigation
Open
Description
When I start the application, the ‘onRepeatEvent’ is correctly triggered, updating the push notification every 5 seconds.
However, after the app has been in the background for several hours on Android, if all notifications on the device are cleared, it seems that the event is no longer triggered.
The app is still running, as launching it does not show the Splash screen.
What could be the reason why the ‘onRepeatEvent’ method stops being triggered?
Below is an example implementation following the documentation.
flutter doctor -v
[✓] Flutter (Channel stable, 3.32.5, on macOS 15.5 24F74 darwin-arm64, locale es-ES) [548ms]
• Flutter version 3.32.5 on channel stable at /Volumes/data/development/flutter/sdk/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision fcf2c11572 (8 days ago), 2025-06-24 11:44:07 -0700
• Engine revision dd93de6fb1
• Dart version 3.8.1
• DevTools version 2.45.1
[✓] Android toolchain - develop for Android devices (Android SDK version 36.0.0) [1.460ms]
• Android SDK at /Volumes/data/development/android/sdk
• Platform android-36, build-tools 36.0.0
• ANDROID_HOME = /Volumes/data/development/android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 16.3) [967ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16E140
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [10ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 2025.1) [9ms]
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13391695-b895.109)
[✓] VS Code (version 1.101.1) [8ms]
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.112.0
[✓] VS Code (version 1.82.2) [8ms]
• VS Code at /Users/thorito/Documents/Curso Android Lollipop/Visual Studio Code.app/Contents
• Flutter extension version 3.112.0
[✓] Connected device (3 available) [6,1s]
• iPhone de Apple Team (wireless) (mobile) • 00008020-00097C623AF3002E • ios • iOS 18.5 22F76
• macOS (desktop) • macos • darwin-arm64 • macOS 15.5 24F74 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 137.0.7151.122
[✓] Network resources [224ms]
• All expected network resources are available.
• No issues found!
main.dart
// code ...
FlutterForegroundTask.initCommunicationPort();
runApp(App());
background_handler.dart
@pragma('vm:entry-point')
void startCallback() {
FlutterForegroundTask.setTaskHandler(BackgroundHandler());
}
class BackgroundHandler extends TaskHandler {
final _translationService = _getTranslations();
static Map<String, String> _getTranslations() {
final language = UserPreferences.getDefaultLanguage();
return getTranslationService(language: language);
}
@override
Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
final time = DateHelper.getTime(timestamp.millisecondsSinceEpoch);
log('onStart(time: $time, starter: ${starter.name})');
_updateNotification();
}
@override
void onRepeatEvent(DateTime timestamp) {
final time = DateHelper.getTime(timestamp.millisecondsSinceEpoch);
log('onRepeatEvent(time: $time)');
_updateNotification();
// code ...
}
@override
Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {
final time = DateHelper.getTime(timestamp.millisecondsSinceEpoch);
log('onDestroy(time: $time, isTimeout: $isTimeout)');
}
@override
void onReceiveData(Object data) {
log('onReceiveData(data: $data)');
}
@override
void onNotificationButtonPressed(String id) {
log('onNotificationButtonPressed(id: $id)');
}
@override
void onNotificationPressed() {
log('onNotificationPressed()');
}
@override
void onNotificationDismissed() {
log('onNotificationDismissed()');
}
Future<void> _updateNotification() async {
await FlutterForegroundTask.updateService(
notificationTitle: _translationService['service_title'] ?? '',
notificationText: _translationService['service_description'] ?? '',
);
}
}
background_service.dart
class BackgroundService {
static final _translationService = getTranslations();
static bool _hasLocation = false;
static Map<String, String> getTranslations() {
final language = UserPreferences.getDefaultLanguage();
return getTranslationService(language: language);
}
static Future<bool> isRunningBackgroundService() async {
final isRunning = await FlutterForegroundTask.isRunningService;
return isRunning;
}
static Future<void> requestBackgroundPermissions() async {
final NotificationPermission notificationPermission =
await FlutterForegroundTask.checkNotificationPermission();
if (notificationPermission != NotificationPermission.granted) {
await FlutterForegroundTask.requestNotificationPermission();
}
if (isAndroid) {
if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) {
await FlutterForegroundTask.requestIgnoreBatteryOptimization();
}
if (!await FlutterForegroundTask.canScheduleExactAlarms) {
await FlutterForegroundTask.openAlarmsAndRemindersSettings();
}
}
}
static Future<void> initService() async {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: BACKGROUND_SERVICE_CHANNEL_ID,
channelName: _translationService['service_channel_name'] ?? '',
channelDescription: _translationService['service_channel_description'],
onlyAlertOnce: true,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(5000),
autoRunOnBoot: true,
autoRunOnMyPackageReplaced: true,
allowWifiLock: true,
allowWakeLock: true,
),
);
}
static Future<ServiceRequestResult> startBackgroundService({
required bool hasLocation,
}) async {
_hasLocation = hasLocation;
if (await FlutterForegroundTask.isRunningService) {
return FlutterForegroundTask.restartService();
} else {
final serviceTypes = [
ForegroundServiceTypes.dataSync,
ForegroundServiceTypes.remoteMessaging,
];
if (_hasLocation) {
serviceTypes.add(ForegroundServiceTypes.location);
}
return FlutterForegroundTask.startService(
serviceId: BACKGROUND_SERVICE_NOTIFICATION_ID,
notificationTitle: _translationService['service_title'] ?? '',
notificationText: _translationService['service_description'] ?? '',
serviceTypes: serviceTypes,
notificationInitialRoute: '/',
callback: startCallback,
);
}
}
static Future<ServiceRequestResult> stopBackgroundService() async {
// code ...
return FlutterForegroundTask.stopService();
}
}
I would appreciate it if you could let me know the reason why it is not doing it.
Thank you very much. 😃
Metadata
Metadata
Assignees
Labels
No labels
Activity
YarosMallorca commentedon Jul 6, 2025
dataSync service has a timeout of 6 hours. Android will terminate the service if it been running for longer than that.
thorito commentedon Jul 6, 2025
A question: If I request the location every 5 hours, would it be valid?
Is there a way to keep it running without having to bring the app to the foreground?
YarosMallorca commentedon Jul 6, 2025
I haven't messed with this, so I can't say for sure, but I don't think so. What exactly are you trying to achieve in your foreground task? Usually, they're meant for small, user-actioned tasks that don't last more than 30 minutes to an hour. Anything else should be a background process, ideally implemented in native code, but there is also a flutter package for background tasks if you prefer that.
Documented here
thorito commentedon Jul 7, 2025
I need to keep my app running so the operating system doesn't shut it down.
It must stay active even if I close the app or the user tries to remove it from the recent apps list.Every 30 seconds, it needs to send a "ping" to our server.
I tried another library, flutter_background_service, but it didn't work well on iOS (it would close after some time).
I'm thinking about using the workmanager library, but I'm not sure if a foreground service would be better to let the user know the app is still running in the background.
The main reasons are:
I would appreciate any help or suggestions.
Thanks a lot!
YarosMallorca commentedon Jul 7, 2025
Could you please explain what exactly you're trying to achieve? That seems super inefficient doing a network request every 30 seconds. Android is very aggressive when it comes to this kind of behavior.
RutvikCimcon commentedon Jul 27, 2025
The same issue occurs - it's not related to the Android 15 six-hour time limit. My service stops after running for 30 minutes on some devices, particularly on Vivo and sometimes on Samsung devices as well