I'm building a Pomodoro app and I want the timer to continue counting down even when the user locks the screen or moves the app into the background. Once the timer hits 0, it plays a custom audio file of the user's choosing.
I have this functionality working in the app itself, but I need it to work when the app is placed in the background, or when the user locks their screen (similar to the alarm app that comes installed on android phones). However, I can't seem to get a background task to run at all.
My plan was to register my background task (which would just be a setInterval timer that played an alarm when the timer hit zero) whenever the user minimized the app. I created a dummy background task, but I can't get it to run at all.
const BACKGROUND_TASK_INDENTIFIER = "background-task";
TaskManager.defineTask(BACKGROUND_TASK_INDENTIFIER, async () => {
const status = await BackgroundTask.getStatusAsync()
console.log("Executing background task", status)
return setTimeout(() => console.log("Status of Background task ", status), 3000)
})
async function registerBgTask(){
return BackgroundTask.registerTaskAsync(BACKGROUND_TASK_INDENTIFIER)
}
async function unregisterBgTask(){
return BackgroundTask.unregisterTaskAsync(BACKGROUND_TASK_INDENTIFIER)
}
// inside component
useEffect(() => {
const subscription = AppState.addEventListener("change", async (state) => {
if (state === "background") {
console.log("registering task...")
await registerBgTask() // the code in my task here doesn't run
} else {
console.log("unregistering task...")
await unregisterBgTask()
}
})
return () => subscription.remove()
}, [])
If possible, I'd like to know why the task isn't running, as well as how I can fix this problem.
Registering a task does not mean that this task is now running in the background. It only makes the task available for triggering within the app. You need to "activate" the task for example with Expo-Locations or Expo-BackgroundFetch.
For your example i think the best way is to schedule a Notification. Here a example code (you can set custom sound):
await Notifications.scheduleNotificationAsync({
content: {
title: "You've got mail! 📬",
sound: 'mySoundFile.wav', // Provide ONLY the base filename
},
trigger: {
type: Notifications.SchedulableTriggerInputTypes.TIME_INTERVAL,
seconds: 2,
channelId: '...',
},
});
(For Android you need to define a channel!)