flutter_background_service

repository·master·Indexed 43 days ago

https://github.com/ekasetiawans/flutter_background_service

A Flutter plugin for executing Dart code in background isolates, supporting foreground services with notifications and background modes on Android and iOS. It provides a federated plugin architecture and supports communication between the UI and background isolates via message passing using invoke and on methods.

Tokens
5.3K
Snippets
15
Records
23
Agent score
55%

What's inside flutter_background_service

  1. Run background service when application is closed

    master

    To execute code even when the app is closed (e.g., for real-time data fetching):

    • Foreground Mode (isForegroundMode: true): Displays a notification according to Android policy.
    • Background Mode (isForegroundMode: false): Requires running in release mode and requires disabling battery optimization so the service stays active when the user closes the application.

    Use autoStart: true and autoStartOnBoot: true in AndroidConfiguration to ensure the service persists.

    await service.configure(
      androidConfiguration: AndroidConfiguration(
        autoStart: true,
        onStart: onStart,
        isForegroundMode: false, // Requires disabling battery optimization in release mode
        autoStartOnBoot: true,
      ),
      iosConfiguration: IosConfiguration(
        autoStart: true,
        onForeground: onStart,
        onBackground: onIosBackground,
      ),
    );
  2. Handle iOS background limitations

    master

    iOS does not support long-running background services like Android. The OS will suspend your application shortly after it enters the background.

    To execute code periodically on iOS, use the onBackground method. This relies on the iOS Background Fetch capability, which has the following constraints:

    • Execution interval: Cannot be faster than every 15 minutes.
    • Execution duration: The process is only alive for approximately 15-30 seconds.
  3. Communicate between UI and Background Service

    master

    Because the service runs in a separate Isolate, you cannot share object references between the UI and the Background Service. Instead, use message passing:

    • From UI to Service: Use FlutterBackgroundService.invoke(String method) to send a command.
    • From Service to UI: Use ServiceInstance.invoke(String method) to send data/events.
    • Listening for messages: Use service.on(String method).listen(...) in both isolates to react to incoming messages.

    Note: Always call FlutterBackgroundService.configure() in your main() function to ensure the callback handler is correctly registered.

  4. Configure Foreground Services for Android 14+ (SDK 34)

    master

    If your app targets Android 14 (SDK 34) or higher, you must declare the foreground service type in both the AndroidManifest.xml and the AndroidConfiguration object.

    1. Update AndroidManifest.xml:

      • Add the FOREGROUND_SERVICE permission.
      • Add the specific permission for your service type (e.g., FOREGROUND_SERVICE_LOCATION).
      • Declare the BackgroundService within the <application> tag and specify the android:foregroundServiceType.
    2. Update AndroidConfiguration:

      • Pass the corresponding types to the foregroundServiceTypes list using AndroidForegroundType.

    Warning: You must ensure all required permissions are granted before starting the service, and the types declared in code must match those in the Manifest.

    <!-- android/app/src/main/AndroidManifest.xml -->
    <manifest ...>
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
    
      <application ...>
        <service
            android:name="id.flutter.flutter_background_service.BackgroundService"
            android:foregroundServiceType="location"
        />
      </application>
    </manifest>
    await service.configure(
      androidConfiguration: AndroidConfiguration(
        // ...
        foregroundServiceTypes: [AndroidForegroundType.location],
      ),
    );
  5. Use custom notifications for Foreground Service

    master

    You can use plugins like flutter_local_notifications to create custom notifications (with progress bars, buttons, etc.) for your foreground service.

    To implement this:

    1. Create a notification channel using your preferred notification plugin.
    2. In AndroidConfiguration, set notificationChannelId to match your created channel, and provide foregroundServiceNotificationId.
    3. Inside the onStart method (the background isolate), use the notification plugin to call .show() with the same notificationId to update the notification content dynamically.
    // 1. Setup Channel in main/initialization
    const notificationChannelId = 'my_foreground';
    const notificationId = 888;
    
    final AndroidNotificationChannel channel = AndroidNotificationChannel(
      notificationChannelId,
      'MY FOREGROUND SERVICE',
      importance: Importance.low,
    );
    
    // 2. Configure Service
    await service.configure(
      androidConfiguration: AndroidConfiguration(
        onStart: onStart,
        isForegroundMode: true,
        notificationChannelId: notificationChannelId,
        foregroundServiceNotificationId: notificationId,
      ),
    );
    
    // 3. Update notification in onStart
    Future<void> onStart(ServiceInstance service) async {
      final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    
      Timer.periodic(const Duration(seconds: 1), (timer) async {
        if (service is AndroidServiceInstance) {
          if (await service.isForegroundService()) {
            flutterLocalNotificationsPlugin.show(
              notificationId,
              'COOL SERVICE',
              'Awesome ${DateTime.now()}',
              const NotificationDetails(
                android: AndroidNotificationDetails(
                  notificationChannelId,
                  'MY FOREGROUND SERVICE',
                  icon: 'ic_bg_service_small',
                  ongoing: true,
                ),
              ),
            );
          }
        }
      });
    }
  6. Configure iOS background execution

    master

    To enable background execution on iOS:

    1. Background Fetch: Enable the background_fetch capability in Xcode (optional, required if you want to use IosConfiguration.onBackground).
    2. BGTaskScheduler (iOS 13+): Add the permitted identifiers to ios/Runner/Info.plist:
      <key>BGTaskSchedulerPermittedIdentifiers</key>
      <array>
          <string>dev.flutter.background.refresh</string>
      </array>
    3. Custom Identifier: To use a custom identifier, update ios/Runner/AppDelegate.swift:
      import flutter_background_service_ios
      // ...
      SwiftFlutterBackgroundServicePlugin.taskIdentifier = "your.custom.task.identifier"
    <!-- ios/Runner/Info.plist -->
    <key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>dev.flutter.background.refresh</string>
    </array>
    // ios/Runner/AppDelegate.swift
    import flutter_background_service_ios
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        SwiftFlutterBackgroundServicePlugin.taskIdentifier = "your.custom.task.identifier"
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
  7. Use flutter_background_service on iOS

    master

    The flutter_background_service_ios package is the iOS-specific implementation of the federated plugin flutter_background_service.

    Because this is an endorsed federated plugin, you do not need to add flutter_background_service_ios to your pubspec.yaml manually. Instead, simply add the main package flutter_background_service to your project. The iOS implementation will be automatically included and utilized by the Flutter engine when building for iOS.

    dependencies:
      flutter_background_service: ^0.1.12
  8. Migrate to the latest version of flutter_background_service

    master

    If you are upgrading from an older version, note the following breaking changes:

    • sendData() is now invoke(String method).
    • onDataReceived() is now on(String method).
    • Isolate Separation: You must use the ServiceInstance object provided in the onStart method for background logic. Do not create a new FlutterBackgroundService object inside the background isolate.
    • Usage Rule: Use the FlutterBackgroundService class only in the UI Isolate and the ServiceInstance class only in the Background Isolate.
  9. Implement a new platform for flutter_background_service

    master

    To add support for a new platform (e.g., a new OS or a specific hardware implementation), you must extend the FlutterBackgroundServicePlatform class. Your implementation should handle the platform-specific logic required by the flutter_background_service plugin.

    Once your implementation is ready, you must register it as the active instance by assigning it to FlutterBackgroundServicePlatform.instance during your plugin registration process.

    // 1. Extend the platform interface
    class MyPlatformImplementation extends FlutterBackgroundServicePlatform {
      // Implement required methods here
    }
    
    // 2. Register the implementation
    FlutterBackgroundServicePlatform.instance = MyPlatformImplementation();
  10. Customize the iOS launch screen assets

    master

    To change the image displayed during the app's launch on iOS, you can either replace the image files directly in the ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode to manage the assets.

    To use Xcode:

    1. Open your Flutter project's iOS workspace using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  11. Configure Android Gradle and Kotlin versions

    master

    Ensure your Android project uses the following compatible versions to avoid build issues:

    • Gradle Tools: In android/build.gradle, set classpath 'com.android.tools.build:gradle:7.4.2'.
    • Kotlin Version: In android/build.gradle, set ext.kotlin_version = '1.8.10'.
    • Gradle Wrapper: In android/gradle/wrapper/gradle-wrapper.properties, set distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip.
    // android/build.gradle
    classpath 'com.android.tools.build:gradle:7.4.2'
    ext.kotlin_version = '1.8.10'
    
    // android/gradle/wrapper/gradle-wrapper.properties
    distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip