How to run background tasks in Expo React Native
June 12, 2020
Expo is a great tool for developing mobile applications with React Native, especially for beginners, but this power has consequences and limits. some features cannot be implemented without detaching from Expo.
Update - December 30, 2021
🚀 Since the release of Expo 42, it has become limitless in the managed workflow.
👉 Check out this example on how to edit Android manifest file in Expo!
In this article, we are going to show the default way to do tasks in the background, without detaching from the expo, and the tricky way using React Native Webview.
Using task manager
To make background tasks work in IOS, we need to add the following configuration to the app.json file:
{
"expo": {
...
"ios": {
"infoPlist": {
"UIBackgroundModes": ["location", "fetch"]
}
}
}
}
Then we have to install the required packages, we use expo install
instead of npm install
to ensure we are installing the versions of the dependencies that are compatible with our Expo SDK.
expo install expo-background-fetch expo-task-manager
Importing our packages:
import * as BackgroundFetch from "expo-background-fetch"
import * as TaskManager from "expo-task-manager"
This way we define our task, it must be outside of any component.
const TASK_NAME = "BACKGROUND_TASK"
TaskManager.defineTask(TASK_NAME, () => {
try {
// fetch data here...
const receivedNewData = "Simulated fetch " + Math.random()
console.log("My task ", receivedNewData)
return receivedNewData
? BackgroundFetch.Result.NewData
: BackgroundFetch.Result.NoData
} catch (err) {
return BackgroundFetch.Result.Failed
}
})
Then we create our task register function which will be called once the main component is mounted.
RegisterBackgroundTask = async () => {
try {
await BackgroundFetch.registerTaskAsync(TASK_NAME, {
minimumInterval: 5, // seconds,
})
console.log("Task registered")
} catch (err) {
console.log("Task Register failed:", err)
}
}
Here is the console output when the application is in the background.
Task registered
My task Simulated fetch 0.722435766683574
My task Simulated fetch 0.7553518044351863
Using webview
In a previous article in dev.to, I already talked about running background audio in React Native specifically Expo using WebView, here is another trick for running background tasks.
Installing webview:
expo install react-native-webview
Create a background-task component:
import * as React from "react"
import { WebView } from "react-native-webview"
function BackgroundTask(props) {
return (
<WebView
onMessage={props.function}
source={{
html: `<script>
setInterval(()=>{window.ReactNativeWebView.postMessage("");}, ${props.interval})
</script>`,
}}
/>
)
}
export default BackgroundTask
Using the background-task component:
import * as React from "react";
import BackgroundTask from "./BackgroundTask";
export default class App extends React.Component {
...
render() {
return (
...
<BackgroundTask
interval={1000}
function={() => {
console.log("My task " + Math.random();
}}
/>
);
}
}
Comparison
Here is what I got while testing the two methods.
Expo background task:
- Works in background
- Works when app closed
- Updates randomly, it does not follow the given interval
- Works in IOS and Android
Webview background task:
- Works in background and foreground
- Does not work when app is closed
- Update regularly following the given interval
- Works in Android but not recent IOS versions
👉 Want to track the GPS position in the background or in the foreground, check out this article.