Background Tasks

RSS for tag

Request the system to launch your app in the background to run tasks using Background Tasks.

Posts under Background Tasks tag

140 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Background Tasks Resources
General: DevForums tag: Background Tasks Background Tasks framework documentation UIApplication background tasks documentation ProcessInfo expiring activity documentation watchOS background execution documentation WWDC 2020 Session 10063 Background execution demystified — This is critical resource. Watch it! WWDC 2022 Session 10142 Efficiency awaits: Background tasks in SwiftUI iOS Background Execution Limits DevForums post UIApplication Background Task Notes DevForums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
3.0k
Jun ’22
App cannot fetch any resource after a while
Hi everyone, We came an issue that, In some scenarios in our app we cannot fetch any resources from device (Photo and Contact). One case we catched is putting app in background and spending time in other commonly used apps and coming back to our app cause this issue but there is a small chance that get this issue during using the application. In cell, we are trying to fetch the image like this imageFetchTask = Task { let image = await CompositionRoot.shared.photosManager.image(requestType: .imageCollections, forId: photoAsset.photoId) self.photoImageView.image(image) } and inner layers of this code we get the PHAsset and request image PHAsset.firstAsset(for: id) let manager = PHImageManager.default() manager.requestImage(for: asset, targetSize: request.targetSize, contentMode: .aspectFill, options: request.options) { (image, info) in continuation.resume(returning: image) } We figured out that issue not happening only in Photos also Contacts and any web request. So any help according to this situation is well appreciated. Thanks
0
0
4
31m
WidgetCenter.shared.reloadAllTimelines() doesnt work when app in background
I have an iOS app, watchOS app, and iOS Widget that shows the most recent data in the database. The watch app sends data to the iOS app over the WCSession and is received in session(didReceiveMessage, replyHandler). After that data is processed, reloadAllTimelines() is called. When running in Simulator or on device plugged in to debugger, it works, the widget updates when the app is closed (in background, even if force quit). But when running TestFlight or App Store build, the data is still processed and saved to Core Data (I open the app and it's there), but the widget doesn't update. It seems that reloadAllTimelines only works when the app is in foreground (at least in non debug builds). I dont have an iOS 17 device to check but I think this is a recent bug with iOS 18.
1
1
73
13h
App rejected guidelines performance 2.5.4 - UIBackgroundModes
Hi everyone, I’m encountering a recurring issue with my app submission, and I’d appreciate your insights. My app has been rejected due to Guideline 2.5.4 with the following feedback: Guideline 2.5.4 - Performance - Software Requirements The app continues to declare support for location in the UIBackgroundModes key in your Info.plist file but we are unable to locate any features besides employee tracking that require persistent location. Using the location background mode for the sole purpose of tracking employees is not appropriate. Please note we located the features of the app but the location background tracking of employees is not appropriate with this guideline. Next Steps If the app has a feature besides tracking employees that requires persistent location, reply to this message and let us know how to locate this feature. Otherwise, it would be appropriate to revise the app to include additional features for your users that require the persistent use of real-time location updates while the app is in the background My App’s Use Case: The app is designed to support events where users can check in and check out. Persistent location tracking is essential for the following: 1. During Events: • Tracking users’ real-time location ensures they remain within the event boundaries. • If a user exits the designated area, the system logs the occurrence for compliance and security purposes. 2. Workforce Monitoring: • For work events, the app records working hours based on their presence within the event area. • This ensures accurate logging of attendance and work durations. Steps I’ve Taken: • Limited Scope of Tracking: Persistent location tracking is active only during event check-in and check-out periods. Outside of these periods, tracking is disabled. • User Consent: I’ve implemented clear permission requests and a privacy policy to explain how location data is used. • Info.plist Configuration: I’ve declared the UIBackgroundModes key with location to support background tracking. Despite these measures, my app continues to be rejected with the feedback above. I believe my app’s features align with the guidelines as the location tracking is directly tied to event functionality and user benefit. Questions: 1. How can I better explain this use case to Apple’s review team to demonstrate compliance? 2. Are there any additional features or adjustments I should consider to ensure my app meets the guidelines? 3. Has anyone faced a similar issue with persistent location tracking, and how did you resolve it? Thank you for your guidance and support!
1
0
111
3d
Speech synthesis from Safari app extension
I'm making a Safari extension for learning languages. I need speech synthesis for any language the user chooses to learn. I initially tried to make this work within JavaScript, but Safari 18 doesn't reliably list voices for all languages on the web SpeechSynthesis API as described here: https://stackoverflow.com/questions/79179072/how-do-you-use-a-japanese-voice-with-speechsynthesis-in-safari-ios-18 As a workaround, I've had to use AVSpeechSynthesizer in SafariWebExtensionHandler (NSExtensionRequestHandling implementation for the extension). This works in the simulator but not on a real device. I've found this note from Apple in a StackOverflow reply: "Safari extensions are very short-lived, hence not fit for audio playback or speech synthesis. Not being able to validate an app extension in Xcode with a manually-added plist entry for background audio is the designed behavior. The general recommendation is to synthesize speech using JavaScript in conjunction with the Web Speech API." Unfortunately, the suggestion to use the Web Speech API is unsuitable as I just explained. Is there a way to set up a background process in the host app that can do speech synthesis? The app extension would need a way to communicate with this process, and start it if it's not running. Is that possible?
0
0
109
5d
How can I keep my app up to date with the server without throttling
I am trying to build a chat app. I am using FCM to deliver messages to my app accompanied by some custom data like the new message_data, deleted message_id and so on; each message will need to run the app in the background to do some background processing and local database syncing. This continuous background processing is clearly not acceptable as APNs imposes a per-device limit on background push notifications . I am asking how can I push messages and actions payload without being throttled ?
2
0
121
1w
Are some backgrounded apps allowed to record phone calls but not others?
It’s been established that generally speaking background apps cannot record audio while the foreground app is already reading audio data from the microphone, but are there exceptions? For instance, is there an exception for certain Apple apps? If so, and there’s a special exception that most programmers don’t know about but some Apple’s engineers do and perhaps some hackers do as well, wouldn’t the mechanism that allows that eventually be exploited?
0
0
178
1w
Background Task Scheduling (BGAppRefreshTask)
All the nuances of when and whether a background task runs aside, does launching the app cancel the currently scheduled refresh task? As an example, consider the following case: 8AM - user launches app. This launch schedules a background refresh for 12 hours later, at 8PM 12PM (noon) - user launches the app, views some content, then exits the app. Does the scheduled refresh for 8PM still exist, or does the launch at noon invalidate that task, since the refresh could conceivably be handled during that noon launch? Hopefully this is articulated clearly enough, but I'm trying to understand the specifics of background refresh behavior, since I don't want to run that refresh every time the app is opened. However, if opening the app invalidates scheduled refreshes, I will need to include logic that will reschedule the refresh accordingly.
2
0
152
2w
Refreshing widgets - policy and background tasks?
I have widgets providing their timeline using the .atEnd reload policy, i.e.: // AppIntentTimelineProvider: return Timeline(entries: entries, policy: .atEnd) // TimelineProvider let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) I can't seem to find any information on what happens after the end of the timeline. So, let's say I've got two days worth of entries, the dev docs for the reload policy say, "A policy that specifies that WidgetKit requests a new timeline after the last date in a timeline passes." Great! But how does it request the new timeline? Does iOS launch my app in the background and simply re-run the timeline to generate another two days worth of entries? I doubt it. I figure I need to implement some sort of background task, and the dev docs say how to do it with an Operation, but then I read that this is an old way of doing it? I've found some info online saying to use something like this, so this is what I've implemented: let kBackgroundWidgetRefreshTask = "my.refresh.task.identifier" // This has been registered in the info.plist correctly class SchedulingService { static let shared = SchedulingService() func registerBackgroundTasks() { let isRegistered = BGTaskScheduler.shared.register(forTaskWithIdentifier: kBackgroundWidgetRefreshTask, using: nil) { task in print("Background task is executing: \(task.identifier)") // This does print "true" self.handleWidgetRefresh(task: task as! BGAppRefreshTask) } print("Is the background task registered? \(isRegistered)") } func scheduleWidgetRefresh() { let request = BGAppRefreshTaskRequest(identifier: kBackgroundWidgetRefreshTask) // Fetch no earlier than 1 hour from now - test, will be two days request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60) do { try BGTaskScheduler.shared.submit(request) print("Scheduled widget refresh for one hour from now") } catch { print("Could not schedule widget refresh: \(error)") } } private func handleWidgetRefresh(task: BGAppRefreshTask) { // Schedule a new refresh task scheduleWidgetRefresh() // Start refresh of the widget data let refreshTask = Task { do { print("Going to refresh widgets") try await self.backgroundRefreshWidgets() task.setTaskCompleted(success: true) } catch { print("Could not refresh widgets: \(error)") task.setTaskCompleted(success: false) } } // Provide the background task with an expiration handler that cancels the operation task.expirationHandler = { refreshTask.cancel() } } func backgroundRefreshWidgets() async throws { print("backgroundRefreshWidgets() called") definitelyRefreshWidgets() } } As I've commented above, the line print("Background task is executing: \(task.identifier)") does print true so the task has been registered correctly. I've put the app into the background and left it for hours and nothing is printed to the console. I've implemented a logger that writes to a file in the app container, but that doesn't get anything either. So, is there something I'm misunderstanding? Should I change the reload policy to .after(date)? But what makes the timeline reload? As a second but linked issue, my widgets have countdown timers on them and the entire timeline shows that every entry is correct, but the widgets on the Home Screen simply fail to refresh correctly. For example, with timeline entries for every hour for the next two days from 6pm today (so, 7pm, 8pm...) every entry in the preview in Xcode shows the right countdown timer. However, if you put the widget on the Home Screen, after about five hours the timer shows 25:12:34 (for example). No entry in the timeline preview ever shows more than 24 hours because the entires are every hour, and the one that shows a timer starting at 23:00:00 should never get to 24:00:00 as the next entry would kick in from 0:00:00, so it should never show more than 23:59:59 on the timer. It's like the 23:00:00 timer is just left to run for hours instead of being replaced by the next entry. It's as though the widget isn't refreshing correctly and entries aren't loaded? Given this is the Simulator - and my development device - and both are set to Developer Mode so widget refresh budgets aren't an issue, why is this happening? How do you get widgets to refresh properly? The dev docs are not very helpful (neither is the Backyard Birds example Apple keep pushing). Thanks!
5
0
241
1w
How to implement continuous speech recognition in the background?
Hi, I'd like to develop an app which runs speech recognition even after going into background. I know I can accomplish this using audio background mode and the process the audio but I am not sure if this workaround would get accepted into App Store because of the processing limitations while in the background. How can I accomplish this while still being compliant with Apples privacy policy and other restrictions? Thanks, Marek
0
0
141
2w
Core Data and Background Tasks
Hello, our application works with Core Data to save some datas about its activity. We have background Tasks implemented and our app execution in background shows this error message in the Logs: error: Failed to acquire background task assertion for task 'CoreData: Executing write request'. Anyone could explain what this message means? Could it be that NSManagedObjectContext changes might not be written?
1
0
187
2w
Inconsistance interval between background task execution
I have a use case in my app where I need to call an API from the device every 30 minutes to verify the app state. In certain cases, the backend records the time of the last received API call or observes the absence of an API call for business logic, making it crucial that the call is executed at fixed intervals. I am using React Native to build the app and the react-native-background-fetch package to create the background task. As I understand it, the package uses the Background Fetch API under the hood. From what I have observed and read from other sources so far, there is no guarantee that the task will run every 30 minutes. Is there any way to make the background task more consistent, or is there a better approach to achieve this objective on iOS?
2
0
156
2w
Notifications on iOS sourced from a machine on an offline local network
We have a device which is an appliance and we are developing a control interface app for macOS and iOS/iPadOS. How can we set up our iOS application to grab information from a local network device while it is in the background in order to show notifications? Communication between the Apple device and our device is via local networking and the device is designed to be used on networks without internet connections. On networks with internet connections we could forward events from the device, via a server and APNS push notifications, but that isn't valid here. Events occur on our device and are forwarded to clients, who are subscribed to Server-Sent Events. On macOS this works well and the application can receive updates and show Notification Center notifications fine. On iOS we are using a BGAppRefreshTaskRequest with time interval set to 1 minute, but it appears that we get scheduled only every few hours. This isn't very useful as notifications just arrive in batches rather than in a timely manner. All normal networking is closed when the app goes into the background, so we cannot keep the SSE request open. Another idea which we haven't tried yet: Creating a new endpoint on the device which keeps the connection open until a notification arrives, then using background URLSession to poll on that endpoint. Would that work? It seems like a mis-use of the API perhaps?
9
0
237
2w
Background Task Execution - Doesn't Seem Consistent
I have an app, that when enters the background schedules a task to run. The earliest possible time value is set, as is the completion handler when the task eventually runs. It seems to run pretty reliably for the 1st few interations and then (from looking at the streaming Console logs), doesn't seem to reach a high CP score to execute next time around. eg '......background.task:EDBC23' CurrentScore: 0.648418, ThresholdScore: 0.808034 DecisionToRun:0 looking at the previous entries before this, I can see the breakdown... {name: Application Policy, policyWeight: 50.000, response: {0, 0.35}} {name: Device Activity Policy, policyWeight: 5.000, response: {0, 0.50}} ], Decision: CP Score: 0.648418} and I understand certain elements are outside of our control; however, is there a preferred method to get a background task (which ultimately runs an API call) to trigger consistently? The silent-push method has come up a few times - but of course, if the user disables / doesn't consent to push notifications, that fails Any suggestions?
1
0
158
3w
How to start and automatically update/end a local live activity?
I'm implementing a timer feature and facing the issue that the live activity I'm starting just continues showing after the timer is complete. The body of the live activity widget is more or less: ActivityConfiguration(for: WhendyWidgetAttributes.self) { context in VStack { Text( context.state.timerEndDate, style: .timer ) // if Date.now < timerEndTime { Text("Done") } self.expandedView(state: context.state) } } … Ideally I could get the activity to show something else when it is done but I don't know how to get it to re-evaluate it's body once the end time is reached. I create the activity with let activity = try ActivityKit.Activity.request( attributes: attributes, content: .init( state: .init(timerEndDate: timerEndDate), staleDate: timerEndDate ), pushType: nil ) Can I schedule the activity to do a refresh it's body (and reevaluating Date.now) once the timerEndDate is reached? Considered Approaches trying staleDate However, the activity never shows that it has become stale. Would it be expected that it shows the stale-ness? scheduling dismissal I also thought about starting and immediately stopping the activity with a delayed dismissal, but unfortunately it seems this is limited to a 4 hour window, and I'd like longer timers too. remote updates I understand I could use remote notifications to update the live activity, but I'd really like to keep things local as all the functionality is locally plannable. Background Tasks I understand these don't run reliably or at a predictable time. A Timer in the app that updates the content I think this would only update the activity while the app is in foreground.
0
0
123
3w
swift DeviceActivityReport run in background
DeviceActivityReport presents statistics for a device: https://developer.apple.com/documentation/deviceactivity/deviceactivityreport The problem: DeviceActivityReport can present statistics with a delay for a parent device (when DeviceActivityReport is presenting, the DeviceActivityReportExtension is called to process the statistics). One possible solution is to call DeviceActivityReport periodically throughout the day in a child device. However, the app will not be available all day. Is there any way to run DeviceActivityReport in the background? I have tried the following approach, but it didn’t work (DeviceActivityReportExtension didnt call): let hostingController: UIHostingController? = .init(rootView: DeviceActivityReport(context, filter: filter)) hostingController?.view.frame = .init(origin: .zero, size: .init(width: 100, height: 100)) hostingController?.beginAppearanceTransition(true, animated: false) hostingController?.loadView() hostingController?.viewDidLoad() try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewWillAppear(true) hostingController?.viewWillLayoutSubviews() try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewDidAppear(true) try? await Task.sleep(for: .seconds(0.5)) hostingController?.didMove(toParent: rootVC) try? await Task.sleep(for: .seconds(0.5)) hostingController?.viewWillLayoutSubviews() hostingController?.viewDidLayoutSubviews() hostingController?.view.layoutIfNeeded() hostingController?.view.layoutSubviews() hostingController?.endAppearanceTransition() Is there any way to run DeviceActivityReport in the background? (when app is not visible/closed). The main problem is call DeviceActivityReport
0
0
198
Nov ’24
Notification Received in Kill Mode but No Method Invoked in iOS
Hello Apple Developer Team, I am facing an issue with remote notifications in my iOS app. When the app is in a terminated (kill) state, notifications are successfully received by the device, but none of the app's handlers (like _firebaseMessagingBackgroundHandler in Flutter) are invoked. This is impacting our ability to process silent notifications or perform background tasks reliably when the app is not running. Steps to reproduce: Send a remote notification with content-available: 1 in the payload. Confirm the notification is received by the device while the app is in kill mode. Observe that no background or foreground notification methods are triggered in the app. Expected Behavior: The app should invoke the background handler to process the notification payload, even in a terminated state. Observed Behavior: The notification is delivered to the device, but no app-level processing occurs because none of the methods are triggered. Can you please confirm if this is the intended behavior due to iOS limitations, or if there is a configuration or alternative solution to allow background handlers to execute in such scenarios? Any guidance or clarification would be highly appreciated. Thank you!
1
0
180
Nov ’24
Background update home widget iOS
The application was initially written in Swift, and we released an update where the app was rewritten in Flutter. Currently, we are adding a widget natively written in SwiftUI to the Home screen. The widget updates are managed by BGTaskScheduler. In BGTaskScheduler, an API request is made to fetch the latest data. The data is then processed to calculate an average value, which is subsequently sent to UserDefaults. The widget displays data fetched from UserDefaults. The minimum update interval is set to 30 minutes. When testing the widget updates through a build in Xcode, the widget updates as expected at the specified interval. However, when this build was provided to users via TestFlight, the widget does not update for them. Could this issue be related to TestFlight’s resource limitations? Is there any guarantee that releasing this version will ensure the widget updates correctly for users?
2
0
295
Nov ’24
Background fetching data not work
Hello, I have a some problem with background fetch. In my app I use background modes for fetch data and display on my home widget iPhone. Its working correct when I built app on my phone from Xcode but when I distribute my app on TestFlight my home widget not updating at all. Help me understand if this issue is only due to TestFlight resources, or should I try releasing the app and hope that it will work in the release version?
1
0
336
Nov ’24
UserDefaults.standard.set() shows warning, but it can not be acted upon?
We run simple iOS Swift code triggered by a remote notification: UserDefaults.standard.set("key", forKey: "value") It runs fine when the app is active or inactive, but when the device is closed/locked and the code is triggered, we see a warning in Xcode: Couldn't write values for keys ( key ) in CFPrefsPlistSource&lt;0x3018802d0&gt; (Domain: com.example, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): Path not accessible Not updating lastKnownShmemState in CFPrefsPlistSource&lt;0x3018802d0&gt; (Domain: com.example, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): 767 -&gt; 767 The issue is that there seems to be no way to catch that warning. The value is set, when it's re-read the value is correct. But the value is never written to disk, so after an app restart/update the value is gone, potentially has an old wrong value. This code runs without any interruption, it's just showing the warning on iOS 17.7.1 on iPad: UserDefaults.standard.set("key", forKey: "value") UserDefaults.standard.synchronize() print("value: \(UserDefaults.standard.string(forKey: "key"))") Should there not be a way to catch this, so the code can act accordingly to the circumstances? It would be good to know inside the code that the value is not persisted. I would expect that an exception is generated somewhere which can be caught. It seems .completeFileProtectionUntilFirstUserAuthentication enables files to be written to disk while the device is closed/locked, can something similar be used for UserDefaults.standard?
1
0
255
Nov ’24
Background Tasks runs foreground
Hello everyone! I'm having a problem with background tasks running in the foreground. When a user enters the app, a background task is triggered. I've written some code to check if the app is in the foreground and to prevent the task from running, but it doesn't always work. Sometimes the task runs in the background as expected, but other times it runs in the foreground, as I mentioned earlier. Could it be that I'm doing something wrong? Any suggestions would be appreciated. here is code: class BackgroundTaskService { @Environment(\.scenePhase) var scenePhase static let shared = BackgroundTaskService() private init() {} // MARK: - create task func createCheckTask() { let identifier = TaskIdentifier.check BGTaskScheduler.shared.getPendingTaskRequests { requests in if requests.contains(where: { $0.identifier == identifier.rawValue }) { return } self.createByInterval(identifier: identifier.rawValue, interval: identifier.interval) } } private func createByInterval(identifier: String, interval: TimeInterval) { let request = BGProcessingTaskRequest(identifier: identifier) request.earliestBeginDate = Date(timeIntervalSinceNow: interval) scheduleTask(request: request) } // MARK: submit task private func scheduleTask(request: BGProcessingTaskRequest) { do { try BGTaskScheduler.shared.submit(request) } catch { // some actions with error } } // MARK: background actions func checkTask(task: BGProcessingTask) { let today = Calendar.current.startOfDay(for: Date()) let lastExecutionDate = UserDefaults.standard.object(forKey: "lastCheckExecutionDate") as? Date ?? Date.distantPast let notRunnedToday = !Calendar.current.isDate(today, inSameDayAs: lastExecutionDate) guard notRunnedToday else { task.setTaskCompleted(success: true) createCheckTask() return } if scenePhase == .background { TaskActionStore.shared.getAction(for: task.identifier)?() } task.setTaskCompleted(success: true) UserDefaults.standard.set(today, forKey: "lastCheckExecutionDate") createCheckTask() } } And in AppDelegate: BGTaskScheduler.shared.register(forTaskWithIdentifier: "check", using: nil) { task in guard let task = task as? BGProcessingTask else { return } BackgroundTaskService.shared.checkNodeTask(task: task) } BackgroundTaskService.shared.createCheckTask()
1
0
279
Nov ’24