Rapsssito / react-native-background-actions

React Native background service library for running background tasks forever in Android & iOS.
MIT License
818 stars 117 forks source link

react-native-background-actions prevent the app from closing by user on Android 10 #114

Closed alexfov closed 2 years ago

alexfov commented 2 years ago

Hello and thank you for such a nice library. I faced a problem on Android. When I use background task, and then close my app it doesn't closes actually despite it is absent in the opened apps list. When I open the app again it starts with the last state that was before closing.

import React, { useEffect } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import SplashScreen from 'react-native-splash-screen';
import BackgroundService from 'react-native-background-actions';

const sleep = (time) => new Promise((resolve) => setTimeout(() => resolve(), time));

const veryIntensiveTask = async (taskDataArguments) => {
  // Example of an infinite loop task
  const { delay } = taskDataArguments;
  await new Promise(async (resolve) => {
    for (let i = 0; BackgroundService.isRunning(); i++) {
      console.log(i);
      await sleep(delay);
    }
  });
};

const options = {
  taskName: 'Example',
  taskTitle: 'ExampleTask title',
  taskDesc: 'ExampleTask description',
  taskIcon: {
    name: 'ic_launcher',
    type: 'mipmap',
  },
  color: '#ff00ff',
  linkingURI: 'yourSchemeHere://chat/jane', // See Deep Linking for more info
  parameters: {
    delay: 1000,
  },
};

let i = 0;
export default function App() {
  useEffect(() => {
    SplashScreen.hide();
  }, []);

  useEffect(() => {
    BackgroundService.start(veryIntensiveTask, options);
    return () => {
      BackgroundService.stop();
    };
  }, []);

  useEffect(() => {
    i++;
    console.log({ i });
  }, []);

  return (
    <View style={st.container}>
      <Text />
    </View>
  );
}

const st = StyleSheet.create({
  container: { flex: 1 },
});

On first open I see i = 1. Then I close the app and open it again and see i = 2, then i = 3 etc... This leads to several time redux-saga initialization and multiple queries.

"react-native": "^0.64.2", "react": "^17.0.2", "react-native-background-actions": "^2.6.5",

Android 9, 10 BlackView 5900, Xiaomi Redmi Note 7

clgh0331 commented 2 years ago

i have same issue..

clgh0331 commented 2 years ago

I sorved this problem if (!BackgroundService.isRunning()) { await BackgroundService.start(veryIntensiveTask, options); }

alexfov commented 2 years ago

It doesn't help for me. As workaround I use this:

useLayoutEffect(() => {
    i++;
    console.log({ i });
    if (i > 1) CodePush.restartApp();
  }, []);
clgh0331 commented 2 years ago

Sorry, I misunderstood. But, I don't have such issues

Rapsssito commented 2 years ago

@alexfov, this is the expected behavior. However, I believe React Native allows you to listen for app state changes, so you can close the task when the app is being closed.

alexfov commented 2 years ago

@Rapsssito as you can see in the 1st post I use stop() method inside useEffect. If I add log to the promise result I can see that task is stopped. Also I added BackgroudService.isRunning() before starting task and it says that there is no active task. And notification disappears when the app is closed. So I can infer that there is no background tasks when app is closed.

Rapsssito commented 2 years ago

@alexfov, the issue is that when you open the app, it starts counting from when it stopped?

alexfov commented 2 years ago

@alexfov, the issue is that when you open the app, it starts counting from when it stopped?

Not counting itself. The issue is several times redux-saga initialization. So when I dispatch an action that makes a network request I get multiple queries. It is the first issue that I noticed. I'm sure there are others.

App opened 1st time - normal behavior, 1 dispatch - 1 query. App opened 2nd time - 1 dispatch - 2 queries. App opened 3rd time - 1 dispatch - 3 queries. And so on.

It is strange, because I haven't active background actions when app is closed. Log says that task is terminated.

useEffect(() => {
   console.log(BackgroundService.isRunning()); //false
    BackgroundService.start(veryIntensiveTask, options);
    return () => {
      BackgroundService.stop().then(()=> console.log("task is terminated"));
    };
  }, []);
Rapsssito commented 2 years ago

@alexfov, I am sorry, I am not familiar with redux-saga. I guess that React hook is only called once and the veryIntensiveTask does not dispatch several queries. I am sure no background task is running after restarting the app because I have tried to implement it (#43).

The only thing I can think of is some kind of cache/batch/concatenation of queries. Sorry, but I can't help you anymore with this.

alexfov commented 2 years ago

@Rapsssito could you explain why the app starts from previous state, when using this lib?

alexfov commented 2 years ago

Ok it's because BackgroundService doesn't stopped actually. If you stop it when an app is still opened there is no the issue. It seems like we can't know and use a callback when a user closes an app

Rapsssito commented 2 years ago

@alexfov, I am sorry, but background tasks are heavily managed by the OS. Each Android flavor has its own battery management rules and can cause incoherence between devices. If the user closes the app manually from the "open apps" is highly possible that the background task will also be killed.

I don't know why the app is starting from a previous state, for more info you may take a look at the docs for Headless JS in React Native. Also, make sure your AndroidManifest.xml is set to android:launchMode="singleTask": https://github.com/Rapsssito/react-native-background-actions/blob/cfbb451813f61ba9ddab71f9486b755bb6f2ed9d/examples/backgroundExample/android/app/src/main/AndroidManifest.xml#L20