Skip to content

[iOS] JS doesn't keep running in background if it's production build #25083

@craftzdog

Description

@craftzdog

I have an editor app that syncs with server. I would like to keep it running for a few seconds to finish syncing after it becomes inactive in background.
I managed to do that by adding following code to AppDelegate.m:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
  UIBackgroundTaskIdentifier taskId = [application beginBackgroundTaskWithExpirationHandler:nil];
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // do nothing for 4.7 seconds
    [NSThread sleepForTimeInterval:4.7f];
    [application endBackgroundTask:taskId];
  });
}

While it works well in debug build, I encountered that it does not work in production build (TestFlight).
Seems like JS stops immediately after becoming inactive whereas the background task runs as expected on native side.
I suspect it's a bug and tried to fix but couldn't.
Could you help me out? Where should I look into?
I'm happy to contribute.

React Native version: 0.59.2

react-native info
info
  React Native Environment Info:
    System:
      OS: macOS 10.14.5
      CPU: (8) x64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
      Memory: 21.46 GB / 56.00 GB
      Shell: 3.0.2 - /usr/local/bin/fish
    Binaries:
      Node: 11.12.0 - ~/.nvm/versions/node/v11.12.0/bin/node
      Yarn: 1.13.0 - /usr/local/bin/yarn
      npm: 6.9.0 - ~/.nvm/versions/node/v11.12.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
      Android SDK:
        API Levels: 22, 23, 25, 26, 27, 28
        Build Tools: 23.0.1, 25.0.2, 26.0.1, 26.0.3, 27.0.3, 28.0.3
        System Images: android-22 | Google APIs Intel x86 Atom, android-26 | Google Play Intel x86 Atom, android-27 | Google APIs Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-Q | Google Play Intel x86 Atom
    IDEs:
      Android Studio: 3.4 AI-183.6156.11.34.5522156
      Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
    npmPackages:
      react: 16.8.3 => 16.8.3
      react-native: 0.59.2 => 0.59.2
    npmGlobalPackages:
      react-native-cli: 2.0.1

Steps To Reproduce

  1. Implement a background task in your AppDelegate.m:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
  UIBackgroundTaskIdentifier taskId = [application beginBackgroundTaskWithExpirationHandler:nil];
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [NSThread sleepForTimeInterval:4.7f];
    [application endBackgroundTask:taskId];
  });
}
  1. Add a following code to your App.js:
AppState.addEventListener('change', (nextAppState) => {
    if (nextAppState === 'background') {
      setTimeout(() => {
        fetch('<Somewhere you can watch requests>')
      }, 2000)
    }
})
  1. Replace <Somewhere you can watch requests> with a proper URL

Make sure App Transport Security Settings is correctly configured if the URL is not HTTPS.

  1. Run it via TestFlight

Describe what you expected to happen:

It issues a HTTP request after 2 seconds when going to background.

Thanks in advance!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions