flutter_lifecycle_guard

Reliable background execution for Flutter apps that need tasks to survive real device behavior, including OEM battery restrictions.

flutter_lifecycle_guard routes work to the right strategy at runtime:

  • directIsolate when app is foregrounded
  • Android foreground service for immediate background work
  • Android WorkManager for deferrable work
  • iOS BG processing/refresh pathways

Release Status

Current line: 1.0.0-dev.1
This is a developer preview and not marked stable yet.

Why This Package

Most packages expose platform primitives and leave strategy choices to you. This package includes a routing policy layer so your app asks for work intent (immediate vs deferrable) and the plugin decides execution strategy.

Features

  • Runtime routing for immediate and deferrable tasks
  • Unified API across Android and iOS
  • Foreground-service support for immediate Android background work
  • WorkManager scheduling for deferrable Android work
  • Heartbeat API for periodic background maintenance
  • Status stream (enqueued, running, completed, failed, etc.)
  • OEM guidance helper for aggressive battery saver devices
  • Optional automatic permission orchestration
  • Detailed logs for route decisions and lifecycle transitions

Installation

dependencies:
  flutter_lifecycle_guard: ^1.0.0-dev.1

Platform Setup

Android

The plugin contributes required components via manifest merge.
Your app should still declare permissions relevant to your use case.

Common permissions:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

If you use specific foreground service types (Android 12+), declare matching type permissions in the app manifest, for example:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />

If you rely on exact alarms, also declare:

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />

iOS

Add required background modes and permitted task identifiers in ios/Runner/Info.plist:

<key>UIBackgroundModes</key>
<array>
  <string>fetch</string>
  <string>processing</string>
</array>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
  <string>sync_heartbeat</string>
  <string>data_processing_task</string>
</array>

Quick Start

1. Define top-level callbacks

import 'package:flutter_lifecycle_guard/flutter_lifecycle_guard.dart';

@pragma('vm:entry-point')
Future<void> uploadTask(ProgressCallback updateProgress) async {
  updateProgress(0.2);
  await Future<void>.delayed(const Duration(seconds: 1));
  updateProgress(1.0);
}

@pragma('vm:entry-point')
Future<void> heartbeatTask() async {
  // lightweight periodic work
}

2. Initialize once

await LifecycleGuard.initialize(
  config: const LifecycleGuardConfig(
    androidNotificationChannelId: 'bg_tasks',
    androidNotificationChannelName: 'Background Tasks',
    enableOemGuidance: true,
    autoRequestPermissions: true,
    enableDetailedLogging: true,
  ),
);

3. Execute an immediate task

final handle = await LifecycleGuard.instance.execute(
  TaskDescriptor(
    id: 'upload_now',
    urgency: TaskUrgency.immediate,
    work: uploadTask,
    serviceType: ForegroundServiceType.dataSync,
    notification: const TaskNotification(
      title: 'Uploading',
      body: 'Running in background',
    ),
  ),
);

handle.statusStream.listen((status) {
  // state, strategy, progress, message
  // e.g. TaskState.running via ExecutionStrategy.androidForegroundService
});

4. Execute a deferrable task

await LifecycleGuard.instance.execute(
  TaskDescriptor(
    id: 'sync_later',
    urgency: TaskUrgency.deferrable,
    work: uploadTask,
    constraints: const TaskConstraints(requiresNetwork: true),
  ),
);

5. Schedule heartbeat

await LifecycleGuard.instance.scheduleHeartbeat(
  HeartbeatConfig(
    id: 'sync_heartbeat',
    interval: const Duration(minutes: 15),
    work: heartbeatTask,
    constraints: const TaskConstraints(requiresNetwork: true),
  ),
);

OEM Battery Optimization Helper

final opened = await LifecycleGuard.instance.showBatteryOptimizationSettings();

This attempts OEM-specific settings pages first, then falls back to standard battery settings.

Callback Rules

  • Background callbacks must be top-level or static functions.
  • Use @pragma('vm:entry-point') on background callbacks.
  • Keep heartbeat callbacks short and idempotent.

Operational Notes

  • Android periodic work has a minimum 15-minute interval.
  • iOS background scheduling is opportunistic, not exact.
  • OEM settings pages vary by model/ROM; fallback behavior is expected.
  • Swiping away or force-stopping apps can still affect scheduling on some OEMs.

Verifying Behavior

  • Enable enableDetailedLogging: true.
  • Run on at least:
    • Stock Android emulator
    • One aggressive OEM device (OPPO/Xiaomi/Realme/etc.)
  • Validate for both:
    • Immediate background task
    • Deferrable task
  • Confirm terminal statuses in statusStream (completed/failed).

API Surface

Main classes:

  • LifecycleGuard
  • LifecycleGuardConfig
  • TaskDescriptor
  • HeartbeatConfig
  • GuardTaskHandle
  • GuardStatus

Support

Buy Me a Coffee: https://buymeacoffee.com/sanaullah49

License

See LICENSE.

Libraries

flutter_lifecycle_guard
Reliable background execution for Flutter.