capacitor-mobilecron 0.2.23 → 0.2.24

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.
@@ -15,5 +15,6 @@ Pod::Spec.new do |s|
15
15
  s.ios.deployment_target = '14.0'
16
16
 
17
17
  s.dependency 'Capacitor'
18
+ s.dependency 'CapacitorNativeAgent'
18
19
  s.swift_version = '5.9'
19
20
  end
package/Package.swift CHANGED
@@ -11,14 +11,16 @@ let package = Package(
11
11
  )
12
12
  ],
13
13
  dependencies: [
14
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
14
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
15
+ .package(path: "../capacitor-native-agent")
15
16
  ],
16
17
  targets: [
17
18
  .target(
18
19
  name: "MobileCronPlugin",
19
20
  dependencies: [
20
21
  .product(name: "Capacitor", package: "capacitor-swift-pm"),
21
- .product(name: "Cordova", package: "capacitor-swift-pm")
22
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
23
+ .product(name: "CapacitorNativeAgent", package: "capacitor-native-agent")
22
24
  ],
23
25
  path: "ios/Plugin",
24
26
  exclude: ["MobileCronPlugin.m"]
@@ -37,6 +37,7 @@ repositories {
37
37
 
38
38
  dependencies {
39
39
  implementation project(':capacitor-android')
40
+ compileOnly project(':capacitor-native-agent')
40
41
  implementation "org.jetbrains.kotlin:kotlin-stdlib"
41
42
  implementation "androidx.work:work-runtime-ktx:2.9.0"
42
43
  testImplementation "junit:junit:$junitVersion"
@@ -10,7 +10,10 @@ class CronWorker(
10
10
  ) : CoroutineWorker(appContext, params) {
11
11
  override suspend fun doWork(): Result {
12
12
  NativeJobEvaluator.evaluate(applicationContext, "workmanager")
13
- CronBridge.wake("workmanager")
13
+ val handledNatively = NativeAgentBridge.handleWake(applicationContext, "workmanager")
14
+ if (!handledNatively) {
15
+ CronBridge.wake("workmanager")
16
+ }
14
17
  return Result.success()
15
18
  }
16
19
  }
@@ -0,0 +1,67 @@
1
+ package io.mobilecron
2
+
3
+ import android.content.Context
4
+ import com.t6x.plugins.nativeagent.MemoryProviderImpl
5
+ import com.t6x.plugins.nativeagent.NativeNotifierImpl
6
+ import java.util.concurrent.atomic.AtomicBoolean
7
+ import uniffi.native_agent_ffi.NativeAgentHandle
8
+ import uniffi.native_agent_ffi.createHandleFromPersistedConfig
9
+
10
+ object NativeAgentBridge {
11
+ private const val STORAGE_FILE = "CapacitorStorage"
12
+ private const val CONFIG_PATH_KEY = "mobilecron:native-agent-config-path"
13
+
14
+ @Volatile
15
+ private var handle: NativeAgentHandle? = null
16
+ private val libraryLoaded = AtomicBoolean(false)
17
+
18
+ fun handleWake(context: Context, source: String): Boolean {
19
+ return runCatching {
20
+ val agentHandle = getOrCreateHandle(context) ?: return false
21
+ agentHandle.handleWake(source)
22
+ true
23
+ }.getOrDefault(false)
24
+ }
25
+
26
+ private fun getOrCreateHandle(context: Context): NativeAgentHandle? {
27
+ handle?.let { return it }
28
+ synchronized(this) {
29
+ handle?.let { return it }
30
+ ensureLibraryLoaded()
31
+ val configPath = context
32
+ .getSharedPreferences(STORAGE_FILE, Context.MODE_PRIVATE)
33
+ .getString(CONFIG_PATH_KEY, null)
34
+ ?: return null
35
+
36
+ val agentHandle = runCatching {
37
+ createHandleFromPersistedConfig(configPath)
38
+ }.getOrNull() ?: return null
39
+
40
+ runCatching {
41
+ agentHandle.setNotifier(NativeNotifierImpl(context.applicationContext))
42
+ }
43
+ runCatching {
44
+ val memoryProvider = MemoryProviderImpl(context.applicationContext)
45
+ if (memoryProvider.isAvailable()) {
46
+ agentHandle.setMemoryProvider(memoryProvider)
47
+ }
48
+ }
49
+
50
+ handle = agentHandle
51
+ return agentHandle
52
+ }
53
+ }
54
+
55
+ private fun ensureLibraryLoaded() {
56
+ if (libraryLoaded.get()) {
57
+ return
58
+ }
59
+ synchronized(libraryLoaded) {
60
+ if (libraryLoaded.get()) {
61
+ return
62
+ }
63
+ System.loadLibrary("native_agent_ffi")
64
+ libraryLoaded.set(true)
65
+ }
66
+ }
67
+ }
@@ -63,7 +63,9 @@ final class BGTaskManager {
63
63
  task.setTaskCompleted(success: false)
64
64
  }
65
65
  _ = NativeJobEvaluator.evaluate(source: "bgtask_refresh")
66
- plugin?.handleBackgroundWake(source: "bgtask_refresh")
66
+ if !NativeAgentBridge.shared.handleWake("bgtask_refresh") {
67
+ plugin?.handleBackgroundWake(source: "bgtask_refresh")
68
+ }
67
69
  task.setTaskCompleted(success: true)
68
70
  }
69
71
 
@@ -74,7 +76,9 @@ final class BGTaskManager {
74
76
  task.setTaskCompleted(success: false)
75
77
  }
76
78
  _ = NativeJobEvaluator.evaluate(source: "bgtask_processing")
77
- plugin?.handleBackgroundWake(source: "bgtask_processing")
79
+ if !NativeAgentBridge.shared.handleWake("bgtask_processing") {
80
+ plugin?.handleBackgroundWake(source: "bgtask_processing")
81
+ }
78
82
  task.setTaskCompleted(success: true)
79
83
  }
80
84
  }
@@ -0,0 +1,62 @@
1
+ import Foundation
2
+
3
+ #if canImport(CapacitorNativeAgent)
4
+ import CapacitorNativeAgent
5
+ #elseif canImport(NativeAgentPlugin)
6
+ import NativeAgentPlugin
7
+ #endif
8
+
9
+ #if canImport(CapacitorNativeAgent) || canImport(NativeAgentPlugin)
10
+ final class NativeAgentBridge {
11
+ static let shared = NativeAgentBridge()
12
+
13
+ private let configPathKey = "mobilecron:native-agent-config-path"
14
+ private let lock = NSLock()
15
+ private var handle: NativeAgentHandle?
16
+
17
+ func handleWake(_ source: String) -> Bool {
18
+ guard let handle = getOrCreateHandle() else {
19
+ return false
20
+ }
21
+ do {
22
+ try handle.handleWake(source: source)
23
+ return true
24
+ } catch {
25
+ return false
26
+ }
27
+ }
28
+
29
+ private func getOrCreateHandle() -> NativeAgentHandle? {
30
+ lock.lock()
31
+ defer { lock.unlock() }
32
+
33
+ if let handle {
34
+ return handle
35
+ }
36
+
37
+ guard let configPath = UserDefaults.standard.string(forKey: configPathKey) else {
38
+ return nil
39
+ }
40
+
41
+ do {
42
+ let handle = try createHandleFromPersistedConfig(configPath: configPath)
43
+ try handle.setNotifier(notifier: NativeNotifierImpl())
44
+ if let memoryProvider = MemoryProviderImpl.makeIfAvailable() {
45
+ try handle.setMemoryProvider(provider: memoryProvider)
46
+ }
47
+ self.handle = handle
48
+ return handle
49
+ } catch {
50
+ return nil
51
+ }
52
+ }
53
+ }
54
+ #else
55
+ final class NativeAgentBridge {
56
+ static let shared = NativeAgentBridge()
57
+
58
+ func handleWake(_ source: String) -> Bool {
59
+ false
60
+ }
61
+ }
62
+ #endif
@@ -142,7 +142,7 @@ final class NativeJobEvaluator {
142
142
  return firedEvents
143
143
  }
144
144
 
145
- private static func computeNextDueAt(schedule: [String: Any]?, nowMs: Int64) -> Int64? {
145
+ static func computeNextDueAt(schedule: [String: Any]?, nowMs: Int64) -> Int64? {
146
146
  guard let schedule else { return nil }
147
147
  switch scheduleKind(schedule) {
148
148
  case "at":
@@ -171,7 +171,7 @@ final class NativeJobEvaluator {
171
171
  return nil
172
172
  }
173
173
 
174
- private static func isWithinActiveHours(activeHours: [String: Any], nowMs: Int64) -> Bool {
174
+ static func isWithinActiveHours(activeHours: [String: Any], nowMs: Int64) -> Bool {
175
175
  guard let startValue = activeHours["start"] as? String,
176
176
  let endValue = activeHours["end"] as? String,
177
177
  let start = parseClock(startValue),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-mobilecron",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "Capacitor scheduling primitive that emits job due events across web, Android, and iOS",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",