@capacitor/background-runner 1.0.6-dev-20240409T144959.0 → 1.0.6-dev-20240416T204052.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/Plugin/BackgroundRunner.swift +54 -68
- package/ios/Plugin/BackgroundRunnerErrors.swift +1 -0
- package/ios/Plugin/BackgroundRunnerPlugin.swift +22 -7
- package/ios/Plugin/CapacitorAPI/KV.swift +4 -2
- package/ios/Plugin/RunnerConfig.swift +2 -2
- package/ios/Plugin/RunnerEngine/Runner.swift +2 -15
- package/package.json +2 -2
|
@@ -5,8 +5,8 @@ import JavaScriptCore
|
|
|
5
5
|
|
|
6
6
|
public class BackgroundRunner {
|
|
7
7
|
public static let shared = BackgroundRunner()
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
public var config: RunnerConfig?
|
|
9
|
+
|
|
10
10
|
private var runner = Runner()
|
|
11
11
|
|
|
12
12
|
public init() {
|
|
@@ -17,93 +17,51 @@ public class BackgroundRunner {
|
|
|
17
17
|
print("could not initialize BackgroundRunner: \(error)")
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
public func
|
|
20
|
+
|
|
21
|
+
public func scheduleBackgroundTasks() throws {
|
|
22
22
|
guard let config = config else {
|
|
23
|
-
|
|
24
|
-
return
|
|
23
|
+
throw BackgroundRunnerPluginError.noRunnerConfig
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
if config.
|
|
28
|
-
print("cannot register background task without a event to call")
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
BGTaskScheduler.shared.register(forTaskWithIdentifier: config.label, using: nil) { task in
|
|
33
|
-
do {
|
|
34
|
-
task.expirationHandler = {
|
|
35
|
-
print("task timed out")
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
guard let event = config.event else {
|
|
39
|
-
throw BackgroundRunnerPluginError.invalidRunnerConfig(reason: "runner event is missing or invalid")
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
_ = try BackgroundRunner.shared.execute(config: config, event: event)
|
|
43
|
-
|
|
44
|
-
task.setTaskCompleted(success: true)
|
|
45
|
-
} catch {
|
|
46
|
-
print("background task error: \(error)")
|
|
47
|
-
task.setTaskCompleted(success: false)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
public func scheduleBackgroundTasks() {
|
|
53
|
-
guard let config = config else {
|
|
25
|
+
|
|
26
|
+
if !config.autoSchedule {
|
|
54
27
|
return
|
|
55
28
|
}
|
|
56
29
|
|
|
57
30
|
guard let interval = config.interval else {
|
|
58
|
-
|
|
59
|
-
return
|
|
31
|
+
throw BackgroundRunnerPluginError.invalidRunnerConfig(reason: "cannot register background task without a configured interval")
|
|
60
32
|
}
|
|
61
33
|
|
|
62
34
|
let request = BGAppRefreshTaskRequest(identifier: config.label)
|
|
63
35
|
request.earliestBeginDate = Date(timeIntervalSinceNow: Double(interval) * 60)
|
|
64
36
|
|
|
65
|
-
|
|
66
|
-
print("Scheduling \(config.label)")
|
|
37
|
+
print("Scheduling \(config.label)")
|
|
67
38
|
|
|
68
|
-
|
|
69
|
-
} catch {
|
|
70
|
-
print("Could not schedule app refresh: \(error)")
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
public func getConfig() -> RunnerConfig? {
|
|
75
|
-
return config
|
|
39
|
+
try BGTaskScheduler.shared.submit(request)
|
|
76
40
|
}
|
|
77
41
|
|
|
78
|
-
public func
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
var err: Error?
|
|
42
|
+
public func registerBackgroundTask() throws {
|
|
43
|
+
guard let config = config else {
|
|
44
|
+
throw BackgroundRunnerPluginError.noRunnerConfig
|
|
45
|
+
}
|
|
84
46
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} catch {
|
|
90
|
-
err = error
|
|
91
|
-
print("[\(config.label)]: \(error)")
|
|
47
|
+
BGTaskScheduler.shared.register(forTaskWithIdentifier: config.label, using: nil) { task in
|
|
48
|
+
do {
|
|
49
|
+
task.expirationHandler = {
|
|
50
|
+
print("task timed out")
|
|
92
51
|
}
|
|
93
52
|
|
|
94
|
-
|
|
95
|
-
}
|
|
53
|
+
_ = try BackgroundRunner.shared.execute(config: config)
|
|
96
54
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
55
|
+
task.setTaskCompleted(success: true)
|
|
56
|
+
} catch {
|
|
57
|
+
print("background task error: \(error)")
|
|
58
|
+
task.setTaskCompleted(success: false)
|
|
101
59
|
}
|
|
102
60
|
}
|
|
103
61
|
}
|
|
104
|
-
|
|
62
|
+
|
|
105
63
|
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
|
106
|
-
public func execute(config: RunnerConfig,
|
|
64
|
+
public func execute(config: RunnerConfig, inputArgs: [String: Any]? = nil, callbackId: String? = nil) throws -> [String: Any]? {
|
|
107
65
|
do {
|
|
108
66
|
let context = try initContext(config: config, callbackId: callbackId)
|
|
109
67
|
|
|
@@ -170,9 +128,10 @@ public class BackgroundRunner {
|
|
|
170
128
|
|
|
171
129
|
waitGroup.enter()
|
|
172
130
|
|
|
173
|
-
try context.dispatchEvent(event: event, details: args)
|
|
131
|
+
try context.dispatchEvent(event: config.event, details: args)
|
|
174
132
|
|
|
175
133
|
waitGroup.wait()
|
|
134
|
+
|
|
176
135
|
|
|
177
136
|
if let rejection = rejectionErr {
|
|
178
137
|
throw EngineError.jsException(details: rejection.message)
|
|
@@ -185,6 +144,33 @@ public class BackgroundRunner {
|
|
|
185
144
|
}
|
|
186
145
|
}
|
|
187
146
|
|
|
147
|
+
public func dispatchEvent(event: String, inputArgs: [String: Any]?, callbackId: String? = nil) throws {
|
|
148
|
+
if let config = config {
|
|
149
|
+
let waitGroup = DispatchGroup()
|
|
150
|
+
waitGroup.enter()
|
|
151
|
+
|
|
152
|
+
var err: Error?
|
|
153
|
+
|
|
154
|
+
// swiftlint:disable:next unowned_variable_capture
|
|
155
|
+
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
|
156
|
+
do {
|
|
157
|
+
_ = try self.execute(config: config, inputArgs: inputArgs, callbackId: callbackId)
|
|
158
|
+
} catch {
|
|
159
|
+
err = error
|
|
160
|
+
print("[\(config.label)]: \(error)")
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
waitGroup.leave()
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
waitGroup.wait()
|
|
167
|
+
|
|
168
|
+
if let err = err {
|
|
169
|
+
throw err
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
188
174
|
private func loadRunnerConfig() throws -> RunnerConfig? {
|
|
189
175
|
guard let capacitorConfigFileURL = Bundle.main.url(forResource: "capacitor.config.json", withExtension: nil) else {
|
|
190
176
|
throw BackgroundRunnerPluginError.runnerError(reason: "capacitor.config.json file not found")
|
|
@@ -13,6 +13,7 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
13
13
|
name: UIApplication.didEnterBackgroundNotification,
|
|
14
14
|
object: nil
|
|
15
15
|
)
|
|
16
|
+
|
|
16
17
|
initWatchConnectivity()
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -54,22 +55,23 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
54
55
|
|
|
55
56
|
@objc func dispatchEvent(_ call: CAPPluginCall) {
|
|
56
57
|
do {
|
|
57
|
-
guard let runnerEvent = call.getString("event") else {
|
|
58
|
+
guard let runnerEvent = call.getString("event"), !runnerEvent.isEmpty else {
|
|
58
59
|
throw BackgroundRunnerPluginError.invalidArgument(reason: "event is missing or invalid")
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
let details = call.getObject("details", JSObject())
|
|
62
63
|
|
|
63
|
-
guard
|
|
64
|
-
throw BackgroundRunnerPluginError.
|
|
64
|
+
guard var config = impl.config else {
|
|
65
|
+
throw BackgroundRunnerPluginError.noRunnerConfig
|
|
65
66
|
}
|
|
67
|
+
|
|
68
|
+
config.event = runnerEvent
|
|
66
69
|
|
|
67
70
|
// swiftlint:disable:next unowned_variable_capture
|
|
68
71
|
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
|
69
72
|
do {
|
|
70
73
|
let result = try self.impl.execute(
|
|
71
74
|
config: config,
|
|
72
|
-
event: runnerEvent,
|
|
73
75
|
inputArgs: details as [String: Any],
|
|
74
76
|
callbackId: call.callbackId
|
|
75
77
|
)
|
|
@@ -94,14 +96,27 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
@objc private func didEnterBackground() {
|
|
97
|
-
|
|
99
|
+
do {
|
|
100
|
+
try impl.scheduleBackgroundTasks()
|
|
101
|
+
} catch {
|
|
102
|
+
print("could not schedule background task: \(error)")
|
|
103
|
+
}
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
public static func registerBackgroundTask() {
|
|
101
|
-
|
|
107
|
+
do {
|
|
108
|
+
try BackgroundRunner.shared.registerBackgroundTask()
|
|
109
|
+
} catch {
|
|
110
|
+
print("could not register background task: \(error)")
|
|
111
|
+
}
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
public static func dispatchEvent(event: String, eventArgs: [AnyHashable: Any], completionHandler: ((Result<Bool, Error>) -> Void)) {
|
|
115
|
+
if event.isEmpty {
|
|
116
|
+
completionHandler(.failure(BackgroundRunnerPluginError.invalidArgument(reason: "event is missing or invalid")))
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
|
|
105
120
|
var args: [String: Any] = [:]
|
|
106
121
|
|
|
107
122
|
eventArgs.forEach { (key: AnyHashable, value: Any) in
|
|
@@ -147,7 +162,7 @@ public class BackgroundRunnerPlugin: CAPPlugin {
|
|
|
147
162
|
return
|
|
148
163
|
}
|
|
149
164
|
|
|
150
|
-
guard let config = impl.
|
|
165
|
+
guard let config = impl.config else {
|
|
151
166
|
return
|
|
152
167
|
}
|
|
153
168
|
|
|
@@ -13,9 +13,11 @@ class CapacitorKVStore: NSObject, CapacitorKVStoreExports {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
static func get(_ key: String) -> JSValue {
|
|
16
|
+
guard let value = UserDefaults.standard.string(forKey: key) else {
|
|
17
|
+
return JSValue(nullIn: JSContext.current())
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
var valueWrapper: [String: String] = [:]
|
|
17
|
-
|
|
18
|
-
let value = UserDefaults.standard.string(forKey: key)
|
|
19
21
|
valueWrapper["value"] = value
|
|
20
22
|
|
|
21
23
|
return JSValue(object: valueWrapper, in: JSContext.current())
|
|
@@ -5,7 +5,7 @@ public struct RunnerConfig {
|
|
|
5
5
|
let label: String
|
|
6
6
|
let src: String
|
|
7
7
|
var autoSchedule: Bool
|
|
8
|
-
|
|
8
|
+
var event: String
|
|
9
9
|
let repeats: Bool?
|
|
10
10
|
let enableWatchConnectivity: Bool
|
|
11
11
|
|
|
@@ -20,7 +20,7 @@ public struct RunnerConfig {
|
|
|
20
20
|
throw BackgroundRunnerPluginError.invalidRunnerConfig(reason: "runner source file path is missing or invalid")
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
let event = jsObject["event"] as? String
|
|
23
|
+
let event = jsObject["event"] as? String ?? ""
|
|
24
24
|
let repeats = jsObject["repeat"] as? Bool
|
|
25
25
|
let interval = jsObject["interval"] as? Int
|
|
26
26
|
let autoStart = jsObject["autoStart"] as? Bool
|
|
@@ -3,31 +3,17 @@ import JavaScriptCore
|
|
|
3
3
|
|
|
4
4
|
public class Runner {
|
|
5
5
|
var machine: JSVirtualMachine
|
|
6
|
-
var contexts: [String: Context]
|
|
7
6
|
|
|
8
7
|
private let runLoop: RunLoop
|
|
9
8
|
private var thread: Thread?
|
|
10
9
|
|
|
11
10
|
public init() {
|
|
12
11
|
machine = JSVirtualMachine()
|
|
13
|
-
contexts = [:]
|
|
14
12
|
runLoop = RunLoop.current
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
func createContext(name: String) throws -> Context {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if contexts.keys.contains(name) {
|
|
21
|
-
throw EngineError.runnerError(details: "context with name \(name) already exists")
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
contexts[name] = context
|
|
25
|
-
|
|
26
|
-
return context
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
func destroyContext(name: String) {
|
|
30
|
-
contexts.removeValue(forKey: name)
|
|
16
|
+
return try Context(vm: machine, contextName: name, runLoop: runLoop)
|
|
31
17
|
}
|
|
32
18
|
|
|
33
19
|
func start() {
|
|
@@ -54,6 +40,7 @@ public class Runner {
|
|
|
54
40
|
}
|
|
55
41
|
|
|
56
42
|
thread.cancel()
|
|
43
|
+
|
|
57
44
|
while !thread.isFinished {
|
|
58
45
|
Thread.sleep(forTimeInterval: 0.05)
|
|
59
46
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/background-runner",
|
|
3
|
-
"version": "1.0.6-dev-
|
|
3
|
+
"version": "1.0.6-dev-20240416T204052.0",
|
|
4
4
|
"description": "Capacitor Background Runner",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"src": "android"
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "142e96d6415e4d5f8bcf8b217993cd99e2764659"
|
|
85
85
|
}
|