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 +17 -3
- package/android/build.gradle +21 -9
- package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskModule.kt +1 -1
- package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskScheduler.kt +61 -29
- package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskWork.kt +9 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,8 +10,22 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
-
## 0.1.
|
|
13
|
+
## 0.1.2 — 2025-02-14
|
|
14
14
|
|
|
15
|
-
|
|
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))
|
package/android/build.gradle
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
79
|
-
val
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
38
|
+
"expo-module-scripts": "^4.0.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"expo": "*"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "7080126694798ca950d5dc3ef33483a17fa401bb"
|
|
44
44
|
}
|