I have currently created an app which contains an upload button which when clicked upload health data using HealthKit to an AWS S3 bucket.
Now I want to implement an automatic file upload mechanism which would mean that the app is installed and opened just once - and then the upload must happen on a schedule (once daily) from the background without ever having to open the app again.
I've tried frameworks like NSURLSession and BackgroundTasks but nothing seems to work. Is this use case even possible to implement? Does iOS allow this?
The file is just a few KBs in size.
For reference, here is the Background Tasks code:
import UIKit
import BackgroundTasks
import HealthKit
class AppDelegate: NSObject, UIApplicationDelegate {
let backgroundTaskIdentifier = "com.yourapp.healthdata.upload"
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Register the background task
BGTaskScheduler.shared.register(forTaskWithIdentifier: backgroundTaskIdentifier, using: nil) { task in
self.handleHealthDataUpload(task: task as! BGAppRefreshTask)
}
// Schedule the first upload task
scheduleDailyUpload()
return true
}
// Schedule the background task for daily execution
func scheduleDailyUpload() {
print("[AppDelegate] Scheduling daily background task.")
let request = BGAppRefreshTaskRequest(identifier: backgroundTaskIdentifier)
request.earliestBeginDate = Date(timeIntervalSinceNow: 24*60*60)
do {
try BGTaskScheduler.shared.submit(request)
print("[AppDelegate] Daily background task scheduled.")
} catch {
print("[AppDelegate] Could not schedule daily background task: \(error.localizedDescription)")
}
}
// Handle the background task when it's triggered by the system
func handleHealthDataUpload(task: BGAppRefreshTask) {
print("[AppDelegate] Background task triggered.")
// Call your upload function with completion handler
HealthStoreManager.shared.fetchAndUploadHealthData { success in
if success {
print("[AppDelegate] Upload completed successfully.")
task.setTaskCompleted(success: true)
// Schedule the next day's upload after a successful upload
self.scheduleDailyUpload()
} else {
print("[AppDelegate] Upload failed.")
task.setTaskCompleted(success: false)
}
}
// Handle task expiration (e.g., if upload takes too long)
task.expirationHandler = {
print("[AppDelegate] Background task expired.")
task.setTaskCompleted(success: false)
}
}
}
The issue here is that you’re using an app refresh task. App refresh only kicks in if the user is using your app frequently. I talk about this more in iOS Background Execution Limits.
What you want is a processing task. Those usually run once a day, over night, when the device is on mains power and has access to the network.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"