transistorsoft/react-native-background-fetch

BackgroundFetch.finish does not stop scheduled tasks

rakshitbharat opened this issue · 15 comments

Your Environment

  • Plugin version:
  • Platform: iOS or Android : Both
  • OS version: windows 11
  • Device manufacturer / model: Pixel 6
  • React Native version (react-native -v): 0.76
  • Plugin config

Expected Behavior

finish should stop and terminate the ongoing task

Actual Behavior

finish is not working so you cant stop the running task

import BackgroundFetch from 'react-native-background-fetch';

/**
 * Class BackgroundTaskManager is designed to manage background tasks using
 * react-native-background-fetch. However, the finish method does not seem
 * to terminate the ongoing tasks as expected.
 */
class BackgroundTaskManager {
  /**
   * Configures the task manager with provided arguments for background execution.
   */
  static configure(...args) {
    return BackgroundFetch.configure(...args);
  }

  /**
   * Schedules a new background task using react-native-background-fetch.
   */
  static scheduleTask(...args) {
    console.log('Scheduling task with args:', args);
    return BackgroundFetch.scheduleTask(...args);
  }

  /**
   * Attempts to stop the background task using react-native-background-fetch's
   * finish method. However, this does not seem to stop the ongoing task.
   */
  static finish(...args) {
    console.log('Finishing task with args:', args);
    return BackgroundFetch.finish(...args);
  }
}

export default BackgroundTaskManager;

.finish(taskId) does not "stop" a periodic task from continuing -- it's merely a signal to the OS "I'm finished with this task invocation".

See the API docs .stop(taskId).

any way to force stop the running task ?

To signal to the OS that the currently running task is finished, call .finish(taskId).

this class want meant to do the same but not working,
the task is not terminated

Do you understand the difference between .stop(taskId) and .finish(taskId)?

if i have to terminate the on going task
should i first programatically call finish and then stop ?

import BackgroundFetch from 'react-native-background-fetch';
import { DeviceEventEmitter } from 'react-native';

/**
 * BackgroundTaskManager manages background tasks using react-native-background-fetch.
 * Issue: The finish method does not terminate the ongoing tasks as expected.
 */
class BackgroundTaskManager {
  static configStartFunction = null;

  /**
   * Configures the task manager for background execution.
   * @param {...any} args - Arguments for configuration.
   * @returns The result of the BackgroundFetch configuration.
   */
  static configure(...args) {
    // Store the start function provided in arguments for later use
    this.configStartFunction = args[1];

    // A wrapper for the task execution
    const taskWrapper = async (taskId) => {
      console.log(`Executing task with taskId: ${taskId}`);

      // Listen for a stop signal
      DeviceEventEmitter.addListener('stopBackgroundTask', () => {
        console.log(`Received stop signal for task ${taskId}`);
        BackgroundFetch.finish(taskId);
      });

      // Execute the provided start function if it exists
      if (this.configStartFunction) {
        this.configStartFunction(taskId);
      }
    };

    // Replace the original start function with the wrapper in arguments
    args[1] = taskWrapper;
    return BackgroundFetch.configure(...args);
  }

  /**
   * Schedules a new background task.
   * @param {...any} args - Arguments for scheduling the task.
   * @returns The result of scheduling the task.
   */
  static scheduleTask(...args) {
    console.log('Scheduling task with args:', args);
    return BackgroundFetch.scheduleTask(...args);
  }

  /**
   * Attempts to stop the background task.
   * Issue: This method does not stop the ongoing task.
   * @param {string} taskId - The ID of the task to stop.
   */
  static finish(taskId) {
    console.log('Finishing task with taskId:', taskId);
    DeviceEventEmitter.emit('stopBackgroundTask', taskId);
    BackgroundFetch.finish(taskId);
  }
}

export default BackgroundTaskManager;

no luck tried all way

I found very strange phenomena, if we will use infinite loop like ""while"" in case you use any library or even promise it will never ever going to stop the task.
and there is no way i can find to terminate the callback function in case the callback function contains the while loop

I don't know what you're trying to do. You're making this way more complex than it actually is.

You get a finite number of seconds to complete each invocation of your callback function before the OS gets impatient for consuming too much time in the background. Call .finish(taskId) to signal to the OS that your task invocation is complete.

When you no longer wish for the plug-in to schedule more invocations of your callback function, call .stop(taskId) and your callback will no longer be scheduled to execute in the future.

I want to run a task in which i can terminate it any time when neede, i tried almost all library but no luck,
i want any way to run the task and terminate it, also note i want to run it in foreground only.

Calling .finish(taskId) does not STOP your code from running.

It is merely a signal to the OS "I'm finished. You may put the app to sleep if you wish".

You CANNOT do an infinite loop in your callback and expect that calling .finish(taskId) is going to magically make your infinite while-loop stop executing.

any option to do so ?
i have a hardware based communication where if user wants we dismiss all the operations immediately

"You CANNOT do" really means "CANNOT do".

It doesn't mean "maybe there's an option to do it".

It's up to you to make your own flag to exit out of an infinite loop.

Thanks for reply i found a way to send a emit to change the value of the flag of while loop to false from finish function this way the loop is getting exit on time.