Skip to content

Foreground service stops after few hours #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
darshansatra1 opened this issue Aug 9, 2021 · 8 comments
Closed

Foreground service stops after few hours #13

darshansatra1 opened this issue Aug 9, 2021 · 8 comments

Comments

@darshansatra1
Copy link

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?

@Dev-hwang
Copy link
Owner

The above problem seems to be related to the Android doze mode or not handling the exception that occurs inside the initDispatcher function.

Try the following:

  1. Not recommended to use cancelOnError when subscribing to a stream. because, if an error occurs during stream operation, the foreground service does not terminate, only the stream. Change it to false or remove it.
    image

  2. Handle the exception by wrapping the code inside the initDispatcher function with try-catch. Well written in the example above, but I don't know right now.

  3. Starting with Android 6.0 (API level 23), Android uses power saving features to optimize the battery. If the app is in the background, certain features may not be available due to doze restrictions. In some cases, an exception is thrown when trying to use the resource. Refer to this page to turn off battery optimization.

@Dev-hwang
Copy link
Owner

Still having issues?

@darshansatra1
Copy link
Author

The issue is still there, after some time the steps just stops counting. I tried an interval update of 1 hour and checked but after few hours, the service still stops.

@Dev-hwang
Copy link
Owner

Dev-hwang commented Aug 20, 2021

I've been using this plugin with the pedometer plugin for 3 days and haven't had any issues. Still works fine in the background.

I need more information to test.

  1. Requires device os version and brand.
  2. Information from executing flutter doctor command.
  3. Please tell me specifically what you do when a step event occurs.
  4. Please tell me specifically under what circumstances the foreground service stops.
    -- Build Mode: Debug or Release?
    -- Task Interval:
    -- App Location: Foreground or Background?
    -- When: few hours
    -- Task: What does the app do when an error occurs? or are you just walking?

@darshansatra1
Copy link
Author

flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.2.4-0.0.pre.1, on Microsoft Windows [Version 10.0.22000.160], locale en-IN)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] IntelliJ IDEA Ultimate Edition (version 2021.1)
[√] VS Code (version 1.59.1)
[√] Connected device (2 available)

• No issues found!

Build Mode: Issue occurs in both Debug and Release
Task Interval: 1 hour, although there is a pedometer stream running inside.
App Location: Background(When the app is terminated)
When: 3-4 hours
Task: Mostly I think when I'm not walking after few hours, this error occurs.
Device: Samsung M31

@Dev-hwang
Copy link
Owner

I will test it according to the environment. What do you do when a pedometer event occurs? (For example, data storage in DB, network communication, etc.)

@darshansatra1
Copy link
Author

Yes, DB store, I used Objext_Box for storing steps in the DB.

@Dev-hwang
Copy link
Owner

Dev-hwang commented Aug 26, 2021

Hmm... that's strange... I tested it in the similar environment and there is no problem.

env:
Flutter sdk: 2.2.3
Dart sdk: 2.13.4
OS: Android 9, 10, 11
Build: debug, release
Location: background
all running time: 38 hours (no stop, no crash)

code:

@Entity()
class StepCountData {
  int? id;
  int steps;
  String timestamp;

  StepCountData({this.id, required this.steps, required this.timestamp});
}

void startCallback() async {
  final stepCountStream = Pedometer.stepCountStream;
  StreamSubscription<StepCount>? streamSubscription;
  Store? store;
  Box? stepCountDataBox;

  FlutterForegroundTask.initDispatcher((timestamp, sendPort) async {
    if (streamSubscription != null) return;
    streamSubscription = stepCountStream.listen((event) {
      // 데이터 생성
      final data = StepCountData(
          steps: event.steps,
          timestamp: event.timeStamp.toString());

      // 데이터 삽입
      final id = stepCountDataBox?.put(data);
      print('data id: $id');

      // 노티피케이션 업데이트
      FlutterForegroundTask.update(
          notificationText: 'your steps: ${event.steps}');

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

    store = await openStore();
    stepCountDataBox = store?.box<StepCountData>();
  }, onDestroy: (timestamp) async {
    store?.close();
    await streamSubscription?.cancel();
  });
}

Would you like to upgrade this plugin to 3.0.0? The code is more stable.

@Entity()
class StepCountData {
  int? id;
  int steps;
  String timestamp;

  StepCountData({this.id, required this.steps, required this.timestamp});
}

void startCallback() =>
    FlutterForegroundTask.setTaskHandler(FirstTaskHandler());

class FirstTaskHandler implements TaskHandler {
  late Store store;
  late Box stepCountDataBox;
  late StreamSubscription<StepCount> streamSubscription;

  @override
  Future<void> onStart(DateTime timestamp, SendPort? sendPort) async {
    store = await openStore();
    stepCountDataBox = store.box<StepCountData>();

    final stepCountStream = Pedometer.stepCountStream;
    streamSubscription = stepCountStream.listen((event) {
      // 데이터 생성
      final data = StepCountData(
          steps: event.steps,
          timestamp: event.timeStamp.toString());

      // 데이터 삽입
      final id = stepCountDataBox.put(data);
      print('data id: $id');

      // 노티피케이션 업데이트
      FlutterForegroundTask.updateService(
          notificationText: 'your steps: ${event.steps}');

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

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

  }

  @override
  Future<void> onDestroy(DateTime timestamp) async {
    store.close();
    await streamSubscription.cancel();
  }
}

And I will continue to monitor this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants