Skip to content

Commit

Permalink
First part of background capabilities implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
redmilk committed Jan 20, 2022
1 parent 47fe74e commit 8987579
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 11 deletions.
20 changes: 20 additions & 0 deletions AirPrint.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
796B1AD6275A127F005864B0 /* ColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796B1AD5275A127F005864B0 /* ColorPalette.swift */; };
796B1AD9275A12A0005864B0 /* Typealias.swift in Sources */ = {isa = PBXBuildFile; fileRef = 796B1AD8275A12A0005864B0 /* Typealias.swift */; };
79763582274E88B9001D2155 /* InteractionFeedbackService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79763581274E88B9001D2155 /* InteractionFeedbackService.swift */; };
7983E3132798B4450098A2D7 /* BackgroundTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7983E3122798B4450098A2D7 /* BackgroundTimer.swift */; };
7983E3152798BC310098A2D7 /* TaskBackgroundKeeper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7983E3142798BC310098A2D7 /* TaskBackgroundKeeper.swift */; };
7983E3172798C5640098A2D7 /* BackgroundScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7983E3162798C5640098A2D7 /* BackgroundScheduler.swift */; };
7983ECCC275092AF00B5C2AF /* PDFService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7983ECCB275092AF00B5C2AF /* PDFService.swift */; };
7988745E2770BCC40027C121 /* PurchaseService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7988745D2770BCC40027C121 /* PurchaseService.swift */; };
798874612770C09B0027C121 /* Purchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 798874602770C09B0027C121 /* Purchase.swift */; };
Expand Down Expand Up @@ -191,6 +194,9 @@
796B1AD5275A127F005864B0 /* ColorPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPalette.swift; sourceTree = "<group>"; };
796B1AD8275A12A0005864B0 /* Typealias.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typealias.swift; sourceTree = "<group>"; };
79763581274E88B9001D2155 /* InteractionFeedbackService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InteractionFeedbackService.swift; sourceTree = "<group>"; };
7983E3122798B4450098A2D7 /* BackgroundTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundTimer.swift; sourceTree = "<group>"; };
7983E3142798BC310098A2D7 /* TaskBackgroundKeeper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskBackgroundKeeper.swift; sourceTree = "<group>"; };
7983E3162798C5640098A2D7 /* BackgroundScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundScheduler.swift; sourceTree = "<group>"; };
7983ECCB275092AF00B5C2AF /* PDFService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFService.swift; sourceTree = "<group>"; };
7983ECDE2750B0D500B5C2AF /* AirPrint-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AirPrint-Bridging-Header.h"; sourceTree = "<group>"; };
7983ECDF2750B0D500B5C2AF /* iCarousel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iCarousel.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -363,6 +369,7 @@
79763581274E88B9001D2155 /* InteractionFeedbackService.swift */,
799DA1692762CFE2003EA17F /* Onboarding.swift */,
79C362AF276CAB57001B1745 /* SharedActivityResults.swift */,
7983E3162798C5640098A2D7 /* BackgroundScheduler.swift */,
);
path = Services;
sourceTree = "<group>";
Expand Down Expand Up @@ -427,6 +434,15 @@
path = Protocols;
sourceTree = "<group>";
};
7983E3112798B4260098A2D7 /* Utils */ = {
isa = PBXGroup;
children = (
7983E3122798B4450098A2D7 /* BackgroundTimer.swift */,
7983E3142798BC310098A2D7 /* TaskBackgroundKeeper.swift */,
);
path = Utils;
sourceTree = "<group>";
};
7983ECDD2750B06400B5C2AF /* CarouselView */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -662,6 +678,7 @@
79F913CD274652E200771FFE /* Source */ = {
isa = PBXGroup;
children = (
7983E3112798B4260098A2D7 /* Utils */,
798F5D83278E05C60042BA98 /* Controller */,
79A598092762FDA800EB580A /* View */,
79DCEF9B275B9266007BC160 /* Model */,
Expand Down Expand Up @@ -821,6 +838,7 @@
79A725B12750C41700D8B330 /* ResultPreviewCollectionCell.swift in Sources */,
79D1AA7827740A2F00733F20 /* TapAnimatedButton.swift in Sources */,
794F73ED2746B36900B07410 /* Publisher+Extensions.swift in Sources */,
7983E3172798C5640098A2D7 /* BackgroundScheduler.swift in Sources */,
792D661127552DE300063F4B /* CameraScanManager.swift in Sources */,
79F80FBC2752A93C00081C7A /* ServicesContainer.swift in Sources */,
79C362B0276CAB58001B1745 /* SharedActivityResults.swift in Sources */,
Expand Down Expand Up @@ -860,6 +878,7 @@
793ADF5F2754E36100F58923 /* HomeScreenMenuViewModel.swift in Sources */,
794F73EC2746B36900B07410 /* UICollectionView+Extensions.swift in Sources */,
79D102A527717CC500F3C4D5 /* SubscriptionPlanPopup.swift in Sources */,
7983E3152798BC310098A2D7 /* TaskBackgroundKeeper.swift in Sources */,
79BBD8AB276319660087B1E0 /* ParticleEmitterView.swift in Sources */,
79F913B62746501500771FFE /* SceneDelegate.swift in Sources */,
7911B025276B0FEC0058CD26 /* MiscSettingsModulesViewController.swift in Sources */,
Expand All @@ -873,6 +892,7 @@
794F73EF2746B36900B07410 /* UIControl+Extensions.swift in Sources */,
793ADF5D2754E36100F58923 /* HomeScreenMenuCoordinator.swift in Sources */,
79A725A62750BE3B00D8B330 /* HomeCollectionManager.swift in Sources */,
7983E3132798B4450098A2D7 /* BackgroundTimer.swift in Sources */,
79697CD6275AF1FC0056B0B0 /* WebpageViewController.swift in Sources */,
79B787CD2750B250009D7655 /* PrintingOptionsViewModel.swift in Sources */,
796B1AD6275A127F005864B0 /* ColorPalette.swift in Sources */,
Expand Down
3 changes: 2 additions & 1 deletion Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import ApphudSDK
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

BackgroundScheduler.shared.register()

ApplicationGlobalConfig().configure()
Apphud.start(apiKey: "app_EaKCtoJCJkjJV73Dc7XA2L2ikP7KST")

Expand Down
9 changes: 9 additions & 0 deletions Application/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.surf.devip</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
Expand Down Expand Up @@ -58,6 +62,11 @@
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
7 changes: 5 additions & 2 deletions Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window!.makeKeyAndVisible()

applicationCoordinator = ApplicationCoordinator(window: window!)
applicationCoordinator.start()
applicationCoordinator.start()
}

func sceneDidDisconnect(_ scene: UIScene) {
Expand All @@ -34,10 +34,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}

func sceneWillEnterForeground(_ scene: UIScene) {
//BackgroundScheduler.shared.cancelPendingTask()
//print("🥲🥲🥲")
//print(UserDefaults.standard.value(forKey: "123") as? String)
}

func sceneDidEnterBackground(_ scene: UIScene) {
BackgroundScheduler.shared.scheduleBackgroundFetch(in: 10)
}

}

8 changes: 0 additions & 8 deletions Module/Onboarding/OnboardingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ final class OnboardingViewController: UIViewController {
@IBOutlet weak var printerAnim: AnimationView!
@IBOutlet weak var scanerAnim: AnimationView!
@IBOutlet weak var signatureAnim: AnimationView!

@IBOutlet weak var primaryImageView: UIImageView!
@IBOutlet weak var pagingImageView: UIImageView!
@IBOutlet weak var primaryLabel: UILabel!
Expand Down Expand Up @@ -75,13 +74,6 @@ final class OnboardingViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// printerAnim.play()
//
// scanerAnim.play()
// scanerAnim.isHidden = true
// signatureAnim.play()
// signatureAnim.isHidden = true
// printerAnim.play()
changeAnimation()
}

Expand Down
56 changes: 56 additions & 0 deletions Source/Services/BackgroundScheduler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// SessionCleaner.swift
// AirPrint
//
// Created by Danyl Timofeyev on 20.01.2022.
//

import Foundation
import BackgroundTasks
/// fire debug:
/// e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.surf.devip"]
class BackgroundScheduler {

static let shared = BackgroundScheduler()

var taskProcess: VoidClosure?
var shouldRepeating: Bool = true

private var taskIdentifierFromPlist: String!

func register(taskIdentifier: String = "com.surf.devip") {
taskIdentifierFromPlist = taskIdentifier
BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: nil) { (task) in
self.handleAppRefreshTask(task: task as! BGAppRefreshTask)
}
}

func handleAppRefreshTask(task: BGAppRefreshTask) {
task.expirationHandler = {
task.setTaskCompleted(success: false)
}
/// task process
//UserDefaults.standard.set("\(Date().timeIntervalSince1970)", forKey: "123")
taskProcess?()
///
task.setTaskCompleted(success: true)
if shouldRepeating {
scheduleBackgroundFetch()
}
}

func scheduleBackgroundFetch(in seconds: Double = 60) {
let task = BGAppRefreshTaskRequest(identifier: taskIdentifierFromPlist)
//task.earliestBeginDate = Date(timeIntervalSinceNow: seconds)
do {
try BGTaskScheduler.shared.submit(task)
} catch {
Logger.log("Unable to submit task: \(error.localizedDescription)", type: .error)
Logger.logError(error)
}
}

func cancelPendingTask() {
BGTaskScheduler.shared.cancelAllTaskRequests()
}
}
62 changes: 62 additions & 0 deletions Source/Utils/BackgroundTimer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// BackgroundTimer.swift
// AirPrint
//
// Created by Danyl Timofeyev on 19.01.2022.
//

import Foundation

class BackgroundTimer {

let timeInterval: TimeInterval

init(timeInterval: TimeInterval) {
self.timeInterval = timeInterval
}

private lazy var timer: DispatchSourceTimer = {
let t = DispatchSource.makeTimerSource()
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval)
t.setEventHandler(handler: { [weak self] in
self?.eventHandler?()
})
return t
}()

var eventHandler: (() -> Void)?

private enum State {
case suspended
case resumed
}

private var state: State = .suspended

deinit {
timer.setEventHandler {}
timer.cancel()
/*
If the timer is suspended, calling cancel without resuming
triggers a crash. This is documented here https://forums.developer.apple.com/thread/15902
*/
resume()
eventHandler = nil
}

func resume() {
if state == .resumed {
return
}
state = .resumed
timer.resume()
}

func suspend() {
if state == .suspended {
return
}
state = .suspended
timer.suspend()
}
}
36 changes: 36 additions & 0 deletions Source/Utils/TaskBackgroundKeeper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// TaskBackgroundKeeper.swift
// AirPrint
//
// Created by Danyl Timofeyev on 19.01.2022.
//

import Foundation

class TaskBackgroundKeeper {
private var backgroundTaskId: UIBackgroundTaskIdentifier?
private var taskName: String = "task-that-should-continue-runing-in-background"
private var queue = DispatchQueue.global(qos: .background)

func executeAfterDelay(delay: TimeInterval, completion: @escaping (() -> Void)) {
backgroundTaskId = UIApplication.shared.beginBackgroundTask(
withName: taskName,
expirationHandler: { [weak self] in
if let taskId = self?.backgroundTaskId {
UIApplication.shared.endBackgroundTask(taskId)
}
})
let startTime = Date()
queue.async {
while Date().timeIntervalSince(startTime) < delay {
Thread.sleep(forTimeInterval: 1) //0.01)
}
DispatchQueue.main.async { [weak self] in
completion()
if let taskId = self?.backgroundTaskId {
UIApplication.shared.endBackgroundTask(taskId)
}
}
}
}
}

0 comments on commit 8987579

Please sign in to comment.