Hello Community,
Need your help/guidance please. Seeking LocationServices experts who can advise me whether my idea for a valuable add-on feature that I've been trying to add into my app for 2+ months is achievable or not given LocationServices limitations.
The Feature: to enable users who would like to be automatically notified whenever they're within X meters from a store that provides them an exclusive discount BUT only when they choose to be notified. Instruction to enjoy the feature is by keeping app open in 'background state' (means opened and kept in background) but not when app is terminated state (completely closed).
The state is important because I would like to give users the choice to only receive notifications when they choose to instead of all-time. That is to eliminate unnecessary power consumption fetching location updates constantly when user don't need them (example staying at home, at work, etc), but give them option when they go out.
Ideal scenario (after opting in to enable 'Always'): user launches the app, keeps in background, go out shopping/dining/etc and enjoy convenience of being automatically notified whenever about Xmeters from a place that they have an exclusive offer for.
Implemented conditions:
API is called at fixed time interval whenever user is within about 10 meters from their last location, that is to limit checking only when there is certainty user is within the same place for sometime instead of just walking by (this currently works perfectly, using AccuracyBest),
the challenge when user terminates app, LocationServices wakes up again and continues to fetch location updates constantly.
The Ask:
Is it technically possible that I configure app LocationServices to not wake-up with [AccuracyBest] when terminated but instead use only reduced accuracy (like 'significant location updates' or on 'AccuracyOne/ThreeKilometer')?
Ideas/suggestions/recommendations would be much much appreciated
Background Tasks
RSS for tagRequest the system to launch your app in the background to run tasks using Background Tasks.
Posts under Background Tasks tag
132 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I would like to call a "GetMessages" API every 10 minutes while the app is not active or shutdown.
if a message is returned, display the message as a local notification
Will the background api run if the app is shut down?
An example of this is when an email app shows a notification. Can they pull from their server while the app is not running or do they use the push notification service.
I know that calendar events can be scheduled locally and for location changes, but I don't know if calling a api task with the app not running is possible.
I'm working on an in-house iOS app designed to help users accurately track their routes during trips. Currently, I've implemented a method to track users when the app is open in the background. However, I'm facing challenges, as the tracking stops when the device is locked for more than 10 minutes.
I'm looking for a solution to continuously track a user's geolocation, even if the app is closed or not in use. Specifically, I want to ensure uninterrupted tracking, especially when the device is locked.
Here are some key points:
Current Method: I'm currently using the Core Location method and a combination of background tasks and a repeating timer to fetch the user's location and update a log for geolocation tracking when the app is open in the background.
Issues Faced: The tracking stops when the device is locked for more than 10 minutes. This limitation impacts the accuracy of the route tracking during longer trips.
Objective: My goal is to achieve continuous geolocation tracking, even when the app is closed or not actively used, to provide users with a seamless and accurate record of their routes.
Platform: The app is developed for iOS using the .net maui platform, and I'm seeking solutions or suggestions that are compatible with the iOS .net maui environment.
If anyone has experience or insights into achieving continuous geolocation tracking on iOS, especially when the app is not in use or the device is locked, I would greatly appreciate the assistance.
Should we use absolute or calendar Date when scheduling background tasks?
I would guess it doesn't matter how we construct Date but I wanted to double check since WWDC videos show both ways.
I've experienced some instances where background tasks ran much later than expected, and while this is not surprising since iOS has many factors to consider when they allot background execution time, the times of execution seemed to line up with the hours change between Absolute and Calendar time.
Or
And
I understand there is no guarantee that the system will run the background task exactly or even near the date requested.
Thanks!
I'am developing an iOS widget for my weather app, where the user can set the widget to "My location". This means the widget needs to be refreshed on location changes. Since a widget can't run a location manager in the background, apple tech support wrote that you have to setup a location manager in the main app and share the updated location data over App groups to the widget. This part works fine. I also managed to setup a location manager running in the background, but it uses too much battery and shows always the location indicator on top (blue bar) if the app is running, but I don't need this since its not a navigation app or something similar. How to configure a lightweight location manager running in the background?
class WidgetLocationManager: NSObject, CLLocationManagerDelegate {
static let shared: WidgetLocationManager = WidgetLocationManager()
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyKilometer
manager.distanceFilter = 1000
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
manager.activityType = .other
manager.showsBackgroundLocationIndicator = false
}
func setupWidgetLocationManager() {
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
if manager.authorizationStatus == .notDetermined || manager.authorizationStatus == .denied || manager.authorizationStatus == .restricted {
manager.stopUpdatingLocation()
manager.stopMonitoringSignificantLocationChanges()
}
if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {
manager.startUpdatingLocation()
manager.startMonitoringSignificantLocationChanges()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let newestLocation = locations.last {
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.coordinate.latitude), forKey: "newest_location_latitude")
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.coordinate.longitude), forKey: "newest_location_longitude")
UserDefaults(suiteName: "group.com.***")?.set(Double(newestLocation.altitude), forKey: "newest_location_altitude")
WidgetCenter.shared.reloadAllTimelines()
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
}
Capability for background modes location is set, also mandatory strings in info.plist for location privacy info.
Hello everyone!
I'm currently working on an iOS app developed with Swift that involves connecting to a specific ble (Bluetooth Low Energy) device and exchanging data even when the app is terminated or running in the background.
I'm trying to figure out a way to wake up my application when a specific Bluetooth device(uuid is known) is visible and then connect to it and exchange data.
Is this functionality achievable?
Thank you in advance for your help!
Hello,
Our team is working on a mobile app that uses Nearby Interaction framework (UWB technology) to get real-time high-accuracy ranging information with our third-party UWB-enabled device. So far everything works fine, background sessions included as explained in wwdc2022/10008 video. We are using Bluetooth LE to exchange the UWB parameters as recommended by Apple.
Our next goal is to go for a full hands-free configuration of the UWB session. Let's think of an access control use case where UWB is used to measure the distance between the user and the door (credentials exchanged via Bluetooth). What we want to achieve is to start the UWB session without requiring the user to take the phone out of his wallet and open the access control app.
What it works for us today is if the user starts the app, then switches off the screen and puts the phone into his pocket. The app is still running in background, so the Bluetooth Scan keeps working, the Bluetooth session starts, the UWB parameters exchanged and the UWB session started in the background, all good.
But what if the user killed the app or never started it after reboot? How can we force the app to start from killed state when the BLE / UWB third-party accessory comes into proximity? iBeacon seems like a promising approach, but according to the forums, in iOS 16 the app will not be restarted from killed state. Is this correct?
Any idea / suggestion about how to let the OS start our app when the user approaches the BLE / UWB accessory and the app is in killed state?
Thanks in advance for your time.
Regards.
I’m working on an independent watchOS app which is primarily designed to to collect and periodically send location updates to a server. The UI features a toggle that allows the user to turn this capability on or off at their discretion. The typical use case scenario would be for the user to turn the toggle on in the morning, put the app in the background and then go about their day.
Given the limitations and restrictions regarding background execution on watchOS, in an ideal situation, I would be able to upload the stored location updates about every 15-20 minutes. With an active complication on the watch face, it’s my understanding that this should be possible. I’ve implemented background app refresh and indeed, I do see this reliably being triggered every 15-20 minutes or so.
In my handle(_:) method, I process the WKApplicationRefreshBackgroundTask like this:
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
backgroundTasks.forEach { task in
switch task {
case let appRefreshBackgroundTask as WKApplicationRefreshBackgroundTask:
// start background URL session to upload data; watchOS will perform the request in a separate process so that it will continue to run even if our app gets
// terminated; when the system is done transferring data, it will call this method again and backgroundTasks will contain an instance of
// WKURLSessionRefreshBackgroundTask which will be processed below
startBackgroundURLSessionUploadTask()
scheduleNextBackgroundAppRefresh()
appRefreshBackgroundTask.setTaskCompletedWithSnapshot(false)
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
// add urlSessionTask to the pendingURLSessionRefreshBackgroundTasks array so we keep a reference to it; when the system completes the upload and
// informs us via a URL session delegate method callback, then we will retrieve urlSessionTask from the pendingURLSessionRefreshBackgroundTasks array
// and call .setTaskCompletedWithSnapshot(_:) on it
pendingURLSessionRefreshBackgroundTasks.append(urlSessionTask)
// create another background URL session using the background task’s sessionIdentifier and specify our extension as the session’s delegate; using the same
// identifier to create a second URL session allows the system to connect the session to the upload that it performed for us in another process
let configuration = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier)
let _ = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
default:
task.setTaskCompletedWithSnapshot(false)
}
}
}
And here is how I'm creating and starting the background URL session upload task:
func startBackgroundURLSessionUploadTask() {
// 1. check to see that we have locations to report; otherwise, just return
// 2. serialize the locations into a temporary file
// 3. create the background upload task
let configuration = URLSessionConfiguration.background(withIdentifier: Constants.backgroundUploadIdentifier)
configuration.isDiscretionary = false
configuration.sessionSendsLaunchEvents = true
let backgroundUrlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let request: URLRequest = createURLRequest() // this is a POST request
let backgroundUrlSessionUploadTask = backgroundUrlSession.uploadTask(with: request, fromFile: tempFileUrl)
backgroundUrlSessionUploadTask.countOfBytesClientExpectsToSend = Int64(serializedData.count) // on average, this is ~1.5 KB
backgroundUrlSessionUploadTask.countOfBytesClientExpectsToReceive = Int64(50) // approximate size of server response
backgroundUrlSessionUploadTask.resume()
}
Note that I'm not setting the .earliestBeginDate property on the backgroundUrlSessionUploadTask because I'd like the upload to start as soon as possible without any delay. Also, this same class (my WatchKit application delegate) conforms to URLSessionTaskDelegate and I have implemented urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:) and urlSession(_:task:didCompleteWithError:).
In my testing (on an actual Apple Watch Ultra running watchOS 9.3.1), I've observed that when the system performs the background app refresh, I always receive a callback to myhandle(_:) method. But when I start the background URL session upload task (in startBackgroundURLSessionUploadTask()), I was expecting that when the upload completes, I'd receive another call to myhandle(_:) method with an instance of WKURLSessionRefreshBackgroundTask but this doesn't seem to happen consistently. Sometimes I do see it but other times, I don't and when I don't, the data doesn't seem to be getting uploaded.
On a side note, most of the time, startBackgroundURLSessionUploadTask() gets called as a result of my code handling a background app refresh task. But when the user turns off the toggle in the UI and I stop the location updates, I need to report any stored locations at that time and so I call startBackgroundURLSessionUploadTask() to do that. In that specific case, the upload seems to work 100% of the time but I definitely don't see a callback to my handle(_:) method when this occurs.
Am I wrong in expecting that I should always be getting a callback to handle(_:) when a background URL session upload task completes? If so, under what circumstances should this occur? Thanks very much!
Error Code: error build: Command CompileSwift failed with a nonzero exit code
My Code:
.backgroundTask(.appRefresh("checkValidity")) {
// scheduleAppRefresh()
// checkRecords()
}
Hi dear , I am a beginner developer
I have an application idea , and I think its great idea 😎
I think the application needs to use Device activity frame work , and UIScreen class , even if the app is in background or terminated , the problem is I don't know how to use these classes and frameworks 🤷🏻♂️
the questions are :
can I detect UITouch event on UIScreen object even if the app is in background or terminated
How to get the current activity name of the device
Since I am uploading in the background, I need to save the request body off in a file. The documentation says this gets copied to a temporary storage area and uploaded from there.
When can I delete the temporary file I generated?
Deleting it just after the call to
session.uploadTask(with: request, fromFile: filePath)
seems to be a race condition where I will occasionally get a sharing violation deleting the file.
Do I have to keep my temporary file around until DidCompleteWithError or DidReceiveData is called?
I ask because I'm uploading an existing photo, so I have to generate a multi-part form file with the photo embedded, then iOS makes a copy of that file. This results in having the photo in storage on the device three times. We are uploading photos from an Event so there will be several hundred, so Im worried about device storage running out.
Todd
I regularly see questions, both here on DevForums and in my Day Job™ at DTS, that are caused by a fundamental misunderstanding of how background execution works on iOS. These come in many different variants, for example:
How do I keep my app running continuously in the background?
If I schedule a timer, how do I get it to fire when the screen is locked?
How do I run code in the background every 15 minutes?
How do I set up a network server that runs in the background?
How can my app provide an IPC service to another one of my apps while it’s in the background?
How can I resume my app in the background if it’s been ‘force quit’ by the user?
The short answer to all of these is You can’t. iOS puts strict limits on background execution. Its default behaviour is to suspend your app shortly after the user has moved it to the background; this suspension prevents the process from running any code.
There’s no general-purpose mechanism for:
Running code continuously in the background
Running code at some specific time in the background
Running code periodically at a guaranteed interval
Resuming in the background in response to a network or IPC request
However, iOS does provide a wide range of special-purpose mechanisms for accomplishing specific user goals. For example:
If you’re building a music player, use the audio background mode to continue playing after the user has moved your app to the background.
If you’re building a timer app, use a local notification to notify the user when your timer has expired.
If you’re building a video player app, use AVFoundation’s download support.
Keep in mind that the above is just a short list of examples. There are many other special-purpose background execution mechanisms, so you should search the documentation for something appropriate to your needs.
IMPORTANT Each of these mechanisms fulfils a specific purpose. Do not attempt to use them for some other purpose. Before using a background API, read clause 2.5.4 of the App Review Guidelines.
Additionally, iOS provides some general-purpose mechanisms for background execution:
To resume your app in the background in response to an event on your server, use a background notification (aka a ‘silent’ push). For more information, see Pushing background updates to your App.
To request a small amount of background execution time to refresh your UI, use BGAppRefreshTaskRequest.
To request extended background execution time, typically delivered overnight when the user is asleep, use BGProcessingTaskRequest.
To prevent your app from being suspended for a short period of time so that you can complete some user task, use a UIApplication background task. For more information on this, see UIApplication Background Task Notes.
To download or upload a large HTTP resource, use an NSURLSession background session.
All of these mechanisms prevent you from abusing them to run arbitrary code in the background. As an example, consider the NSURLSession resume rate limiter.
For more information about these limitations, and background execution in general, I strongly recommend that you watch WWDC 2020 Session 10063 Background execution demystified. It’s an excellent resource.
Specifically, this talk addresses a common misconception about the app refresh mechanism (BGAppRefreshTaskRequest and the older background fetch API). Folks assume that app refresh will provide regular background execution time. That’s not the case. The system applies a range of heuristics to decide which apps get app refresh time and when. This is a complex issue, one that I’m not going to try to summarise here, but the take-home message is that, if you expect that the app refresh mechanism will grant you background execution time, say, every 15 minutes, you’ll be disappointed. In fact, there are common scenarios where it won’t grant you any background execution time at all! Watch the talk for the details.
When the user ‘force quits’ an app by swiping up in the multitasking UI, iOS interprets that to mean that the user doesn’t want the app running at all. So:
If the app is running, iOS terminates it.
iOS also sets a flag that prevents the app from being launched in the background. That flag gets cleared when the user next launches the app manually.
This gesture is a clear statement of user intent; there’s no documented way for your app to override the user’s choice.
Note In some circumstances iOS will not honour this flag. The exact cases where this happens are not documented and have changed over time.
Finally, if you have questions about background execution that aren’t covered by the resources listed here, please open a new thread on DevForums with the details. Tag it appropriately for the technology you’re using; if nothing specific springs to mind, use Background Tasks. Also, make sure to include details about the specific problem you’re trying to solve because, when it comes to background execution, the devil really is in the details.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Change history:
2024-03-21 Added a discussion of ‘force quit’.
2023-05-11 Added a paragraph that explains a common misconception about the app refresh mechanism. Made other minor editorial changes.
2021-08-12 Added more entries to the common questions list, this time related to networking and IPC. Made minor editorial changes.
2021-07-26 Extended the statement about what’s not possible to include “running code periodically at a guaranteed interval”.
2021-07-22 First posted.