@capacitor/background-runner 1.0.6-dev-20240409T144959.0 → 1.0.6-dev-20240416T212318.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/README.md +1 -1
- package/dist/docs-api.json +1 -1
- package/dist/docs.json +1 -1
- package/dist/esm/definitions.d.ts +1 -1
- package/dist/esm/definitions.js.map +1 -1
- 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
package/README.md
CHANGED
|
@@ -157,7 +157,7 @@ Calling `resolve()` \ `reject()` is **required** within every event handler call
|
|
|
157
157
|
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
158
158
|
|
|
159
159
|
On load, Background Runner will automatically register a
|
|
160
|
-
background task that will be scheduled and
|
|
160
|
+
background task that will be scheduled and run once your app is
|
|
161
161
|
backgrounded.
|
|
162
162
|
|
|
163
163
|
| Prop | Type | Description | Since |
|
package/dist/docs-api.json
CHANGED
|
@@ -764,7 +764,7 @@
|
|
|
764
764
|
"type": "boolean | undefined"
|
|
765
765
|
}
|
|
766
766
|
],
|
|
767
|
-
"docs": "On load, Background Runner will automatically register a\nbackground task that will be scheduled and
|
|
767
|
+
"docs": "On load, Background Runner will automatically register a\nbackground task that will be scheduled and run once your app is\nbackgrounded."
|
|
768
768
|
}
|
|
769
769
|
]
|
|
770
770
|
}
|
package/dist/docs.json
CHANGED
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
"type": "boolean | undefined"
|
|
308
308
|
}
|
|
309
309
|
],
|
|
310
|
-
"docs": "On load, Background Runner will automatically register a\nbackground task that will be scheduled and
|
|
310
|
+
"docs": "On load, Background Runner will automatically register a\nbackground task that will be scheduled and run once your app is\nbackgrounded."
|
|
311
311
|
}
|
|
312
312
|
]
|
|
313
313
|
}
|
|
@@ -43,7 +43,7 @@ declare module '@capacitor/cli' {
|
|
|
43
43
|
interface PluginsConfig {
|
|
44
44
|
/**
|
|
45
45
|
* On load, Background Runner will automatically register a
|
|
46
|
-
* background task that will be scheduled and
|
|
46
|
+
* background task that will be scheduled and run once your app is
|
|
47
47
|
* backgrounded.
|
|
48
48
|
*/
|
|
49
49
|
BackgroundRunner?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\nimport type { PermissionState } from '@capacitor/core';\n\nexport interface BackgroundRunnerConfig {\n /**\n * The name of the runner, used in logs.\n *\n * @since 1.0.0\n */\n label: string;\n /**\n * The path to the runner JavaScript file, relative to the app bundle.\n *\n * @since 1.0.0\n */\n src: string;\n /**\n * The name of the event that will be called when the OS executes the background task.\n *\n * @since 1.0.0\n */\n event: string;\n /**\n * If background task should repeat based on the interval set in `interval`.\n *\n * @since 1.0.0\n */\n repeat: boolean;\n /**\n * The number of minutes after the the app is put into the background in which the background task should begin.\n *\n * If `repeat` is true, this also specifies the number of minutes between each execution.\n *\n * @since 1.0.0\n */\n interval: number;\n /**\n * Automatically register and schedule background task on app load.\n *\n * @since 1.0.0\n */\n autoStart?: boolean;\n}\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n /**\n * On load, Background Runner will automatically register a\n * background task that will be scheduled and
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,wCAAwC","sourcesContent":["/// <reference types=\"@capacitor/cli\" />\n\nimport type { PermissionState } from '@capacitor/core';\n\nexport interface BackgroundRunnerConfig {\n /**\n * The name of the runner, used in logs.\n *\n * @since 1.0.0\n */\n label: string;\n /**\n * The path to the runner JavaScript file, relative to the app bundle.\n *\n * @since 1.0.0\n */\n src: string;\n /**\n * The name of the event that will be called when the OS executes the background task.\n *\n * @since 1.0.0\n */\n event: string;\n /**\n * If background task should repeat based on the interval set in `interval`.\n *\n * @since 1.0.0\n */\n repeat: boolean;\n /**\n * The number of minutes after the the app is put into the background in which the background task should begin.\n *\n * If `repeat` is true, this also specifies the number of minutes between each execution.\n *\n * @since 1.0.0\n */\n interval: number;\n /**\n * Automatically register and schedule background task on app load.\n *\n * @since 1.0.0\n */\n autoStart?: boolean;\n}\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n /**\n * On load, Background Runner will automatically register a\n * background task that will be scheduled and run once your app is\n * backgrounded.\n */\n BackgroundRunner?: {\n /**\n * The name of the runner, used in logs.\n *\n * @since 1.0.0\n * @example \"com.example.background.task\"\n */\n label: string;\n /**\n * The path to the runner JavaScript file, relative to the app bundle.\n *\n * @since 1.0.0\n * @example \"runners/background.js\"\n */\n src: string;\n /**\n * The name of the event that will be called when the OS executes the background task.\n *\n * @since 1.0.0\n * @example \"myCustomEvent\"\n */\n event: string;\n /**\n * If background task should repeat based on the interval set in `interval`.\n *\n * @since 1.0.0\n * @example true\n */\n repeat: boolean;\n /**\n * The number of minutes after the the app is put into the background in which the background task should begin.\n *\n * If `repeat` is true, this also specifies the number of minutes between each execution.\n *\n * @since 1.0.0\n * @example 15\n */\n interval: number;\n /**\n * Automatically register and schedule background task on app load.\n *\n * @since 1.0.0\n * @example true\n */\n autoStart?: boolean;\n };\n }\n}\n\nexport type API = 'geolocation' | 'notifications';\n\nexport interface PermissionStatus {\n geolocation: PermissionState;\n notifications: PermissionState;\n}\n\nexport interface DispatchEventOptions {\n /**\n * The runner label to dispatch the event to\n *\n * @since 1.0.0\n */\n label: string;\n /**\n * The name of the registered event listener.\n *\n * @since 1.0.0\n */\n event: string;\n details: { [key: string]: any };\n}\n\nexport interface RequestPermissionOptions {\n apis: API[];\n}\n\nexport interface RegisterBackgroundTaskOptions {\n runner: BackgroundRunnerConfig;\n}\n\nexport interface BackgroundRunnerPlugin {\n /**\n * Check permissions for the various Capacitor device APIs.\n *\n * @since 1.0.0\n */\n checkPermissions(): Promise<PermissionStatus>;\n /**\n * Request permission to display local notifications.\n *\n * @since 1.0.0\n */\n requestPermissions(\n options: RequestPermissionOptions,\n ): Promise<PermissionStatus>;\n /**\n * Dispatches an event to the configured runner.\n * @param options\n * @since 1.0.0\n */\n dispatchEvent<T = void>(options: DispatchEventOptions): Promise<T>;\n}\n\ndeclare module '@capacitor/cli' {\n export interface PluginsConfig {\n BackgroundRunner?: BackgroundRunnerConfig;\n }\n}\n"]}
|
|
@@ -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-20240416T212318.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": "bbb1e6ffec4fe612f069f39b3e4c1b4daed27210"
|
|
85
85
|
}
|