My goal is this: perform local backup / copy of some files/folders.
My app is an open source Signal app fork from GitHub. a Messaging app. Messages are store in a local database.
- I need to perform local backup on my iOS app, at least once a day even if app is not in background but closed.
- No server involved in the backup, is all a local process where some files, such images and database are required to be copied in a folder, zipped and encrypted.
- No alert interaction from user should be required.
- App won't be in the store, so I do not have a review fear at this moment.
I only found references to background activity, with a schema about background task (not refresh) that I report in this question, but it will work up to OS needs and wills, even if a preferred hour was set. I understand this. I give my code for example and possible help.
But is it possible to perform intensive operation such a backup while app is closed? Is there a way to perform my local backup at least once a day even if app is closed? how do other apps such Calendar, Alarm wok?
so, no shortcuts, I need to understand if there is some way to book a task while app is closed, or at least wile suspended. If the answer is "not possible" it is ok, I just need an explanation reference for my company.
This is my code for background task, if not possible doing what I ask, is this code right? Tried to test on console, seems to work
Targeting at least iOS 13, using UIKit.
I enabled background modes, background fetch and background processing in settings and capabilities, then added a string for the BGProcessingTaskRequest.
UPADTED from BGAppRefreshTask to BGProcessingTaskRequest (does not have 30 second of activity limit).
import UIKit
import BackgroundTasks
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.mytask", using: nil) { task in
self.handleAppRefreshTask(task: task as! BGProcessingTaskRequest)
}
scheduleAppRefresh()
return true
}
func scheduleAppRefresh() {
print("called: scheduleAppRefresh")
let request = BGProcessingTaskRequest(identifier: "com.example.mytask")
request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("not possible scheduling background app activity: \(error.localizedDescription)")
}
}
func handleAppRefreshTask(task: BGProcessingTaskRequest) {
let startDate = Date()
print("starting backup date: \(startDate)")
DispatchQueue.global().async {
let backupDuration: TimeInterval = 180
let endTime = Date(timeIntervalSinceNow: backupDuration)
while Date() < endTime {
print("performing backup...")
Thread.sleep(forTimeInterval: 1)
}
let endDate = Date()
print("end of backup: \(endDate)")
task.setTaskCompleted(success: true)
}
scheduleAppRefresh()
}
}
my info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.example.mytask</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
</dict>
</plist>