MAUI 10 and 8 do not correctly handle background task lifecycle
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 290
Description
### Description
While trying to implement a MAUI app with background sync behaviour (using `BGProcessingTaskRequest` in iOS and Workers in Android), I noticed a few issues on iOS (I have not fully tested Android yet).
While Background work triggers correctly when app process is still in memory (not killed or terminated by iOS) these issues exist:
1. If app process is terminated (killed by user, or terminated due to memory constraints), the app correctly receives the scheduled background time but goes through normal app start cycle and never hands the execution to the background task
2. Application goes through most of UI related start ups in above scenario which doesn't make much sense: `CreateWindow` method is called on `App`.
This would basically prevent use of background tasks in iOS (and potentially in Android if similar issue exists there)
### Steps to Reproduce
1. Open the provided repro
2. Run the log server script (`node ./server.js`). This is to allow reliably collect logs from the app while being killed and restarted. Would also allow disconnecting the ipad from mac is you need to, while still collecting logs
3. Check if the log server works: browse to the mac url `http://10.x.x.x:8080` in Safari on ipad and see if the log server prints error relating to parsing JSON. If you see such logs, the server is working
4. Run the app on ipad
5. Check the output of log server.
Normal app start up logs:
```
timestamp | Thread Id | Log Message
-----------------------------------------------------------------------
2026-01-28 12:00:38.219 [1] Finished Launching True
2026-01-28 12:00:38.232 [1] Registered periodic background sync handler
2026-01-28 12:00:38.254 [1] Finished registration of handler
```
6. Move the app to background while ipad is connected to power. **Turn off the screen though**. You should see following log statements:
```
2026-01-28 12:00:41.867 [1] Background task entered: [1]
2026-01-28 12:00:41.873 [1] Periodic background sync scheduled (iOS will decide when to run)
```
7. Wait until you see at least one background sync happening (in my case, despite asking for task to run 1 minute later, iOS runs it ~10min to 30min later). You should see these logs:
```
2026-01-28 12:10:04.097 [13] app - HandleBackgroundTask called
2026-01-28 12:10:04.100 [13] Periodic background sync scheduled (iOS will decide when to run)
2026-01-28 12:10:19.133 [14] Periodic background sync completed successfully
```
This indicates that background tasks work fine when app is in background and process is still alive. You can let this happen multiple times.
8. Now kill the app by swiping the app out of task manager (or recent apps, whatever Apple calls it)
9. turn off ipad screen **while in charge**
10. Wait for about 30 more minutes and you should see the background job triggering again. This time you would see the logs related to app normal start up without the background task being triggered:
```
2026-01-28 12:40:40.314 [1] Finished registration of handler
2026-01-28 12:40:40.316 [1] Finished Launching True
```
Alternatively, you can leave the app intact (not try to swipe it out) and instead open enough other apps until the app process is terminated by iOS.
Expected: after these logs you should see the background job start messages similar to step 7.
Note: I tested on net8 and similarly it doesn't work there either.
### Link to public reproduction project repository
https://github.com/rbakhshi/BugRepro-MAUI10-BGTask-lifecycle
### Version with bug
10.0.30
### Is this a regression from previous behavior?
No, this is something new
### Last version that worked well
Unknown/Other
### Affected platforms
iOS
### Affected platform versions
iOS 15
### Did you find any workaround?
No workaround found.
### Relevant log output
```shell
```
Contributor guide
Research direction
Start with the linked BugRepro-MAUI10-BGTask-lifecycle project and run node ./server.js to reproduce the iOS 15 logs. Compare the normal startup path, including CreateWindow, with the HandleBackgroundTask path after the app process is killed. Done means a scheduled background task is handed to the handler without running the normal UI startup cycle.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, ios
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100