transistor-background-fetch
transistor-background-fetch copied to clipboard
fix: impossible to configure task if previous task has call stop(). (Android + Headless)
I noticed that in my app: IF
- I
configure()a background-task - I run this task when my app is killed (using react-native headless)
- I re-open my app and reconfigure a new task
THEN
- The second background task is not properly configured and not run properly
Reproducing the bug
I created a simple react-native app with minimal code to reproduce the bug https://github.com/ACHP/rn-background-fetch-bug-repro
Run the app using react-native (checkout + yarn + yarn start + yarn android)
- Then click on the blue "Register background fetch" button. (This will register a background task)
- Then you can kill your app and run the background task with
adb shell cmd jobscheduler run -f com.rnbgfetchbugrepro 999- You should see a logger in the metro console indicating the task started, stopped, and finished.
- Then re-open the app and re-click the button
- Re-kill your app and re-run the headless task with
adb shell cmd jobscheduler run -f com.rnbgfetchbugrepro 999- You should now see an error in the logcat console
[BGTask] failed to load config for taskId: react-native-background-fetch
- You should now see an error in the logcat console
Video of this process
https://github.com/user-attachments/assets/86a1d6b3-35c9-4115-92ae-fbb19bd82faf
What is happening
From my research, I noticed that the second time we register the background task, it is not properly saved into the shared-preferences (We can see it in the video). This happens because on this line, the mConfig hashmap still contains the taskId when we relaunch the app the second time.
https://github.com/transistorsoft/transistor-background-fetch/blob/7ad81a8fca982c4e7a2abcce440fb2d36716b207/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java#L88
And the hashmap still contains the taskId because when we call stop(), it clean the shared-preferences, but not the mConfig hashmap.
https://github.com/transistorsoft/transistor-background-fetch/blob/7ad81a8fca982c4e7a2abcce440fb2d36716b207/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java#L146-L170
That is why we see a Re-configured existing task, instead of a fresh "configure".
Then when we try to run the background task, it loads the config from the shared-preference, but it can't find nothing. So it fails with [BGTask] failed to load config for taskId: react-native-background-fetch
Suggestion
We should probably clear the mConfig object when we stop the backgroundTask, so that there is no "desynchronisation" between the sharedPreference
Have you actually tested this?
TBH I tested by hand only 2 scenarios:
- When the task is stopped() from background => We should be able to call configure() again and expect it to work
- When the task is stopped() from headless => We should be able to call configure() again and expect it to work
Here is a video where we see these 2 scenarios seems to works
https://github.com/user-attachments/assets/cd6fed30-5289-44f4-bbe2-b82d37dedbfe
I imported the module via android studio and the implementation(group: 'com.transistorsoft', name:'tsbackgroundfetch', version: '+') by implementation project(":tsbackgroundfetch") in order to test.
I didn't test using the schedule instead of the configure()
@christocracy Have you had a chance to review this PR? It's not urgent since we're currently using a patch, but if there are any major issues with my fix or if I overlooked something that makes the pull request unnecessary, I'd appreciate your feedback.
Hello @christocracy, could you please take a moment to review this pull request ? Maybe I'm missing something and all this is not necessary, but if that is the case I'd like to know what I missed and we can close it.
I've described the issue and investigate it as much as I could and done a minimal reproduction example to make it easy to try.