expo-background-task 0.1.0 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -10,8 +10,22 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
- ## 0.1.0 — 2025-01-27
13
+ ## 0.1.2 — 2025-02-14
14
14
 
15
- ### 🎉 New features
15
+ _This version does not introduce any user-facing changes._
16
+
17
+ ## 0.1.1 — 2025-01-31
18
+
19
+ ### 💡 Others
20
+
21
+ - [Android] Started using expo modules gradle plugin. ([#34431](https://github.com/expo/expo/pull/34431) by [@chrfalch](https://github.com/chrfalch))
22
+
23
+ ## 0.0.1 — 2025-01-21
24
+
25
+ ### 💡 Others
26
+
27
+ - Update README description
28
+
29
+ ## 0.0.0 — 2025-01-21
16
30
 
17
- - Added expo-background-task package ([#33438](https://github.com/expo/expo/pull/33438) by [@chrfalch](https://github.com/chrfalch))
31
+ > > > > > > > 1362a71283d ([background-task][gradle] - start use new expo modules gradle plugin (#34431))### 🎉 New features- Added expo-background-task package ([#33438](https://github.com/expo/expo/pull/33438) by [@chrfalch](https://github.com/chrfalch))
@@ -1,14 +1,26 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
- group = 'host.exp.exponent'
4
- version = '0.1.0'
3
+ def useLegacyExpoModulesCorePlugin = {
4
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
5
+ apply from: expoModulesCorePlugin
6
+ applyKotlinExpoModulesCorePlugin()
7
+ useCoreDependencies()
8
+ useDefaultAndroidSdkVersions()
9
+ useExpoPublishing()
10
+ }
11
+
12
+ try {
13
+ apply plugin: 'expo-module-gradle-plugin'
14
+ } catch (e) {
15
+ if (!e instanceof UnknownPluginException) {
16
+ throw e
17
+ }
5
18
 
6
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
- apply from: expoModulesCorePlugin
8
- applyKotlinExpoModulesCorePlugin()
9
- useCoreDependencies()
10
- useDefaultAndroidSdkVersions()
11
- useExpoPublishing()
19
+ useLegacyExpoModulesCorePlugin()
20
+ }
21
+
22
+ group = 'host.exp.exponent'
23
+ version = '0.1.2'
12
24
 
13
25
  dependencies {
14
26
  implementation 'androidx.work:work-runtime-ktx:2.9.1'
@@ -19,6 +31,6 @@ android {
19
31
  namespace "expo.modules.backgroundtask"
20
32
  defaultConfig {
21
33
  versionCode 23
22
- versionName "0.1.0"
34
+ versionName "0.1.2"
23
35
  }
24
36
  }
@@ -50,7 +50,7 @@ class BackgroundTaskModule : Module() {
50
50
  appContext.reactContext?.let {
51
51
  runBlocking {
52
52
  val appScopeKey = it.packageName
53
- BackgroundTaskScheduler.startWorker(it, appScopeKey)
53
+ BackgroundTaskScheduler.scheduleWorker(it, appScopeKey)
54
54
  }
55
55
  } ?: throw MissingContextException()
56
56
  }
@@ -6,7 +6,9 @@ import android.util.Log
6
6
  import androidx.work.Constraints
7
7
  import androidx.work.Data
8
8
  import androidx.work.ExistingPeriodicWorkPolicy
9
+ import androidx.work.ExistingWorkPolicy
9
10
  import androidx.work.NetworkType
11
+ import androidx.work.OneTimeWorkRequestBuilder
10
12
  import androidx.work.Operation
11
13
  import androidx.work.PeriodicWorkRequestBuilder
12
14
  import androidx.work.WorkInfo
@@ -55,14 +57,16 @@ object BackgroundTaskScheduler {
55
57
  /**
56
58
  * Schedules the worker task to run. The worker should run periodically.
57
59
  */
58
- suspend fun startWorker(context: Context, appScopeKey: String): Boolean {
60
+ suspend fun scheduleWorker(context: Context, appScopeKey: String, cancelExisting: Boolean = true): Boolean {
59
61
  if (numberOfRegisteredTasksOfThisType == 0) {
60
62
  Log.d(TAG, "Will not enqueue worker. No registered tasks to run.")
61
63
  return false
62
64
  }
63
65
 
64
66
  // Stop the current worker (if any)
65
- stopWorker(context)
67
+ if (cancelExisting) {
68
+ stopWorker(context)
69
+ }
66
70
 
67
71
  Log.d(TAG, "Enqueuing worker with identifier $WORKER_IDENTIFIER")
68
72
 
@@ -75,37 +79,65 @@ object BackgroundTaskScheduler {
75
79
  .setRequiredNetworkType(NetworkType.CONNECTED)
76
80
  .build()
77
81
 
78
- // Create the work request
79
- val builder = PeriodicWorkRequestBuilder<BackgroundTaskWork>(
80
- repeatIntervalTimeUnit = TimeUnit.MINUTES,
81
- repeatInterval = intervalMinutes
82
- )
83
- .setInputData(data)
84
- .setConstraints(constraints)
82
+ // Get Work manager
83
+ val workManager = WorkManager.getInstance(context)
85
84
 
85
+ // We have two different paths here, since on Android 14-15 we need to use a periodic request
86
+ // builder since the OneTimeWorkRequest doesn't support setting initial delay (which is how we
87
+ // control executing a task periodically - we spawn a One-time work request when backgrounding,
88
+ // and when this is done we spawn a new one. This makes it a lot easier to debug since we can
89
+ // use adb to spawn jobs whenever we want)
90
+ // The following is the path we have to follow on Android.O and later:
86
91
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
92
+ // Create the work request
93
+ val builder = OneTimeWorkRequestBuilder<BackgroundTaskWork>()
94
+ .setInputData(data)
95
+ .setConstraints(constraints)
96
+
87
97
  // Add minimum interval here as well so that the work doesn't start immediately
88
98
  builder.setInitialDelay(Duration.ofMinutes(intervalMinutes))
89
- }
90
-
91
- // Create work request
92
- val workRequest = builder.build()
93
99
 
94
- // Get Work manager
95
- val workManager = WorkManager.getInstance(context)
96
-
97
- // Enqueue the work
98
- return try {
99
- workManager.enqueueUniquePeriodicWork(
100
- WORKER_IDENTIFIER,
101
- ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
102
- workRequest
103
- ).await()
104
-
105
- true
106
- } catch (e: Exception) {
107
- Log.e(TAG, "Worker failed to start with error " + e.message)
108
- false
100
+ // Create work request
101
+ val workRequest = builder.build()
102
+
103
+ // Enqueue the work
104
+ return try {
105
+ workManager.enqueueUniqueWork(
106
+ WORKER_IDENTIFIER,
107
+ // This is where we decide if we should cancel or replace the task - cancelling is done
108
+ // when spawning the first task, while appending is when we spawn from a running task
109
+ // to set up the next periodic run of the task
110
+ if (cancelExisting) ExistingWorkPolicy.REPLACE else ExistingWorkPolicy.APPEND,
111
+ workRequest
112
+ ).await()
113
+
114
+ true
115
+ } catch (e: Exception) {
116
+ Log.e(TAG, "Worker failed to start with error " + e.message)
117
+ false
118
+ }
119
+ } else {
120
+ val builder = PeriodicWorkRequestBuilder<BackgroundTaskWork>(
121
+ repeatIntervalTimeUnit = TimeUnit.MINUTES,
122
+ repeatInterval = intervalMinutes
123
+ )
124
+
125
+ // Create work request
126
+ val workRequest = builder.build()
127
+
128
+ // Enqueue the work
129
+ return try {
130
+ workManager.enqueueUniquePeriodicWork(
131
+ WORKER_IDENTIFIER,
132
+ ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
133
+ workRequest
134
+ ).await()
135
+
136
+ true
137
+ } catch (e: Exception) {
138
+ Log.e(TAG, "Worker failed to start with error " + e.message)
139
+ false
140
+ }
109
141
  }
110
142
  }
111
143
 
@@ -152,7 +184,7 @@ object BackgroundTaskScheduler {
152
184
  val consumers = taskService.getTaskConsumers(appScopeKey)
153
185
  Log.d(TAG, "runTasks: number of consumers ${consumers.size}")
154
186
 
155
- if (consumers.size == 0) {
187
+ if (consumers.isEmpty()) {
156
188
  return false
157
189
  }
158
190
 
@@ -1,6 +1,7 @@
1
1
  package expo.modules.backgroundtask
2
2
 
3
3
  import android.content.Context
4
+ import android.os.Build
4
5
  import android.util.Log
5
6
  import androidx.work.CoroutineWorker
6
7
  import androidx.work.Data
@@ -21,7 +22,15 @@ class BackgroundTaskWork(context: Context, params: WorkerParameters) : Coroutine
21
22
  val appScopeKey = inputData.getString("appScopeKey") ?: throw MissingAppScopeKey()
22
23
 
23
24
  try {
25
+ // Run tasks async using the task service. This call will return when the task has finished
26
+ // ie. When JS task executor has notified the task manager that it is done.
24
27
  BackgroundTaskScheduler.runTasks(applicationContext, appScopeKey)
28
+ // If we are on a newer Android version we're using a One time request and need to spawn new
29
+ // requests for each run (and also ask to not try to cancel the work, since we're already
30
+ // finishing the work item when this function returns.
31
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
32
+ BackgroundTaskScheduler.scheduleWorker(applicationContext, appScopeKey, false)
33
+ }
25
34
  } catch (e: Exception) {
26
35
  // Wrap exception in Data:
27
36
  val outputData = Data.Builder()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-background-task",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Expo universal module for BackgroundTask API",
5
5
  "main": "build/BackgroundTask.js",
6
6
  "types": "build/BackgroundTask.d.ts",
@@ -35,10 +35,10 @@
35
35
  "expo-task-manager": "~12.0.5"
36
36
  },
37
37
  "devDependencies": {
38
- "expo-module-scripts": "^4.0.0"
38
+ "expo-module-scripts": "^4.0.4"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "expo": "*"
42
42
  },
43
- "gitHead": "3fd37fd31fd818d833e85c4723b1578010da6967"
43
+ "gitHead": "7080126694798ca950d5dc3ef33483a17fa401bb"
44
44
  }