transistorsoft / react-native-background-fetch

Periodic callbacks in the background for both IOS and Android
MIT License
1.43k stars 191 forks source link

BackgroundFetch.registerHeadlessTask Issues #454

Closed s1tony closed 2 weeks ago

s1tony commented 10 months ago

For my React Native Application, I am attempting to use the BackgroundFetch.registerHeadlessTask capability. I setup my code per the example, and while the callback for BackgroundFetch.configure fires during my testing, the Headless Task never does.

Your Environment

Expected Behavior

When my application is in the background or terminated, the method passed to BackgroundFetch.registerHeadlessTask should run.

Actual Behavior

When my application is in the background or terminated, the method passed to BackgroundFetch.registerHeadlessTask never fires.

Steps to Reproduce

  1. Add code to configure BackgroundFetch and then Register Headless task
  2. Start app via Metro
  3. Put app in background
  4. Wait 20 or more minutes

App.tsx (snippet)

`const initBackgroundFetch = async () => { const status: number = await BackgroundFetch.configure({ minimumFetchInterval: 15, // <-- minutes (15 is minimum allowed) stopOnTerminate: false, enableHeadless: true, //startOnBoot: true, // Android options forceAlarmManager: false, // <-- Set true to bypass JobScheduler. requiredNetworkType: BackgroundFetch.NETWORK_TYPE_NONE, // Default requiresCharging: false, // Default requiresDeviceIdle: false, // Default requiresBatteryNotLow: false, // Default requiresStorageNotLow: false, // Default }, async (taskId:string) => { console.log('[BackgroundFetch] taskId', taskId); BackgroundFetch.finish(taskId); }, (taskId:string) => { // Oh No! Our task took too long to complete and the OS has signalled // that this task must be finished immediately. console.log('[Fetch] TIMEOUT taskId:', taskId); BackgroundFetch.finish(taskId); })};

const App = () => { const appId = RealmInfo.appId; const realmApp = createRealmApp(appId); Realm.App.Sync.setLogLevel(realmApp, 'error'); Realm.App.Sync.setLogger(realmApp, console.log);

useEffect(() => { initBackgroundFetch();

const unsubscribe = notifee.onForegroundEvent(({ type, detail }) => {
  switch (type) {
    case EventType.DISMISSED:
      console.log('User dismissed notification', detail.notification);

      break;
    case EventType.PRESS:
      console.log('User pressed notification', detail.notification);

      break;
  }
});

return () => {
  unsubscribe();
};

}, []);`

index.js (snippet)

`messaging().setBackgroundMessageHandler(onMessageReceived); AppRegistry.registerComponent(appName, () => App);

const onCheckForExpiredLists = async (event) => { const taskId = event.taskId; const isTimeout = event.timeout;

if (isTimeout) { console.log('[BackgroundFetch] Headless TIMEOUT:', taskId); BackgroundFetch.finish(taskId); return; }

console.log('[BackgroundFetch HeadlessTask] start: ', taskId); BackgroundFetch.finish(taskId); };`

BackgroundFetch.registerHeadlessTask(onCheckForExpiredLists);

Context

I am attempting to have a notification (notifee) be displayed once a day, depending on condition

Debug logs

christocracy commented 10 months ago

"headless" = terminated.

christocracy commented 10 months ago

Your logs do not show your app operating in the "headless" (terminated) state.

s1tony commented 10 months ago

OK, thank you - I will adjust and test some more.

s1tony commented 10 months ago

Would be willing to share how I might put my app in the headless state so I may test?

On Fri, Jun 23, 2023, 4:40 PM Chris Scott @.***> wrote:

Your logs do not show your app operating in the "headless" (terminated) state.

— Reply to this email directly, view it on GitHub https://github.com/transistorsoft/react-native-background-fetch/issues/454#issuecomment-1605012154, or unsubscribe https://github.com/notifications/unsubscribe-auth/AP57MNOME7JQAULR644SQNTXMYEOHANCNFSM6AAAAAAZSA25DY . You are receiving this because you authored the thread.Message ID: @.*** .com>

christocracy commented 10 months ago

If I asked you to terminate the Twitter app (for example), what would you do?

s1tony commented 10 months ago

That's what I thought - realize it was an obvious question, but when I terminate the app, I don't see anything in the logs indicating this.

On Sat, Jun 24, 2023, 10:15 PM Chris Scott @.***> wrote:

If I asked you to terminate the Twitter app (for example), what would you do?

— Reply to this email directly, view it on GitHub https://github.com/transistorsoft/react-native-background-fetch/issues/454#issuecomment-1605840346, or unsubscribe https://github.com/notifications/unsubscribe-auth/AP57MNPLIHQZCP7PAFROIRDXM6UNRANCNFSM6AAAAAAZSA25DY . You are receiving this because you authored the thread.Message ID: @.*** .com>

christocracy commented 10 months ago

Are you simulating events?

yedi97 commented 10 months ago

@christocracy Hi chris, please tell me, on IOS platform when I close the app, when I reopen the app, will the background task event be fired again? Or do I have to start over?

christocracy commented 10 months ago

will the background task event be fired

what background task event are you referring?

yedi97 commented 10 months ago

what background task event are you referring?

i'm creating a schedule task with name com.transistorsoft.fetchNewData, run every 4 hours, it works fine on IOS if the user doesn't close the app, but I wonder when the user closes the app and reopens it Will my task com.transistorsoft.fetchNewData be reactivated automatically?

christocracy commented 10 months ago

I really don’t know if you have to reschedule it.

why don’t you terminate then try simulating the task to see if it runs?

yedi97 commented 10 months ago

I really don’t know if you have to reschedule it.

why don’t you terminate then try simulating the task to see if it runs?

yes, thank you, i just want to check if it has such a mechanism, i will check it myself

AdnanAshraf-gol commented 7 months ago

@christocracy is there any example for headless task ? or can i get some help ?

am calling the BackgroundFetch.start() on a specific notification here is my index.js


import "react-native-gesture-handler";
import React from 'react';
import ReduxThunk from 'redux-thunk'
import { createStore, applyMiddleware } from 'redux';
import reducers from './src/reducers';
import { Provider } from 'react-redux'
import App from './App';
import { AppRegistry, LogBox, } from "react-native";
import { name as appName } from './app.json';
const store = createStore(reducers, {}, applyMiddleware(ReduxThunk))
LogBox.ignoreLogs(['Warning: ...']);
LogBox.ignoreAllLogs();
import BackgroundFetch from 'react-native-background-fetch';

import axios from "axios";
let MyHeadlessTask = async (event) => {
    // Get task id from event {}:
    let taskId = event.taskId;
    let isTimeout = event.timeout;  // <-- true when your background-time has expired.
    if (isTimeout) {
        // This task has exceeded its allowed running-time.
        // You must stop what you're doing immediately finish(taskId)
        console.log('[BackgroundFetch] Headless TIMEOUT:', taskId);
        BackgroundFetch.finish(taskId);
        return;
    }
    console.log('[BackgroundFetch HeadlessTask] start: ', taskId);
    // Perform an example HTTP request.
    // Important:  await asychronous tasks when using HeadlessJS.
    let response = await fetch('https://reactnative.dev/movies.json');
    let responseJson = await response.json();
    console.log('[BackgroundFetch HeadlessTask] response: ', responseJson);

    // Required:  Signal to native code that your task is complete.
    // If you don't do this, your app could be terminated and/or assigned
    // battery-blame for consuming too much time in background.
    BackgroundFetch.finish(taskId);
}
// Configure background fetch
BackgroundFetch.configure(
    {
        enableHeadless: true,
        forceAlarmManager: true,
        requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY,
        // minimumFetchInterval: 15, // Minimum interval in minutes
        stopOnTerminate: true,   // Keep running in the background
    },
    async (taskId) => {
        console.log('taskId Background fetch executed', taskId)
        // Perform background tasks her
        console.log('Background fetch executed start');
        const data = await axios.get("https://random-data-api.com/api/v2/users");
        console.log('data Background fetch executed', data)
        BackgroundFetch.finish(BackgroundFetch.FETCH_RESULT_NEW_DATA);
        console.log('Background fetch executed end');

    },
    (error) => {
        console.log('[js] Background fetch failed to start', error);
    }
);
BackgroundFetch.registerHeadlessTask(MyHeadlessTask);
const Root = () => (
    <Provider store={store}>
        <App />
    </Provider>
)
AppRegistry.registerComponent(appName, () => Root)
christocracy commented 7 months ago

Learn to Syntax Highlight Multiline Code-blocks

AdnanAshraf-gol commented 7 months ago

Learn to Syntax Highlight Multiline Code-blocks

my bad ! i have updated the comment

christocracy commented 7 months ago

BackgroundFetch.configure must not be placed into index.js. It must be place WITHIN your App code.

AdnanAshraf-gol commented 7 months ago

i have moved the BackgroundFetch.configure to live cycle method of one of my component and restarted the project . still nothing ... it doesnt even console anything related to BackgroundFetch in logcat.

christocracy commented 7 months ago

Are you simulating events? See the readme to learn how.

Are you observing $ adb logcat?

AdnanAshraf-gol commented 7 months ago

yes i observing the $ adb logcat ... but i dont see any logs there related to BackgroundFetch.

christocracy commented 7 months ago

Are you simulating events?

AdnanAshraf-gol commented 7 months ago

Screenshot 2023-10-03 at 10 01 31 AM

This?

christocracy commented 7 months ago

"This" what?

I asked you "are you simulating tasks?".

Or just sitting there at your desk wasting time under an umbrella waiting for it to rain?

AdnanAshraf-gol commented 7 months ago

i dont know what do you mean by "simulating tasks" . But i am following the steps mentioned here and the above screenshot is from the adb logcat *:S ReactNative:V ReactNativeJS:V TSBackgroundFetch:V

christocracy commented 7 months ago

Go read the readme and learn how to simulate events..

You don't test this plug-in by staring quietly at your logs waiting for something to happen.

christocracy commented 7 months ago

Read api docs enableHeadless

AdnanAshraf-gol commented 7 months ago

i have enabled enableHeadless to true

BackgroundFetch.configure({
      stopOnTerminate: false,
      enableHeadless: true,
      startOnBoot: true,
      // Android options
      forceAlarmManager: false,      // <-- Set true to bypass JobScheduler.
      requiredNetworkType: BackgroundFetch.NETWORK_TYPE_ANY, // Default
      requiresCharging: false,       // Default
      requiresDeviceIdle: false,     // Default
      requiresBatteryNotLow: false,  // Default
      requiresStorageNotLow: false,
    }, async (taskId: string) => {
      console.log('[BackgroundFetch] taskId', taskId);
      MyHeadlessTask(taskId)
      BackgroundFetch.finish(taskId);
    }, (taskId: string) => {
      console.log('[Fetch] TIMEOUT taskId:', taskId);
      BackgroundFetch.finish(taskId);
    });

but now am getting this error registerTask failed to find BackgroundFetchConfig for taskId react-native-background-fetch Screenshot 2023-10-03 at 4 57 52 PM

christocracy commented 7 months ago

Yea, fine, and did you Read the api docs about it?! There's far more involved than just setting it true.

github-actions[bot] commented 4 weeks ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 2 weeks ago

This issue was closed because it has been inactive for 14 days since being marked as stale.