GithubHelp home page GithubHelp logo

dev-hwang / flutter_foreground_task Goto Github PK

View Code? Open in Web Editor NEW
128.0 6.0 101.0 458 KB

This plugin is used to implement a foreground service on the Android platform.

License: MIT License

Kotlin 46.25% Ruby 1.70% Swift 13.31% Objective-C 0.78% Dart 37.96%
flutter android foreground-service foreground-notification ios background-service

flutter_foreground_task's Introduction

This plugin is used to implement a foreground service on the Android platform.

pub package

Features

  • Can perform repetitive task with foreground service.
  • Provides useful utilities (minimizeApp, wakeUpScreen, etc.) that can use when performing task.
  • Provides a widget that prevents the app from closing when the foreground service is running.
  • Provides a widget that can start the foreground service when the app is minimized or closed.
  • Provides an option to automatically resume foreground service on boot.

Getting started

To use this plugin, add flutter_foreground_task as a dependency in your pubspec.yaml file. For example:

dependencies:
  flutter_foreground_task: ^6.5.0

After adding the flutter_foreground_task plugin to the flutter project, we need to specify the permissions and service to use for this plugin to work properly.

๐Ÿค Android

Open the AndroidManifest.xml file and specify the service inside the <application> tag as follows. If you want the foreground service to run only when the app is running, add android:stopWithTask option.

As it is mentioned in the Android Guidelines, in Android 14, to start a FG service, you need to specify its type.

You can read all the details in the Android Developer Page : https://developer.android.com/about/versions/14/changes/fgs-types-required

If you want to target Android 14 phones, you need to add a few lines to your manifest. Change the type with your type (all types are listed in the link above).

<!-- required -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

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

<!-- foregroundServiceType: remoteMessaging -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />

<!-- Add android:stopWithTask option only when necessary. -->
<service 
    android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
    android:foregroundServiceType="dataSync|remoteMessaging" <!-- Here, chose the type according to your app -->
    android:exported="false" />

Check runtime requirements before starting the service. If this requirement is not met, the foreground service cannot be started.

Runtime requirements are listed in the link above.

๐Ÿค iOS

We can also launch flutter_foreground_task on the iOS platform. However, it has the following limitations.

  • Works only on iOS 10.0 or later.
  • If the app is forcibly closed, the task will not work.
  • Task cannot be started automatically on device reboot.
  • Due to the background processing limitations of the platform, the onRepeatEvent event may not work properly in the background. But in the foreground it works fine.

Objective-C:

  1. To use this plugin developed in Swift language in a project using Objective-C, you need to add a bridge header. If you don't have an ios/Runner/Runner-Bridging-Header.h file in your project, check this page.

  2. Open the ios/Runner/AppDelegate.swift file and add the commented code.

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"

// here
#import <flutter_foreground_task/FlutterForegroundTaskPlugin.h>

// here
void registerPlugins(NSObject<FlutterPluginRegistry>* registry) {
  [GeneratedPluginRegistrant registerWithRegistry:registry];
}

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];

  // here, Without this code the task will not work.
  [FlutterForegroundTaskPlugin setPluginRegistrantCallback:registerPlugins];
  if (@available(iOS 10.0, *)) {
    [UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
  }

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Swift:

  1. Declare the import statement below in the ios/Runner/Runner-Bridging-Header.h file.
#import <flutter_foreground_task/FlutterForegroundTaskPlugin.h>
  1. Open the ios/Runner/AppDelegate.swift file and add the commented code.
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // here, Without this code the task will not work.
    SwiftFlutterForegroundTaskPlugin.setPluginRegistrantCallback(registerPlugins)
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }

    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

// here
func registerPlugins(registry: FlutterPluginRegistry) {
  GeneratedPluginRegistrant.register(with: registry)
}

How to use

This plugin has two ways to start a foreground task. There is a way to manually start a foreground task and a way to start it when the app is minimized or closed by the WillStartForegroundTask widget.

๐Ÿฅ Start manually

  1. Initialize the FlutterForegroundTask. You can use the FlutterForegroundTask.init() function to set notifications and task options.
  • androidNotificationOptions: Options for setting up notifications on the Android platform.
  • iosNotificationOptions: Options for setting up notifications on the iOS platform.
  • foregroundTaskOptions: Options for setting the foreground task.
void _initForegroundTask() {
  FlutterForegroundTask.init(
    androidNotificationOptions: AndroidNotificationOptions(
      channelId: 'foreground_service',
      channelName: 'Foreground Service Notification',
      channelDescription: 'This notification appears when the foreground service is running.',
      channelImportance: NotificationChannelImportance.LOW,
      priority: NotificationPriority.LOW,
      iconData: const NotificationIconData(
        resType: ResourceType.mipmap,
        resPrefix: ResourcePrefix.ic,
        name: 'launcher',
      ),
      buttons: [
        const NotificationButton(id: 'sendButton', text: 'Send'),
        const NotificationButton(id: 'testButton', text: 'Test'),
      ],
    ),
    iosNotificationOptions: const IOSNotificationOptions(
      showNotification: true,
      playSound: false,
    ),
    foregroundTaskOptions: const ForegroundTaskOptions(
      interval: 5000,
      isOnceEvent: false,
      autoRunOnBoot: true,
      allowWakeLock: true,
      allowWifiLock: true,
    ),
  );
}

@override
void initState() {
  super.initState();
  _initForegroundTask();
}
  1. Add WithForegroundTask widget to prevent the app from closing when the foreground service is running.
@override
Widget build(BuildContext context) {
  // A widget that prevents the app from closing when the foreground service is running.
  // This widget must be declared above the [Scaffold] widget.
  return WithForegroundTask(
    child: Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Foreground Task'),
        centerTitle: true,
      ),
      body: buildContentView(),
    ),
  );
}
  1. Write callback and handler and start the foreground service. FlutterForegroundTask.startService() provides the following options:
  • notificationTitle: The title that will be displayed in the notification.
  • notificationText: The text that will be displayed in the notification.
  • callback: A top-level function that calls the setTaskHandler function.
// The callback function should always be a top-level function.
@pragma('vm:entry-point')
void startCallback() {
  // The setTaskHandler function must be called to handle the task in the background.
  FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
}

class FirstTaskHandler extends TaskHandler {
  SendPort? _sendPort;

  // Called when the task is started.
  @override
  void onStart(DateTime timestamp, SendPort? sendPort) async {
    _sendPort = sendPort;

    // You can use the getData function to get the stored data.
    final customData =
        await FlutterForegroundTask.getData<String>(key: 'customData');
    print('customData: $customData');
  }

  // Called every [interval] milliseconds in [ForegroundTaskOptions].
  @override
  void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {
    // Send data to the main isolate.
    sendPort?.send(timestamp);
  }

  // Called when the notification button on the Android platform is pressed.
  @override
  void onDestroy(DateTime timestamp, SendPort? sendPort) async {

  }

  // Called when the notification button on the Android platform is pressed.
  @override
  void onNotificationButtonPressed(String id) {
    print('onNotificationButtonPressed >> $id');
  }

  // Called when the notification itself on the Android platform is pressed.
  //
  // "android.permission.SYSTEM_ALERT_WINDOW" permission must be granted for
  // this function to be called.
  @override
  void onNotificationPressed() {
    // Note that the app will only route to "/resume-route" when it is exited so
    // it will usually be necessary to send a message through the send port to
    // signal it to restore state when the app is already started.
    FlutterForegroundTask.launchApp("/resume-route");
    _sendPort?.send('onNotificationPressed');
  }
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const ExamplePage(),
        '/resume-route': (context) => const ResumeRoutePage(),
      },
    );
  }
}

class ExamplePage extends StatefulWidget {
  const ExamplePage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  ReceivePort? _receivePort;

  // ...

  Future<void> _requestPermissionForAndroid() async {
    if (!Platform.isAndroid) {
      return;
    }

    // "android.permission.SYSTEM_ALERT_WINDOW" permission must be granted for
    // onNotificationPressed function to be called.
    //
    // When the notification is pressed while permission is denied,
    // the onNotificationPressed function is not called and the app opens.
    //
    // If you do not use the onNotificationPressed or launchApp function,
    // you do not need to write this code.
    if (!await FlutterForegroundTask.canDrawOverlays) {
      // This function requires `android.permission.SYSTEM_ALERT_WINDOW` permission.
      await FlutterForegroundTask.openSystemAlertWindowSettings();
    }

    // Android 12 or higher, there are restrictions on starting a foreground service.
    //
    // To restart the service on device reboot or unexpected problem, you need to allow below permission.
    if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) {
      // This function requires `android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` permission.
      await FlutterForegroundTask.requestIgnoreBatteryOptimization();
    }

    // Android 13 and higher, you need to allow notification permission to expose foreground service notification.
    final NotificationPermission notificationPermissionStatus =
        await FlutterForegroundTask.checkNotificationPermission();
    if (notificationPermissionStatus != NotificationPermission.granted) {
      await FlutterForegroundTask.requestNotificationPermission();
    }
  }

  Future<bool> _startForegroundTask() async {
    // You can save data using the saveData function.
    await FlutterForegroundTask.saveData(key: 'customData', value: 'hello');

    // Register the receivePort before starting the service.
    final ReceivePort? receivePort = FlutterForegroundTask.receivePort;
    final bool isRegistered = _registerReceivePort(receivePort);
    if (!isRegistered) {
      print('Failed to register receivePort!');
      return false;
    }

    if (await FlutterForegroundTask.isRunningService) {
      return FlutterForegroundTask.restartService();
    } else {
      return FlutterForegroundTask.startService(
        notificationTitle: 'Foreground Service is running',
        notificationText: 'Tap to return to the app',
        callback: startCallback,
      );
    }
  }

  bool _registerReceivePort(ReceivePort? newReceivePort) {
    if (newReceivePort == null) {
      return false;
    }

    _closeReceivePort();

    _receivePort = newReceivePort;
    _receivePort?.listen((data) {
      if (data is int) {
        print('eventCount: $data');
      } else if (data is String) {
        if (data == 'onNotificationPressed') {
          Navigator.of(context).pushNamed('/resume-route');
        }
      } else if (data is DateTime) {
        print('timestamp: ${data.toString()}');
      }
    });

    return _receivePort != null;
  }

  void _closeReceivePort() {
    _receivePort?.close();
    _receivePort = null;
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      await _requestPermissionForAndroid();
      _initForegroundTask();

      // You can get the previous ReceivePort without restarting the service.
      if (await FlutterForegroundTask.isRunningService) {
        final newReceivePort = FlutterForegroundTask.receivePort;
        _registerReceivePort(newReceivePort);
      }
    });
  }

  @override
  void dispose() {
    _closeReceivePort();
    super.dispose();
  }
}

class ResumeRoutePage extends StatelessWidget {
  const ResumeRoutePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Resume Route'),
        centerTitle: true,
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // Navigate back to first route when tapped.
            Navigator.of(context).pop();
          },
          child: const Text('Go back!'),
        ),
      ),
    );
  }
}

As you can see in the code above, you can manage data with the following functions.

void function() async {
  await FlutterForegroundTask.getData(key: String);
  await FlutterForegroundTask.getAllData();
  await FlutterForegroundTask.saveData(key: String, value: Object);
  await FlutterForegroundTask.removeData(key: String);
  await FlutterForegroundTask.clearAllData();
}

If the plugin you want to use provides a stream, use it like this:

class FirstTaskHandler extends TaskHandler {
  StreamSubscription<Location>? _streamSubscription;

  @override
  void onStart(DateTime timestamp, SendPort? sendPort) async {
    _streamSubscription = FlLocation.getLocationStream().listen((location) {
      FlutterForegroundTask.updateService(
        notificationTitle: 'My Location',
        notificationText: '${location.latitude}, ${location.longitude}',
      );

      // Send data to the main isolate.
      sendPort?.send(location);
    });
  }

  @override
  void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {

  }

  @override
  void onDestroy(DateTime timestamp, SendPort? sendPort) async {
    await _streamSubscription?.cancel();
  }
}
  1. Use FlutterForegroundTask.updateService() to update the foreground service. The options are the same as the start function.
// The callback function should always be a top-level function.
@pragma('vm:entry-point')
void startCallback() {
  // The setTaskHandler function must be called to handle the task in the background.
  FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
}

class FirstTaskHandler extends TaskHandler {
  int _eventCount = 0;

  @override
  void onStart(DateTime timestamp, SendPort? sendPort) async {

  }

  @override
  void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {
    if (_eventCount == 10) {
      FlutterForegroundTask.updateService(
        foregroundTaskOptions: const ForegroundTaskOptions(interval: 1000),
        callback: updateCallback,
      );
    } else {
      FlutterForegroundTask.updateService(
        notificationTitle: 'FirstTaskHandler',
        notificationText: timestamp.toString(),
      );

      // Send data to the main isolate.
      sendPort?.send(_eventCount);

      _eventCount++;
    }
  }

  @override
  void onDestroy(DateTime timestamp, SendPort? sendPort) async {

  }
}

@pragma('vm:entry-point')
void updateCallback() {
  FlutterForegroundTask.setTaskHandler(SecondTaskHandler());
}

class SecondTaskHandler extends TaskHandler {
  @override
  void onStart(DateTime timestamp, SendPort? sendPort) async {

  }

  @override
  void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {
    FlutterForegroundTask.updateService(
      notificationTitle: 'SecondTaskHandler',
      notificationText: timestamp.toString(),
    );

    // Send data to the main isolate.
    sendPort?.send(timestamp);
  }

  @override
  void onDestroy(DateTime timestamp, SendPort? sendPort) async {

  }
}
  1. If you no longer use the foreground service, call FlutterForegroundTask.stopService().
Future<bool> _stopForegroundTask() {
  return FlutterForegroundTask.stopService();
}

๐Ÿฅ Start with WillStartForegroundTask widget

<service 
    android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
    android:stopWithTask="true" /> <!-- important -->
Future<void> _requestPermissionForAndroid() async {
  if (!Platform.isAndroid) {
    return;
  }

  // "android.permission.SYSTEM_ALERT_WINDOW" permission must be granted for
  // onNotificationPressed function to be called.
  //
  // When the notification is pressed while permission is denied,
  // the onNotificationPressed function is not called and the app opens.
  //
  // If you do not use the onNotificationPressed or launchApp function,
  // you do not need to write this code.
  if (!await FlutterForegroundTask.canDrawOverlays) {
    // This function requires `android.permission.SYSTEM_ALERT_WINDOW` permission.
    await FlutterForegroundTask.openSystemAlertWindowSettings();
  }

  // Android 12 or higher, there are restrictions on starting a foreground service.
  //
  // To restart the service on device reboot or unexpected problem, you need to allow below permission.
  if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) {
    // This function requires `android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` permission.
    await FlutterForegroundTask.requestIgnoreBatteryOptimization();
  }

  // Android 13 and higher, you need to allow notification permission to expose foreground service notification.
  final NotificationPermission notificationPermissionStatus =
      await FlutterForegroundTask.checkNotificationPermission();
  if (notificationPermissionStatus != NotificationPermission.granted) {
    await FlutterForegroundTask.requestNotificationPermission();
  }
}

void _onData(dynamic data) {
  if (data is int) {
    print('eventCount: $data');
  } else if (data is String) {
    if (data == 'onNotificationPressed') {
      Navigator.of(context).pushNamed('/resume-route');
    }
  } else if (data is DateTime) {
    print('timestamp: ${data.toString()}');
  }
}

@override
void initState() {
  super.initState();
  _requestPermissionForAndroid();
}

@override
Widget build(BuildContext context) {
  return MaterialApp(
    // A widget that can start the foreground service when the app is minimized or closed.
    // This widget must be declared above the [Scaffold] widget.
    home: WillStartForegroundTask(
      onWillStart: () async {
        // Return whether to start the foreground service.
        return true;
      },
      androidNotificationOptions: AndroidNotificationOptions(
        channelId: 'foreground_service',
        channelName: 'Foreground Service Notification',
        channelDescription: 'This notification appears when the foreground service is running.',
        channelImportance: NotificationChannelImportance.LOW,
        priority: NotificationPriority.LOW,
        isSticky: false, // important
        iconData: const NotificationIconData(
          resType: ResourceType.mipmap,
          resPrefix: ResourcePrefix.ic,
          name: 'launcher',
        ),
        buttons: [
          const NotificationButton(id: 'sendButton', text: 'Send'),
          const NotificationButton(id: 'testButton', text: 'Test'),
        ],
      ),
      iosNotificationOptions: const IOSNotificationOptions(
        showNotification: true,
        playSound: false,
      ),
      foregroundTaskOptions: const ForegroundTaskOptions(
        interval: 5000,
        isOnceEvent: false,
        allowWakeLock: false,
        allowWifiLock: false,
      ),
      notificationTitle: 'Foreground Service is running',
      notificationText: 'Tap to return to the app',
      callback: startCallback,
      onData: _onData,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Foreground Task'),
          centerTitle: true,
        ),
        body: buildContentView(),
      ),
    ),
  );
}

Models

๐Ÿ” AndroidNotificationOptions

Notification options for Android platform.

Property Description
id Unique ID of the notification.
channelId Unique ID of the notification channel.
channelName The name of the notification channel. This value is displayed to the user in the notification settings.
channelDescription The description of the notification channel. This value is displayed to the user in the notification settings.
channelImportance The importance of the notification channel. The default is NotificationChannelImportance.DEFAULT.
priority Priority of notifications for Android 7.1 and lower. The default is NotificationPriority.DEFAULT.
enableVibration Whether to enable vibration when creating notifications. The default is false.
playSound Whether to play sound when creating notifications. The default is false.
showWhen Whether to show the timestamp when the notification was created in the content view. The default is false.
isSticky Whether the system will restart the service if the service is killed. The default is true.
visibility Control the level of detail displayed in notifications on the lock screen. The default is NotificationVisibility.VISIBILITY_PUBLIC.
iconData The data of the icon to display in the notification. If the value is null, the app launcher icon is used.
buttons A list of buttons to display in the notification. A maximum of 3 is allowed.

๐Ÿ” NotificationIconData

Data for setting the notification icon.

Property Description
resType The resource type of the notification icon. If the resource is in the drawable folder, set it to ResourceType.drawable, if the resource is in the mipmap folder, set it to ResourceType.mipmap.
resPrefix The resource prefix of the notification icon. If the notification icon name is ic_simple_notification, set it to ResourcePrefix.ic and set name to simple_notification.
name Notification icon name without prefix.

๐Ÿ” ResourceType

The resource type of the notification icon.

Value Description
drawable A resources in the drawable folder. The drawable folder is where all kinds of images are stored.
mipmap A resources in the mipmap folder. The mipmap folder is usually where the launcher icon image is stored.

๐Ÿ” ResourcePrefix

The resource prefix of the notification icon.

Value Description
ic A resources with the ic_ prefix.
img A resources with the img_ prefix.

๐Ÿ” NotificationButton

The button to display in the notification.

Property Description
id The button identifier.
text The text to display on the button.
textColor The button text color.

๐Ÿ” IOSNotificationOptions

Notification options for iOS platform.

Property Description
showNotification Whether to show notifications. The default is true.
playSound Whether to play sound when creating notifications. The default is false.

๐Ÿ” ForegroundTaskOptions

Data class with foreground task options.

Property Description
interval The task call interval in milliseconds. The default is 5000.
isOnceEvent Whether to invoke the onRepeatEvent of TaskHandler only once. The default is false.
autoRunOnBoot Whether to automatically run foreground task on boot. The default is false.
autoRunOnMyPackageReplaced Whether to automatically run foreground task when the app is updated to a new version. The default is false.
allowWakeLock Whether to keep the CPU turned on. The default is true.
allowWifiLock Allows an application to keep the Wi-Fi radio awake. The default is false.

๐Ÿ” NotificationChannelImportance

The importance of the notification channel. See https://developer.android.com/training/notify-user/channels?hl=ko#importance

Value Description
NONE A notification with no importance: does not show in the shade.
MIN Min notification importance: only shows in the shade, below the fold.
LOW Low notification importance: shows in the shade, and potentially in the status bar (see shouldHideSilentStatusBarIcons()), but is not audibly intrusive.
DEFAULT Default notification importance: shows everywhere, makes noise, but does not visually intrude.
HIGH Higher notification importance: shows everywhere, makes noise and peeks. May use full screen intents.
MAX Max notification importance: same as HIGH, but generally not used.

๐Ÿ” NotificationPriority

Priority of notifications for Android 7.1 and lower.

Value Description
MIN No sound and does not appear in the status bar.
LOW No sound.
DEFAULT Makes a sound.
HIGH Makes a sound and appears as a heads-up notification.
MAX Same as HIGH, but used when you want to notify notification immediately.

๐Ÿ” NotificationVisibility

The level of detail displayed in notifications on the lock screen.

Value Description
VISIBILITY_PUBLIC Show this notification in its entirety on all lockscreens.
VISIBILITY_SECRET Do not reveal any part of this notification on a secure lockscreen.
VISIBILITY_PRIVATE Show this notification on all lockscreens, but conceal sensitive or private information on secure lockscreens.

Utility methods

๐Ÿญ minimizeApp (Both)

Minimize the app to the background.

Warning It only works when the app is in the foreground.

void function() => FlutterForegroundTask.minimizeApp();

๐Ÿญ launchApp (Android)

Launch the app if it is not running otherwise open the current activity.

void function() => FlutterForegroundTask.launchApp();

It is also possible to pass a route to this function but the route will only be loaded if the app is not already running.

๐Ÿญ wakeUpScreen (Android)

Wake up the screen of a device that is turned off.

void function() => FlutterForegroundTask.wakeUpScreen();

๐Ÿญ isIgnoringBatteryOptimizations (Android)

Returns whether the app has been excluded from battery optimization.

Future<bool> function() => FlutterForegroundTask.isIgnoringBatteryOptimizations;

๐Ÿญ openIgnoreBatteryOptimizationSettings (Android)

Open the settings page where you can set ignore battery optimization.

Warning It only works when the app is in the foreground.

Future<bool> function() => FlutterForegroundTask.openIgnoreBatteryOptimizationSettings();

๐Ÿญ requestIgnoreBatteryOptimization (Android)

Request to ignore battery optimization. This function requires android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission.

Warning It only works when the app is in the foreground.

Future<bool> function() => FlutterForegroundTask.requestIgnoreBatteryOptimization();

๐Ÿญ canDrawOverlays (Android)

Returns whether the "android.permission.SYSTEM_ALERT_WINDOW" permission was granted.

Future<bool> function() => FlutterForegroundTask.canDrawOverlays;

๐Ÿญ openSystemAlertWindowSettings (Android)

Open the settings page where you can allow/deny the "android.permission.SYSTEM_ALERT_WINDOW" permission.

Warning It only works when the app is in the foreground.

Future<bool> function() => FlutterForegroundTask.openSystemAlertWindowSettings();

๐Ÿญ isAppOnForeground (Both)

Returns whether the app is in the foreground.

Future<bool> function() => FlutterForegroundTask.isAppOnForeground;

๐Ÿญ setOnLockScreenVisibility (Android)

Toggles lockScreen visibility.

Warning It only works when the app is in the foreground.

void function() => FlutterForegroundTask.setOnLockScreenVisibility(true);

๐Ÿญ checkNotificationPermission (Android)

Returns "android.permission.POST_NOTIFICATIONS" permission status.

for Android 13, https://developer.android.com/develop/ui/views/notifications/notification-permission

Warning It only works when the app is in the foreground.

Future<NotificationPermission> function() => FlutterForegroundTask.checkNotificationPermission();

๐Ÿญ requestNotificationPermission (Android)

Request "android.permission.POST_NOTIFICATIONS" permission.

for Android 13, https://developer.android.com/develop/ui/views/notifications/notification-permission

Warning It only works when the app is in the foreground.

Future<NotificationPermission> function() => FlutterForegroundTask.requestNotificationPermission();

Support

If you find any bugs or issues while using the plugin, please register an issues on GitHub. You can also contact us at [email protected].

flutter_foreground_task's People

Contributors

azihsoyn avatar dev-hwang avatar gaellejoubert avatar h2210316651 avatar hwj930513 avatar insidewhy avatar maxbodelier avatar mouesam avatar techno-disaster avatar unluckyy1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

flutter_foreground_task's Issues

Foreground with database

Hi there, actually it is not an issue :)
I was trying to trigger action on database in foreground ( moor plugin to be more precise, but hive is even more fussy ), but I couldn't find any smart solution for this. I've tried with isolation but it is not working at all. Is it even possible to use db in this way?

How to perform specific function with flutter_foreground_task

Hi, apology for being dumb and asking this question here.

I am using Flutter Telephony plugin which works fine (listens to incoming SMS). But it only works when app is in foreground for some reason. So I decided to use this plugin to listen to incoming SMS through foreground task, but don't know where to start.

So far I have been able to get flutter_foreground_task working as in example, but which part of code in this plugin will handle Flutter Telephony events?

Please help.

Kotlin Redeclaration error

Hi there!

After update, I got ton of some "redeclaration" (and other) Kotlin errors

Luckly, I was able to solve them with:

# in my app directory
flutter clean
cd android
./gradlew clean

cd ..
flutter pub get
flutter run
# Yay it works!

Also in android/build.gradle i updated ext.kotlin_version to '1.5.10', but it was for other plugins so it may not be required for foreground_task

I'm leaving this here in case someome has this issue too (dunno if I should close it right ahead or leave it open ๐Ÿคท)

how add button to initial notification ?

how add button named "Disconnect" in AndroidNotificationOptions ?

my simple code is here .

const AndroidNotificationOptions(
      channelId: 'parameter_channel',
      channelName: 'Parameters',
      channelDescription: 'This notification appears when the reading begaz params running.',
      channelImportance: NotificationChannelImportance.LOW,
      priority: NotificationPriority.LOW,
      visibility: NotificationVisibility.VISIBILITY_PRIVATE,
      playSound: false,
      enableVibration: false,
      iconData: NotificationIconData(
        resType: ResourceType.mipmap,
        resPrefix: ResourcePrefix.ic,
        name: 'launcher',
      ),
    ),

Add SendPort on onButtonPressed callback

Hello, is it possible for this plugin to add SendPort object on onButtonPressed callback as a parameter? I'm having a notification button that is supposed to communicate with the main isolate when pressed, but TaskHandler doesn't seem to have this object by default that this can only be obtained in certain callback like onEvent().

Thank you.

Doesn't call onDestroy on restart

I want to do some operations when the service stops. When the service is stopped in the app onDestroy function works properly. But when I restart my device the onDestroy function is not called. Am I missing something here? or is it just the way services are?

Foreground service stops after few hours

Currently, I'm trying to implement a step counter which is calculated by foreground service having pedometer stream. I have observed that after few hours the foreground service stops, although the notification is still showing. Is there an alternative approach for solving this issue?

No way to get receivePort without restarting task handler

  1. Open the app and start the task handler.
  2. Close the app (i.e. hit app switcher and swipe app away).
  3. Observe the isolate is still running and handling onEvent.
  4. Open the app via the notification button and observe that the related receivePort that was previously stored in memory is now null.
  5. Now there is no way to connect a ReceivePort to the isolate that is still running. You can call FlutterForegroundTask.restartService to get a new receive port, but this destroys your task handler which causes you to lose all the state you've accumulated in it.

If the isolate is lost once the app is stopped, then is there any point in still keeping it running? Or should I be constantly writing to shared preferences so that I can resume?

Unhandled Exception: MissingPluginException

I'm trying to using this plugin with flutter_beacon but i keep getting the error below:

Unhandled Exception: MissingPluginException(No implementation found for method initialize on channel flutter_beacon)

I suppose it has to do with the fact that flutter_foreground_task launches a new isolate. Is there a way around this? Really stuck.

While the foreground task is active the back button minimises the app instead of going back

I'm not 100% sure that this isn't to do with the way I've used flutter_foreground_task but as soon as I activate the foreground task then the back button stops navigating back through the history and minimises the app instead (both the hardware back button and the back button that appears in the main title bar). As soon as I stop the foreground task the back button starts working as intended again.

I've added WithForegroundTask on top of Scaffold for every route, maybe that's not the intended way to use it?

IOS foreground task stops working after around 35 seconds

I've been using this package for my app and the implementation works fine on Android. However I've noticed that after about 35 seconds of swiping out of the app to the Home Screen, the foreground service stops updating. I'm using geolocator to get the location like so:
locationSubscription = positionStream.listen((Position position) { currentLocation = position; FlutterForegroundTask.updateService( notificationTitle: 'Current Position', notificationText: '${position.latitude}, ${position.longitude}'); })
The foreground service updates for about 35 seconds but stops after that. The WithForegroundTask widget has been wrapped around my home widget and I'm using the IOS simulator to test this. I understand the readme did mention that 'If the app is forcibly closed, the task will not work.' I'm not sure if this is a misunderstanding on my part but swiping out to the Home Screen isn't force closing the app right?

Tldr: the flutter foreground task stops updating after about 35 seconds on the iOS simulator

can we Revert to minsdk 21 ?

Hey , i just noticed one thing that my app size increases almost double after changing minsdk from 21 -> 23 , but i can't use 21 with this pcakcge , so any workaround or possible to set minsdk 21 for your package

Unresolved reference: S

When I compile the app with Visual Studio Code it gives me the following error:

e: C:\Projects\flutter.pub-cache\hosted\pub.dartlang.org\flutter_foreground_task-3.5.0\android\src\main\kotlin\com\pravera\flutter_foreground_task\service\ForegroundService.kt: (210, 53): Unresolved reference: S
e: C:\Projects\flutter.pub-cache\hosted\pub.dartlang.org\flutter_foreground_task-3.5.0\android\src\main\kotlin\com\pravera\flutter_foreground_task\service\ForegroundService.kt: (211, 13): Unresolved reference: setForegroundServiceBehavior
e: C:\Projects\flutter.pub-cache\hosted\pub.dartlang.org\flutter_foreground_task-3.5.0\android\src\main\kotlin\com\pravera\flutter_foreground_task\service\ForegroundService.kt: (211, 55): Unresolved reference: FOREGROUND_SERVICE_IMMEDIATE

Thks.

Force Close App when start foreground with Android compileSdkVersion 31

Force Close When Start Foreground with Android compileSdkVersion 31

hi i got force close when start the foreground service running on android emulator version Sv2
can u fix it.

Script

FlutterForegroundTask.init(
androidNotificationOptions: const AndroidNotificationOptions(
channelId: 'notification_channel_id',
channelName: 'Foreground Notification',
channelDescription: 'This notification appears when the foreground service is running.',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
iconData: NotificationIconData(
resType: ResourceType.mipmap,
resPrefix: ResourcePrefix.ic,
name: 'launcher',
),
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: true,
playSound: false,
),
foregroundTaskOptions: const ForegroundTaskOptions(
interval: 5000,
autoRunOnBoot: true,
),
printDevLog: true,
);

Android Log.

D/CompatibilityChangeReporter( 7017): Compat change id reported: 160794467; UID 10151; state: ENABLED
D/AndroidRuntime( 7017): Shutting down VM
E/AndroidRuntime( 7017): FATAL EXCEPTION: main
E/AndroidRuntime( 7017): Process: com.pramana507.cyclops_droid.dev, PID: 7017
E/AndroidRuntime( 7017): java.lang.RuntimeException: Unable to create service com.pravera.flutter_foreground_task.service.ForegroundService: java.lang.IllegalArgumentException: com.pramana507.cyclops_droid.dev: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
E/AndroidRuntime( 7017): Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

Flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[โœ“] Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-arm, locale en-ID)
[โœ“] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[โœ“] Xcode - develop for iOS and macOS
[โœ“] Chrome - develop for the web
[โœ“] Android Studio (version 2020.3)
[โœ“] VS Code (version 1.62.2)
[โœ“] Connected device (2 available)

Pass parameters to the callback function

Future<void> startPeriodicTask({
  required int steps,
  required int yesterdaySteps,
}) async {
  await FlutterForegroundTask.start(
      notificationTitle: "Notification", 
      callback: periodicTaskFun,
);
}

Right now I'm using this code to register the callback function, but can I pass parameters like String or Int to periodicTaskFun? If not please can you add such a feature?

Bidirectional communication

Hi, first of all thanks for the work.
It is not clear to me how I could implement bidirectional communication between the UI and the foreground service isolates.
Currently, it seems that, if the UI wants to send data to the service, it can only use the saveData function.
Moreover, how can I recover the receivePort between app restarts withour restarting the service?

Thank you

flutter_foreground_task

can i use socket.io/ node server/ tcp server
with flutter_foreground_task
if not then
fackebook/messenger/viber/whatsup
how to user ??

Accessing native plugin from TaskHandler

Hi,

I want to access the Wi-Fi SSID, BSSID and RSSI from my TaskHandler so I can measure how the wifi strength varies over time. In the onEvent method of my TaskHandler I'm calling WifiInfoAndroid.getWifiInfo which is from the wifi_info_android plugin. The code for that is pretty simple, it can be found here: https://github.com/sol-x/wifi_info_android/blob/main/android/src/main/kotlin/co/solx/wifi_info_android/WifiInfoAndroidPlugin.kt

When trying to access the wifi info from the TaskHandler I always get a null value though. I'm not sure if there is a general issue with calling native code via a MethodChannel from a TaskHandler or if it's something specific to do with activity aware plugins.

Maybe I should be accessing the wifi info from receivePort.listen and only using the sendPort in the TaskHandler to indicate that the main thread should be accessing the wifi info?

InvokeChannel limitation

Hi @Dev-hwang ,
I'd like to spawn a foreground task with this plugin, which executes code with other plugins (e.g. flutter_beacon). When I do this, I receive errors like "MissingPluginException Method x not found in channel y".

Is this due to the fact, that foreground task runs in a separate isolate and as a result it is not possible to to call methodIncovate because it needs to run in "UIThread"? Is this an implicit limitation or is this only due to other plugins? (Guess it's answered in #10.

Is there any possible workaround you can think of without moving away fro this plugin?

Problem with background on iOS

Hi, I use the GeoLocator's position stream and send the updates to the foreground task receiveport which I listen to. On Android it works fine but on iOS it stops after about 10-15 seconds after returning to the home screen. Any ideas how to fix this?

Geolocator.getPositionStream(intervalDuration: Duration(seconds: 1)).listen((event) {
      print(event);
      sendPort!.send(event);
    });
_receivePort = receivePort;
      _receivePort!.listen((message) {
        print("RECIEVE PORT");
        print(message);
      });

Thanks anyway :)

Notification visible on the lockscreen

I don't know whether it is because of my poor knowledge of the plugin or what but I'm not able to hide the notification of my running foreground service on the lockscreen. Is there any solution for that?

Flutter build apk failed

`Building with sound null safety

Running Gradle task 'assembleRelease'...

FAILURE: Build failed with an exception.

  • What went wrong:

Execution failed for task ':app:mergeReleaseResources'.

Multiple task action failures occurred:

A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade

  > Android resource compilation failed

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-mdpi\ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start with PNG signature.



    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-mdpi\ic_launcher.png: AAPT: error: file failed to compile.

A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade

  > Android resource compilation failed

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-hdpi\ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start with PNG signature.



    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-hdpi\ic_launcher.png: AAPT: error: file failed to compile.

A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade

  > Android resource compilation failed

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xhdpi\ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start with PNG signature.



    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xhdpi\ic_launcher.png: AAPT: error: file failed to compile.

A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade

  > Android resource compilation failed

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xxhdpi\ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start

with PNG signature.

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xxhdpi\ic_launcher.png: AAPT: error: file failed to compile.

A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade

  > Android resource compilation failed

    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xxxhdpi\ic_launcher.png: AAPT: error: failed to read PNG signature: file does not start with PNG signature.



    D:\coding\flutter\app\mileagecalculator\android\app\src\main\res\mipmap-xxxhdpi\ic_launcher.png: AAPT: error: file failed to compile.
  • Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

BUILD FAILED in 13m 59s
Running Gradle task 'assembleRelease'... 849.4s
The build failed likely due to AndroidX incompatibilities in a plugin. The tool is about to try using Jetifier to solve the incompatibility.
โœ๏ธ Creating android\settings_aar.gradle... 158ms
โˆš android\settings_aar.gradle created successfully.
Building plugin flutter_foreground_task...
Running Gradle task 'assembleAarRelease'... 59.6s

FAILURE: Build failed with an exception.

  • What went wrong:
    Could not determine the dependencies of task ':compileReleaseAidl'.

SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project's local properties file at 'C:\src\flutter.pub-cache\hosted\pub.dartlang.org\flutter_foreground_task-2.0.5\android\local.properties'.

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 56s

The plugin flutter_foreground_task could not be built due to the issue above.`

###########################################################################

please can you solve this issue

Foreground task Started but do nothing

I'm having an issue with my Foreground task (on IOS and Android).
I know it starts :

  • I have a log message : "FlutterForegroundTask started"
  • I have the notification that pop up on the phone screen.

But it doesn't seems to do anything I've put in the on start or on event function.
I've put "print" and "log", in the "on start" function, it should be printed on my run console, or is there something I'm misunderstanding ?
Also about the "on event" function, it should be called periodically with the interval specified in the init function, right ?
(I want to be sure that I understood correctly).

Here is my code :
The init function :

FlutterForegroundTask.init(
      androidNotificationOptions: AndroidNotificationOptions(
        channelId: 'notification_channel_id',
        channelName: 'Foreground Notification',
        channelDescription: 'This notification appears when the foreground service is running.',
        channelImportance: NotificationChannelImportance.LOW,
        priority: NotificationPriority.LOW,
        iconData: NotificationIconData(
          resType: ResourceType.mipmap,
          resPrefix: ResourcePrefix.ic,
          name: 'launcher',
        ),
      ),
      iosNotificationOptions: IOSNotificationOptions(
        showNotification: true,
        playSound: false,
      ),
      foregroundTaskOptions: ForegroundTaskOptions(
        interval: 5000,
        autoRunOnBoot: true,
      ),
      printDevLog: true,
    );

The function called to start the background service :

void startBackground2(BuildContext? context) async {
  ReceivePort? _receivePort;
  await FlutterForegroundTask.saveData(key: 'customData', value: 'hello');
  print("Test1");
  _receivePort = await FlutterForegroundTask.startService(
    notificationTitle: 'Foreground Service is running',
    notificationText: 'Tap to return to the app',
    callback: () {startCallback();
    },
  );
  _receivePort?.listen((message) {
    if (message is DateTime)
      print('receive timestamp: $message');
  });
}

The start call back and the TaskHandler :

void startCallback() {
  // The setTaskHandler function must be called to handle the task in the background.
  FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
}

class FirstTaskHandler implements TaskHandler {
  @override
  Future<void> onStart(DateTime timestamp, SendPort? sendPort) async {
    print("allez la");
    log("log la");
    final customData = await FlutterForegroundTask.getData<String>(key: 'customData');
    print('customData: ');
    print('log: ');


  }

  @override
  Future<void> onEvent(DateTime timestamp, SendPort? sendPort) async {
    // Send data to the main isolate.
    print('yeah !');
    log('log yeah ');
    sendPort?.send(timestamp);
  }

  @override
  Future<void> onDestroy(DateTime timestamp) async {
    // You can use the clearAllData function to clear all the stored data.
    await FlutterForegroundTask.clearAllData();
  }
}

As I said before, The service is starting, but I have Zero prints or log which are working, and even the print on " _receivePort?.listen((message) " doesn't work.

Would you have any idea why, or what did I not understand correctly ?
Thanks a lot !

Not able to do network call

I need to upload a file in foreground service & when I am doing the request but didn't receive the response.

 final videoPath = await FlutterForegroundTask.getData<String>(key: 'videoPath');
    print('customDataVideo: $videoPath'); // works till here
    var request = http.MultipartRequest('POST', Uri.parse(url);
   print('customData 2: 2');  // no getting this log

Conflict with audio_service

Hi, first thanks for this great library.
I am having the following issue.

When I call FlutterForegroundTask.stop();

audio_service also stops its service, the opposite does not happen.

I looked and they both use different serviceId.
flutter_foreground_task: 1000
audio_service: 1124

Any suggestions on what it might be?

Considering android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS support on Android

I compared https://pub.dev/packages/flutter_background and https://pub.dev/packages/flutter_foreground_task and I wonder if it was possible to add support for android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permissions on Android. Not sure if https://stackoverflow.com/questions/44862176/request-ignore-battery-optimizations-how-to-do-it-right is something to watch out for (Android 6 is API 23, currently the package min SDK is 21 so theoretically yes). I haven't looked deeper into https://github.com/JulianAssmann/flutter_background yet to see what else is needed for that permission.

Problem with Navigator.pushReplacement()

Hello,

I just noticed if I use the pushReplacement() method of the navigator in the widget which has the WithForegroundTask implemented, the foreground service get lost. Is there any solution to this?
I am using FirebaseAuth in my App and want to provide an logout function which routes to an login page. I dont want to register the service on login.

how to prevent android from kill my app

i have audio app its job play audio in background and when screen look.
i have one problem that android os kill my app after 1hour or less .
now i used you package from prevent os from kill app but still kill it.
and when on lock screen didn't go to next track until open screen
my code

 @override
  void initState() {
    super.initState();
    initPlatformState();
    _initForegroundTask();
    _timerLink = new Timer(
      const Duration(milliseconds: 3000),
      () {
        _dynamicLinkService.retrieveDynamicLink(context);
      },
    );
  }
  Future<void> _initForegroundTask() async {
  await FlutterForegroundTask.init(
    androidNotificationOptions: AndroidNotificationOptions(
      channelId: 'notification_channel_id',
      channelName: 'Foreground Notification',
      channelDescription: 'This notification appears when the foreground service is running.',
      channelImportance: NotificationChannelImportance.LOW,
      priority: NotificationPriority.LOW,
      iconData: const NotificationIconData(
        resType: ResourceType.mipmap,
        resPrefix: ResourcePrefix.ic,
        name: 'launcher',
      ),
      buttons: [
        const NotificationButton(id: 'sendButton', text: 'Send'),
        const NotificationButton(id: 'testButton', text: 'Test'),
      ],
    ),
    iosNotificationOptions: const IOSNotificationOptions(
      showNotification: false,
      playSound: false,
    ),
    foregroundTaskOptions: const ForegroundTaskOptions(
      interval: 5000,
      autoRunOnBoot: false,
      allowWifiLock: true,
    ),
    printDevLog: true,
  );
}

and add WithForegroundTask like that

return Consumer<ThemeProvider>(builder: (context, theme, child) {
      return WithForegroundTask(
        child: GetMaterialApp(
          translations: Translation(),
          debugShowCheckedModeBanner: false,
          theme: lightThemeData(),
          darkTheme: darkThemeData(),
          themeMode: theme.darkMode ? ThemeMode.dark : ThemeMode.light,
          locale: !theme.lang ? Locale('ar') : Locale('en'),
          fallbackLocale: Locale('ar'),
          initialRoute: SplashScreen.routeName,
          routes: routes,
          onGenerateRoute: (RouteSettings routesSettings) {
            final List<String> args = routesSettings.name.split('/');
            if (args[0] != '') {
              return null;
            }
            if (args[1] == 'book') {
              print('hey');
            }
            return;
          },
          onUnknownRoute: (RouteSettings settings) {
            print('bye');
            return;
          },
        ),
      );
    });

all i want to prevent android from kill my app

Class cast exception

Hello there,
tldr; when i'm trying to start foreground tast I get this exception:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
	at com.pravera.flutter_foreground_task.service.ForegroundServiceManager.saveOptions(ForegroundServiceManager.kt:98)
	at com.pravera.flutter_foreground_task.service.ForegroundServiceManager.start(ForegroundServiceManager.kt:24)
	at com.pravera.flutter_foreground_task.MethodCallHandlerImpl.onMethodCall(MethodCallHandlerImpl.kt:47)
	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:818)
	at android.os.MessageQueue.nativePollOnce(Native Method)
	at android.os.MessageQueue.next(MessageQueue.java:325)
	at android.os.Looper.loop(Looper.java:142)
	at android.app.ActivityThread.main(ActivityThread.java:6944)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

My code is pretty much like in the example and I have no clue where to find the problem. In a task, I'm displaying the timestamp so I do not know what kind of integer is trying to be cast into long.

Start service from native side (Kotlin/Java)

HI!
I would like to use a foreground service to update my native Android widget (on home screen) - I have everything set up and figured out, except the part "how to start foreground service with some Dart running when received onUpdate in widget"

Is there some nice Intent that I can just fire to start the service?

Not able to access Pedometer stream in foreground service

While running the foreground service I want to access the pedometer stream. Here I am using pedometer package which exposes a stream for accessing steps of the device. When I was using flutter_foreground_service_plugin I did not face any issue accessing the stream. But using this plugin I am facing an issue related to ServicesBinding.defaultBinaryMessenger. I also placed
WidgetsFlutterBinding.ensureInitialized(); in main.dart but it is still giving me this error. It would be a great help if you can look into it cause I don't want to switch back to flutter_foreground_service_plugin since this plugin is quite awesome and well documented.

Code

Stream _stepCountStream = Pedometer.stepCountStream;
final StepCount steps = await _stepCountStream.first;

Error

E/flutter (23365): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
E/flutter (23365): If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
E/flutter (23365): If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
E/flutter (23365): #0      defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:97:7)
E/flutter (23365): #1      defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:110:4)
E/flutter (23365): #2      EventChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:512:62)
E/flutter (23365): #3      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:532:7)
E/flutter (23365): #4      EventChannel.receiveBroadcastStream.<anonymous closure> (package:flutter/src/services/platform_channel.dart:531:64)
E/flutter (23365): #5      _runGuarded (dart:async/stream_controller.dart:773:24)
E/flutter (23365): #6      _BroadcastStreamController._subscribe (dart:async/broadcast_stream_controller.dart:207:7)
E/flutter (23365): #7      _ControllerStream._createSubscription (dart:async/stream_controller.dart:786:19)
E/flutter (23365): #8      _StreamImpl.listen (dart:async/stream_impl.dart:473:9)
E/flutter (23365): #9      new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:114:10)
E/flutter (23365): #10     _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:86:16)
E/flutter (23365): #11     _ForwardingStream.listen (dart:async/stream_pipe.dart:81:12)
E/flutter (23365): #12     Stream.first (dart:async/stream.dart:1211:14)
E/flutter (23365): #13     periodicTaskFun (package:realfit/core/background/foreground_service.dart:70:50)
E/flutter (23365): #14     _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:140:25)
E/flutter (23365): #15     _rootRun (dart:async/zone.dart:1354:13)
E/flutter (23365): #16     _CustomZone.run (dart:async/zone.dart:1258:19)
E/flutter (23365): #17     _runZoned (dart:async/zone.dart:1788:10)
E/flutter (23365): #18     runZonedGuarded (dart:async/zone.dart:1776:12)
E/flutter (23365): #19     _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:133:5)
E/flutter (23365): #20     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
E/flutter (23365): #21     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
E/flutter (23365): 

FlutterJNI was detached from native C++

Error: W/FlutterJNI(31092): Tried to send a platform message to Flutter, but FlutterJNI was detached from native C++. Could not send. Channel: step_count. Response ID: 0

When I closed the app, sometimes while walking the debug console shows me this message. Can you help me with this, why I'm getting this error?

About the start function

When we call
await FlutterForegroundTask.start( notificationTitle: "Today: $steps steps", notificationText: 'Yesterday: $yesterdaySteps steps', callback: periodicTaskFun, );
Does this call creates a new isolate or is the service still running in the main isolate?

Problem with iOS Bridging Header

I always get this error when I try to run my app on an iOS device:
Runner/Runner-Bridging-Header.h:2:9: error: 'flutter_foreground_task/FlutterForegroundTaskPlugin.h' file not found
#import <flutter_foreground_task/FlutterForegroundTaskPlugin.h>
I tried clean build folder, pod deintegrate, flutter clean, flutter pub get, pod install
nothing worked

Service stops when app is killed

As title says, the service is closed when the app is killed. Is this the right behavior? If so is there a way to prevent this?

What is wakeUpScreen supposed to do?

Hi, thanks for the solid package that is very useful.

void function() => FlutterForegroundTask.wakeUpScreen();

is it supposed to just light up the screen if it is off or is it supposed wake up the up (the opposite of minimizeApp)?

Currently, minimizeApp works and puts the app in the background but wakeUpScreen does nothing for me

Thanks,

App icon is not being shown

When I run the service and the task, the notification shows and updates properly. But the notification icon is a round white circle, how to I change it to my required icon.

Notification Icon is not shown properly

Hello,

I have the problem that the notification icon is not shown. Just an grey circle is displayed.

I am using the launcher icon as notification icon. So I just changed the Icons and not the example code.

iconData: const NotificationIconData(
          resType: ResourceType.mipmap,
          resPrefix: ResourcePrefix.ic,
          name: 'launcher',
        )

in every mipmap folder is a ic_launcher.png file.

IOS Notification Issue when updating notification using updateService method

using
flutter_foreground_task: 3.5.2
flutter: 2.8.0
Dart SDK version: 2.15.0 (stable) (Fri Dec 3 14:23:23 2021 +0100) on "macos_x64"

I am running a timer from onStart() function of the TaskHandler
In the timer event, when I am updating the notification text using FlutterForegroundTask.updateService(), a new notification generates instead of updating the current one.

The issue only exists in IOS

while doing the same in Android, it just updates the current notification, instead of generating the new one

Here is the sample code of TaskHandler to reproduce the issue.

What I am assuming, is the same behavior that is to update the current notification, just update the text instead of updating the whole notification. OR Similar behavior to Android

Everything else is running fine!

class ForegroundTaskHandler implements TaskHandler {
  @override
  Future<void> onStart(DateTime timestamp, SendPort sendPort) async {
    int maxTime = await FlutterForegroundTask.getData(key: 'maxTime');

    Timer.periodic(const Duration(seconds: 1), (timer) async {
      if (maxTime > 0) {
        sendPort.send(--maxTime);
        FlutterForegroundTask.updateService(
          notificationTitle: 'Time Remaining',
          notificationText:
              '${(maxTime ~/ 60).toString().padLeft(2, '0')}:${(maxTime % 60).toString().padLeft(2, '0')}',
        );
      } else {
        timer.cancel();
      }
    });
  }

  @override
  Future<void> onEvent(DateTime timestamp, SendPort sendPort) async {}

  @override
  Future<void> onDestroy(DateTime timestamp) async {
  }

  @override
  void onButtonPressed(String id) {
  }
}

Please have a look into this, or provide some guideline if I am doing it the wrong way.

Feel free to ask more information if needed!

save BluetoothConnection variable in foreground

Hi.
Thank you for develop this plugin.
This dependency solves all my problems except for two, which I will explain below:

  1. how save BluetoothConnection class variable .
    now BluetoothConnection variable is dead when app close from task manager.
    I'm only test this on Android Devices.

  2. I'm not able to network call in background i test two dependeny. retrofit & http

I am also in an urgent position that encourages me to do this today.
Thanks in advance for taking the time to respond to this issue

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.