expo-background-task 0.0.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.
Files changed (47) hide show
  1. package/.eslintrc.js +2 -0
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +43 -0
  4. package/android/build.gradle +24 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskConsumer.kt +54 -0
  7. package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskExceptions.kt +13 -0
  8. package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskModule.kt +66 -0
  9. package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskScheduler.kt +212 -0
  10. package/android/src/main/java/expo/modules/backgroundtask/BackgroundTaskWork.kt +36 -0
  11. package/app.plugin.js +1 -0
  12. package/build/BackgroundTask.d.ts +51 -0
  13. package/build/BackgroundTask.d.ts.map +1 -0
  14. package/build/BackgroundTask.js +89 -0
  15. package/build/BackgroundTask.js.map +1 -0
  16. package/build/BackgroundTask.types.d.ts +41 -0
  17. package/build/BackgroundTask.types.d.ts.map +1 -0
  18. package/build/BackgroundTask.types.js +31 -0
  19. package/build/BackgroundTask.types.js.map +1 -0
  20. package/build/ExpoBackgroundTaskModule.d.ts +11 -0
  21. package/build/ExpoBackgroundTaskModule.d.ts.map +1 -0
  22. package/build/ExpoBackgroundTaskModule.js +3 -0
  23. package/build/ExpoBackgroundTaskModule.js.map +1 -0
  24. package/build/ExpoBackgroundTaskModule.web.d.ts +6 -0
  25. package/build/ExpoBackgroundTaskModule.web.d.ts.map +1 -0
  26. package/build/ExpoBackgroundTaskModule.web.js +7 -0
  27. package/build/ExpoBackgroundTaskModule.web.js.map +1 -0
  28. package/expo-module.config.json +11 -0
  29. package/ios/BackgorundTaskExceptions.swift +48 -0
  30. package/ios/BackgroundTaskAppDelegate.swift +44 -0
  31. package/ios/BackgroundTaskConstants.swift +13 -0
  32. package/ios/BackgroundTaskConsumer.swift +57 -0
  33. package/ios/BackgroundTaskDebugHelper.swift +21 -0
  34. package/ios/BackgroundTaskModule.swift +78 -0
  35. package/ios/BackgroundTaskRecords.swift +12 -0
  36. package/ios/BackgroundTaskScheduler.swift +101 -0
  37. package/ios/ExpoBackgroundTask.podspec +32 -0
  38. package/package.json +43 -0
  39. package/plugin/build/withBackgroundTask.d.ts +3 -0
  40. package/plugin/build/withBackgroundTask.js +29 -0
  41. package/plugin/src/withBackgroundTask.ts +36 -0
  42. package/plugin/tsconfig.json +9 -0
  43. package/src/BackgroundTask.ts +105 -0
  44. package/src/BackgroundTask.types.ts +45 -0
  45. package/src/ExpoBackgroundTaskModule.ts +12 -0
  46. package/src/ExpoBackgroundTaskModule.web.ts +7 -0
  47. package/tsconfig.json +9 -0
package/.eslintrc.js ADDED
@@ -0,0 +1,2 @@
1
+ // @generated by expo-module-scripts
2
+ module.exports = require('expo-module-scripts/eslintrc.base.js');
package/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## Unpublished
4
+
5
+ ### 🛠 Breaking changes
6
+
7
+ ### 🎉 New features
8
+
9
+ ### 🐛 Bug fixes
10
+
11
+ ### 💡 Others
12
+
13
+ ## 0.0.0 — 2025-01-21
14
+
15
+ ### 🎉 New features
16
+
17
+ - Added expo-background-task package ([#33438](https://github.com/expo/expo/pull/33438) by [@chrfalch](https://github.com/chrfalch))
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # expo-background-task
2
+
3
+ Expo universal module for BackgroundTask API
4
+
5
+ # API documentation
6
+
7
+ - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/background-task/)
8
+ - [Documentation for the main branch](https://docs.expo.dev/versions/unversioned/sdk/background-task/)
9
+
10
+ # Installation in managed Expo projects
11
+
12
+ For [managed](https://docs.expo.dev/archive/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/background-task/).
13
+
14
+ # Installation in bare React Native projects
15
+
16
+ For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.
17
+
18
+ ### Add the package to your npm dependencies
19
+
20
+ ```
21
+ npx expo install expo-background-task
22
+ ```
23
+
24
+ ### Configure for Android
25
+
26
+ No additional set up necessary.
27
+
28
+ ### Configure for iOS
29
+
30
+ Run `npx pod-install` after installing the npm package.
31
+
32
+ In order to use `BackgroundTask` API in standalone, detached and bare apps on iOS, your app has to include the background task identifier in the `Info.plist` file. You can do this by adding the following XML snippet to your `Info.plist` file:
33
+
34
+ ```xml
35
+ <key>BGTaskSchedulerPermittedIdentifiers</key>
36
+ <array>
37
+ <string>com.expo.modules.backgroundtask.processing</string>
38
+ </array>
39
+ ```
40
+
41
+ # Contributing
42
+
43
+ Contributions are very welcome! Please refer to guidelines described in the [contributing guide](https://github.com/expo/expo#contributing).
@@ -0,0 +1,24 @@
1
+ apply plugin: 'com.android.library'
2
+
3
+ group = 'host.exp.exponent'
4
+ version = '0.0.0'
5
+
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()
12
+
13
+ dependencies {
14
+ implementation 'androidx.work:work-runtime-ktx:2.9.1'
15
+ implementation 'com.facebook.react:react-android'
16
+ }
17
+
18
+ android {
19
+ namespace "expo.modules.backgroundtask"
20
+ defaultConfig {
21
+ versionCode 23
22
+ versionName "0.0.0"
23
+ }
24
+ }
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ </manifest>
@@ -0,0 +1,54 @@
1
+ package expo.modules.backgroundtask
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import expo.modules.interfaces.taskManager.TaskConsumer
6
+ import expo.modules.interfaces.taskManager.TaskConsumerInterface
7
+ import expo.modules.interfaces.taskManager.TaskExecutionCallback
8
+ import expo.modules.interfaces.taskManager.TaskInterface
9
+ import expo.modules.interfaces.taskManager.TaskManagerUtilsInterface
10
+
11
+ class BackgroundTaskConsumer(context: Context?, taskManagerUtils: TaskManagerUtilsInterface?) :
12
+ TaskConsumer(context, taskManagerUtils), TaskConsumerInterface {
13
+
14
+ companion object {
15
+ private const val BACKGROUND_TASK_TYPE = "expo-background-task"
16
+ private val TAG = BackgroundTaskConsumer::class.java.simpleName
17
+ }
18
+
19
+ private var task: TaskInterface? = null
20
+
21
+ override fun taskType(): String {
22
+ return BACKGROUND_TASK_TYPE
23
+ }
24
+
25
+ /**
26
+ * Exposing the execute task function so that the BackgroundTaskWork (WorkManager Work unit)
27
+ * can execute the inner task. A task is only executed if the app is in the background.
28
+ * This only applies when the app is in release mode.
29
+ */
30
+ fun executeTask(callback: TaskExecutionCallback) {
31
+ Log.d(TAG, "Executing task '${task?.name}'")
32
+ taskManagerUtils.executeTask(task, null, callback)
33
+ }
34
+
35
+ override fun didRegister(task: TaskInterface) {
36
+ Log.d(TAG, "didRegister: ${task.name}")
37
+ this.task = task
38
+
39
+ val intervalMinutes = getIntervalMinutes()
40
+ BackgroundTaskScheduler.registerTask(intervalMinutes)
41
+ }
42
+
43
+ override fun didUnregister() {
44
+ Log.d(TAG, "didUnregister: ${task?.name}")
45
+ this.task = null
46
+ BackgroundTaskScheduler.unregisterTask()
47
+ }
48
+
49
+ private fun getIntervalMinutes(): Long {
50
+ val options = task?.options as? Map<String, Any?>
51
+ return (options?.get("minimumInterval") as? Number)?.toLong()
52
+ ?: BackgroundTaskScheduler.DEFAULT_INTERVAL_MINUTES
53
+ }
54
+ }
@@ -0,0 +1,13 @@
1
+ package expo.modules.backgroundtask
2
+
3
+ import expo.modules.kotlin.exception.CodedException
4
+
5
+ internal class MissingContextException : CodedException(message = "Application context not found")
6
+
7
+ internal class MissingTaskServiceException : CodedException(message = "TaskService not available.")
8
+
9
+ internal class MissingAppScopeKey : CodedException(message = "Could not find required appScopeKey in worker.")
10
+
11
+ internal class TaskMangerInterfaceNotFoundException : CodedException(message = "TaskManagerInterface not found")
12
+
13
+ internal class TestMethodNotAvailableInProductionBuild : CodedException(message = "Background tasks cannot be triggered in production builds")
@@ -0,0 +1,66 @@
1
+ package expo.modules.backgroundtask
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.common.build.ReactBuildConfig
5
+ import expo.modules.interfaces.taskManager.TaskManagerInterface
6
+ import expo.modules.kotlin.functions.Coroutine
7
+ import expo.modules.kotlin.modules.Module
8
+ import expo.modules.kotlin.modules.ModuleDefinition
9
+ import kotlinx.coroutines.runBlocking
10
+
11
+ class BackgroundTaskModule : Module() {
12
+ companion object {
13
+ private val TAG = BackgroundTaskModule::class.java.simpleName
14
+ }
15
+
16
+ private val _taskManager by lazy { appContext.legacyModule<TaskManagerInterface>() }
17
+ private val taskManager: TaskManagerInterface
18
+ get() = _taskManager ?: throw TaskMangerInterfaceNotFoundException()
19
+
20
+ override fun definition() = ModuleDefinition {
21
+ Name("ExpoBackgroundTask")
22
+
23
+ AsyncFunction("getStatusAsync") {
24
+ return@AsyncFunction 2 // WorkManager is always available on Android.
25
+ }
26
+
27
+ AsyncFunction("triggerTaskWorkerForTestingAsync") Coroutine { ->
28
+ if (ReactBuildConfig.DEBUG) {
29
+ Log.d(TAG, "Triggering tasks for testing")
30
+ appContext.reactContext?.let {
31
+ val appScopeKey = it.packageName
32
+ return@Coroutine BackgroundTaskScheduler.runTasks(it, appScopeKey)
33
+ } ?: throw MissingContextException()
34
+ } else {
35
+ throw TestMethodNotAvailableInProductionBuild()
36
+ }
37
+ }
38
+
39
+ AsyncFunction("registerTaskAsync") { taskName: String, options: Map<String, Any?> ->
40
+ Log.d(TAG, "registerTaskAsync: $taskName")
41
+ taskManager.registerTask(taskName, BackgroundTaskConsumer::class.java, options)
42
+ }
43
+
44
+ AsyncFunction("unregisterTaskAsync") { taskName: String ->
45
+ Log.d(TAG, "unregisterTaskAsync: $taskName")
46
+ taskManager.unregisterTask(taskName, BackgroundTaskConsumer::class.java)
47
+ }
48
+
49
+ OnActivityEntersBackground {
50
+ appContext.reactContext?.let {
51
+ runBlocking {
52
+ val appScopeKey = it.packageName
53
+ BackgroundTaskScheduler.startWorker(it, appScopeKey)
54
+ }
55
+ } ?: throw MissingContextException()
56
+ }
57
+
58
+ OnActivityEntersForeground {
59
+ appContext.reactContext?.let {
60
+ runBlocking {
61
+ BackgroundTaskScheduler.stopWorker(it)
62
+ }
63
+ } ?: throw MissingContextException()
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,212 @@
1
+ package expo.modules.backgroundtask
2
+
3
+ import android.content.Context
4
+ import android.os.Build
5
+ import android.util.Log
6
+ import androidx.work.Constraints
7
+ import androidx.work.Data
8
+ import androidx.work.ExistingPeriodicWorkPolicy
9
+ import androidx.work.NetworkType
10
+ import androidx.work.Operation
11
+ import androidx.work.PeriodicWorkRequestBuilder
12
+ import androidx.work.WorkInfo
13
+ import androidx.work.WorkManager
14
+ import com.google.common.util.concurrent.ListenableFuture
15
+ import expo.modules.interfaces.taskManager.TaskServiceProviderHelper
16
+ import kotlinx.coroutines.CancellationException
17
+ import kotlinx.coroutines.CompletableDeferred
18
+ import kotlinx.coroutines.Dispatchers
19
+ import kotlinx.coroutines.awaitAll
20
+ import kotlinx.coroutines.withContext
21
+ import java.time.Duration
22
+ import java.util.concurrent.TimeUnit
23
+
24
+ object BackgroundTaskScheduler {
25
+ // Default interval
26
+ const val DEFAULT_INTERVAL_MINUTES = 60L * 24L // Once every day
27
+
28
+ // Unique identifier (generated by us) to identify the worker
29
+ private const val WORKER_IDENTIFIER = "EXPO_BACKGROUND_WORKER"
30
+
31
+ // Log tag
32
+ private val TAG = BackgroundTaskScheduler::class.java.simpleName
33
+
34
+ // Number of active task consumers
35
+ private var numberOfRegisteredTasksOfThisType = 0
36
+
37
+ // Interval
38
+ private var intervalMinutes: Long = DEFAULT_INTERVAL_MINUTES
39
+
40
+ /**
41
+ * Call when a task is registered
42
+ */
43
+ fun registerTask(intervalMinutes: Long) {
44
+ numberOfRegisteredTasksOfThisType += 1
45
+ this.intervalMinutes = intervalMinutes
46
+ }
47
+
48
+ /**
49
+ * Call when a task is unregistered
50
+ */
51
+ fun unregisterTask() {
52
+ numberOfRegisteredTasksOfThisType -= 1
53
+ }
54
+
55
+ /**
56
+ * Schedules the worker task to run. The worker should run periodically.
57
+ */
58
+ suspend fun startWorker(context: Context, appScopeKey: String): Boolean {
59
+ if (numberOfRegisteredTasksOfThisType == 0) {
60
+ Log.d(TAG, "Will not enqueue worker. No registered tasks to run.")
61
+ return false
62
+ }
63
+
64
+ // Stop the current worker (if any)
65
+ stopWorker(context)
66
+
67
+ Log.d(TAG, "Enqueuing worker with identifier $WORKER_IDENTIFIER")
68
+
69
+ // Build the work request
70
+ val data = Data.Builder()
71
+ .putString("appScopeKey", appScopeKey)
72
+ .build()
73
+ val constraints = Constraints.Builder()
74
+ .setRequiresBatteryNotLow(true)
75
+ .setRequiredNetworkType(NetworkType.CONNECTED)
76
+ .build()
77
+
78
+ // Create the work request
79
+ val builder = PeriodicWorkRequestBuilder<BackgroundTaskWork>(
80
+ repeatIntervalTimeUnit = TimeUnit.MINUTES,
81
+ repeatInterval = intervalMinutes
82
+ )
83
+ .setInputData(data)
84
+ .setConstraints(constraints)
85
+
86
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
87
+ // Add minimum interval here as well so that the work doesn't start immediately
88
+ builder.setInitialDelay(Duration.ofMinutes(intervalMinutes))
89
+ }
90
+
91
+ // Create work request
92
+ val workRequest = builder.build()
93
+
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
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Cancels the worker task
114
+ */
115
+ suspend fun stopWorker(context: Context): Boolean {
116
+ if (!isWorkerRunning(context)) {
117
+ return false
118
+ }
119
+
120
+ Log.d(TAG, "Cancelling worker with identifier $WORKER_IDENTIFIER")
121
+
122
+ // Stop our main worker
123
+ val workManager = WorkManager.getInstance(context)
124
+ return try {
125
+ workManager.cancelUniqueWork(WORKER_IDENTIFIER).await()
126
+ } catch (e: Exception) {
127
+ Log.d(TAG, "Stopping worker failed with error " + e.message)
128
+ false
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Returns true if the worker task is pending
134
+ */
135
+ private suspend fun isWorkerRunning(context: Context): Boolean {
136
+ val workInfo = getWorkerInfo(context)
137
+ return workInfo?.state == WorkInfo.State.RUNNING ||
138
+ workInfo?.state == WorkInfo.State.ENQUEUED
139
+ }
140
+
141
+ /**
142
+ * Runs tasks with the given appScopeKey
143
+ */
144
+ suspend fun runTasks(context: Context, appScopeKey: String): Boolean {
145
+ // Get task service
146
+ val taskService = TaskServiceProviderHelper.getTaskServiceImpl(context)
147
+ ?: throw MissingTaskServiceException()
148
+
149
+ Log.d(TAG, "runTasks: $appScopeKey")
150
+
151
+ // Get all task consumers
152
+ val consumers = taskService.getTaskConsumers(appScopeKey)
153
+ Log.d(TAG, "runTasks: number of consumers ${consumers.size}")
154
+
155
+ if (consumers.size == 0) {
156
+ return false
157
+ }
158
+
159
+ val tasks = consumers.filterIsInstance<BackgroundTaskConsumer>()
160
+ .map { bgTaskConsumer ->
161
+ Log.d(TAG, "runTasks: executing tasks for consumer of type ${bgTaskConsumer.taskType()}")
162
+ val taskCompletion = CompletableDeferred<Unit>()
163
+ bgTaskConsumer.executeTask {
164
+ Log.d(TAG, "Task successfully finished")
165
+ taskCompletion.complete(Unit)
166
+ }
167
+ taskCompletion
168
+ }
169
+ // Await all tasks to complete
170
+ tasks.awaitAll()
171
+ return true
172
+ }
173
+
174
+ /**
175
+ * Returns the worker info object from the WorkManager if the worker has been
176
+ * registered, otherwise returns null
177
+ */
178
+ private suspend fun getWorkerInfo(context: Context): WorkInfo? {
179
+ // Get work manager
180
+ val workManager = WorkManager.getInstance(context)
181
+
182
+ return try {
183
+ val workInfos = workManager.getWorkInfosForUniqueWork(WORKER_IDENTIFIER).await()
184
+ return workInfos.firstOrNull()
185
+ } catch (e: Exception) {
186
+ Log.d(TAG, "Calling getWorkInfosForUniqueWork failed with error " + e.message)
187
+ null
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Helper function for calling functions returning an Operation
193
+ */
194
+ private suspend fun Operation.await(): Boolean = withContext(Dispatchers.IO) {
195
+ result.get()
196
+ true
197
+ }
198
+
199
+ /**
200
+ * Helper function for calling functions returning a ListenableFuture
201
+ */
202
+ private suspend fun <T> ListenableFuture<T>.await(): T = withContext(Dispatchers.IO) {
203
+ try {
204
+ get()
205
+ } catch (e: CancellationException) {
206
+ cancel(true)
207
+ throw e
208
+ } catch (e: Exception) {
209
+ throw e
210
+ }
211
+ }
212
+ }
@@ -0,0 +1,36 @@
1
+ package expo.modules.backgroundtask
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import androidx.work.CoroutineWorker
6
+ import androidx.work.Data
7
+ import androidx.work.WorkerParameters
8
+
9
+ class BackgroundTaskWork(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
10
+ companion object {
11
+ private val TAG = BackgroundTaskWork::class.java.simpleName
12
+ }
13
+
14
+ /**
15
+ * The doWork function is called by the Android WorkManager to execute scheduled work.
16
+ */
17
+ override suspend fun doWork(): Result {
18
+ Log.i(TAG, "doWork: Running worker")
19
+
20
+ // Get the app scope key
21
+ val appScopeKey = inputData.getString("appScopeKey") ?: throw MissingAppScopeKey()
22
+
23
+ try {
24
+ BackgroundTaskScheduler.runTasks(applicationContext, appScopeKey)
25
+ } catch (e: Exception) {
26
+ // Wrap exception in Data:
27
+ val outputData = Data.Builder()
28
+ .putString("error", e.message)
29
+ .putString("stackTrace", e.stackTraceToString())
30
+ .build()
31
+
32
+ return Result.failure(outputData)
33
+ }
34
+ return Result.success()
35
+ }
36
+ }
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/build/withBackgroundTask');
@@ -0,0 +1,51 @@
1
+ import { BackgroundTaskOptions, BackgroundTaskStatus } from './BackgroundTask.types';
2
+ /**
3
+ * Returns the status for the Background Task API. On web, it always returns `BackgroundTaskStatus.Restricted`,
4
+ * while on native platforms it returns `BackgroundTaskStatus.Available`.
5
+ *
6
+ * @returns A BackgroundTaskStatus enum value or `null` if not available.
7
+ */
8
+ export declare const getStatusAsync: () => Promise<BackgroundTaskStatus>;
9
+ /**
10
+ * Registers a background task with the given name. Registered tasks are saved in persistent storage and restored once the app is initialized.
11
+ * @param taskName Name of the task to register. The task needs to be defined first - see [`TaskManager.defineTask`](task-manager/#taskmanagerdefinetasktaskname-taskexecutor)
12
+ * for more details.
13
+ * @param options An object containing the background task options.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import * as TaskManager from 'expo-task-manager';
18
+ *
19
+ * // Register the task outside of the component
20
+ * TaskManager.defineTask(BACKGROUND_TASK_IDENTIFIER, () => {
21
+ * try {
22
+ * await AsyncStorage.setItem(LAST_TASK_DATE_KEY, Date.now().toString());
23
+ * } catch (error) {
24
+ * console.error('Failed to save the last fetch date', error);
25
+ * return BackgroundTaskResult.Failed;
26
+ * }
27
+ * return BackgroundTaskResult.Success;
28
+ * });
29
+ * ```
30
+ *
31
+ * You can now use the `registerTaskAsync` function to register the task:
32
+ *
33
+ * ```ts
34
+ * BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER, {});
35
+ * ```
36
+ */
37
+ export declare function registerTaskAsync(taskName: string, options?: BackgroundTaskOptions): Promise<void>;
38
+ /**
39
+ * Unregisters a background task, so the application will no longer be executing this task.
40
+ * @param taskName Name of the task to unregister.
41
+ * @return A promise which fulfils when the task is fully unregistered.
42
+ */
43
+ export declare function unregisterTaskAsync(taskName: string): Promise<void>;
44
+ /**
45
+ * When in debug mode this function will trigger running the background tasks.
46
+ * This function will only work for apps built in debug mode.
47
+ * @todo(chrfalch): When we have a usable devtools plugin we can enable this function.
48
+ * @returns A promise which fulfils when the task is triggered.
49
+ */
50
+ export { BackgroundTaskStatus, BackgroundTaskResult, BackgroundTaskOptions, } from './BackgroundTask.types';
51
+ //# sourceMappingURL=BackgroundTask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackgroundTask.d.ts","sourceRoot":"","sources":["../src/BackgroundTask.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAIrF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAa,QAAQ,oBAAoB,CAMnE,CAAC;AAGF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAWf;AAGD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAGD;;;;;GAKG;AAcH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+ import * as TaskManager from 'expo-task-manager';
3
+ import ExpoBackgroundTaskModule from './ExpoBackgroundTaskModule';
4
+ // @needsAudit
5
+ /**
6
+ * Returns the status for the Background Task API. On web, it always returns `BackgroundTaskStatus.Restricted`,
7
+ * while on native platforms it returns `BackgroundTaskStatus.Available`.
8
+ *
9
+ * @returns A BackgroundTaskStatus enum value or `null` if not available.
10
+ */
11
+ export const getStatusAsync = async () => {
12
+ if (!ExpoBackgroundTaskModule.getStatusAsync) {
13
+ throw new UnavailabilityError('BackgroundTask', 'getStatusAsync');
14
+ }
15
+ return ExpoBackgroundTaskModule.getStatusAsync();
16
+ };
17
+ // @needsAudit
18
+ /**
19
+ * Registers a background task with the given name. Registered tasks are saved in persistent storage and restored once the app is initialized.
20
+ * @param taskName Name of the task to register. The task needs to be defined first - see [`TaskManager.defineTask`](task-manager/#taskmanagerdefinetasktaskname-taskexecutor)
21
+ * for more details.
22
+ * @param options An object containing the background task options.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import * as TaskManager from 'expo-task-manager';
27
+ *
28
+ * // Register the task outside of the component
29
+ * TaskManager.defineTask(BACKGROUND_TASK_IDENTIFIER, () => {
30
+ * try {
31
+ * await AsyncStorage.setItem(LAST_TASK_DATE_KEY, Date.now().toString());
32
+ * } catch (error) {
33
+ * console.error('Failed to save the last fetch date', error);
34
+ * return BackgroundTaskResult.Failed;
35
+ * }
36
+ * return BackgroundTaskResult.Success;
37
+ * });
38
+ * ```
39
+ *
40
+ * You can now use the `registerTaskAsync` function to register the task:
41
+ *
42
+ * ```ts
43
+ * BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER, {});
44
+ * ```
45
+ */
46
+ export async function registerTaskAsync(taskName, options = {}) {
47
+ if (!ExpoBackgroundTaskModule.registerTaskAsync) {
48
+ throw new UnavailabilityError('BackgroundTask', 'registerTaskAsync');
49
+ }
50
+ if (!TaskManager.isTaskDefined(taskName)) {
51
+ throw new Error(`Task '${taskName}' is not defined. You must define a task using TaskManager.defineTask before registering.`);
52
+ }
53
+ console.log('Calling ExpoBackgroundTaskModule.registerTaskAsync', { taskName, options });
54
+ await ExpoBackgroundTaskModule.registerTaskAsync(taskName, options);
55
+ }
56
+ // @needsAudit
57
+ /**
58
+ * Unregisters a background task, so the application will no longer be executing this task.
59
+ * @param taskName Name of the task to unregister.
60
+ * @return A promise which fulfils when the task is fully unregistered.
61
+ */
62
+ export async function unregisterTaskAsync(taskName) {
63
+ if (!ExpoBackgroundTaskModule.unregisterTaskAsync) {
64
+ throw new UnavailabilityError('BackgroundTask', 'unregisterTaskAsync');
65
+ }
66
+ console.log('Calling ExpoBackgroundTaskModule.unregisterTaskAsync', taskName);
67
+ await ExpoBackgroundTaskModule.unregisterTaskAsync(taskName);
68
+ }
69
+ // @needsAudit
70
+ /**
71
+ * When in debug mode this function will trigger running the background tasks.
72
+ * This function will only work for apps built in debug mode.
73
+ * @todo(chrfalch): When we have a usable devtools plugin we can enable this function.
74
+ * @returns A promise which fulfils when the task is triggered.
75
+ */
76
+ // export async function triggerTaskWorkerForTestingAsync(): Promise<boolean> {
77
+ // if (__DEV__) {
78
+ // if (!ExpoBackgroundTaskModule.triggerTaskWorkerForTestingAsync) {
79
+ // throw new UnavailabilityError('BackgroundTask', 'triggerTaskWorkerForTestingAsync');
80
+ // }
81
+ // console.log('Calling triggerTaskWorkerForTestingAsync');
82
+ // return await ExpoBackgroundTaskModule.triggerTaskWorkerForTestingAsync();
83
+ // } else {
84
+ // return Promise.resolve(false);
85
+ // }
86
+ // }
87
+ // Export types
88
+ export { BackgroundTaskStatus, BackgroundTaskResult, } from './BackgroundTask.types';
89
+ //# sourceMappingURL=BackgroundTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackgroundTask.js","sourceRoot":"","sources":["../src/BackgroundTask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAGjD,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAElE,cAAc;AACd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAmC,EAAE;IACtE,IAAI,CAAC,wBAAwB,CAAC,cAAc,EAAE;QAC5C,MAAM,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;KACnE;IAED,OAAO,wBAAwB,CAAC,cAAc,EAAE,CAAC;AACnD,CAAC,CAAC;AAEF,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAgB,EAChB,UAAiC,EAAE;IAEnC,IAAI,CAAC,wBAAwB,CAAC,iBAAiB,EAAE;QAC/C,MAAM,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,CAAC;KACtE;IACD,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE;QACxC,MAAM,IAAI,KAAK,CACb,SAAS,QAAQ,2FAA2F,CAC7G,CAAC;KACH;IACD,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACzF,MAAM,wBAAwB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,IAAI,CAAC,wBAAwB,CAAC,mBAAmB,EAAE;QACjD,MAAM,IAAI,mBAAmB,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;KACxE;IACD,OAAO,CAAC,GAAG,CAAC,sDAAsD,EAAE,QAAQ,CAAC,CAAC;IAC9E,MAAM,wBAAwB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED,cAAc;AACd;;;;;GAKG;AACH,+EAA+E;AAC/E,mBAAmB;AACnB,wEAAwE;AACxE,6FAA6F;AAC7F,QAAQ;AACR,+DAA+D;AAC/D,gFAAgF;AAChF,aAAa;AACb,qCAAqC;AACrC,MAAM;AACN,IAAI;AAEJ,eAAe;AACf,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,wBAAwB,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport * as TaskManager from 'expo-task-manager';\n\nimport { BackgroundTaskOptions, BackgroundTaskStatus } from './BackgroundTask.types';\nimport ExpoBackgroundTaskModule from './ExpoBackgroundTaskModule';\n\n// @needsAudit\n/**\n * Returns the status for the Background Task API. On web, it always returns `BackgroundTaskStatus.Restricted`,\n * while on native platforms it returns `BackgroundTaskStatus.Available`.\n *\n * @returns A BackgroundTaskStatus enum value or `null` if not available.\n */\nexport const getStatusAsync = async (): Promise<BackgroundTaskStatus> => {\n if (!ExpoBackgroundTaskModule.getStatusAsync) {\n throw new UnavailabilityError('BackgroundTask', 'getStatusAsync');\n }\n\n return ExpoBackgroundTaskModule.getStatusAsync();\n};\n\n// @needsAudit\n/**\n * Registers a background task with the given name. Registered tasks are saved in persistent storage and restored once the app is initialized.\n * @param taskName Name of the task to register. The task needs to be defined first - see [`TaskManager.defineTask`](task-manager/#taskmanagerdefinetasktaskname-taskexecutor)\n * for more details.\n * @param options An object containing the background task options.\n *\n * @example\n * ```ts\n * import * as TaskManager from 'expo-task-manager';\n *\n * // Register the task outside of the component\n * TaskManager.defineTask(BACKGROUND_TASK_IDENTIFIER, () => {\n * try {\n * await AsyncStorage.setItem(LAST_TASK_DATE_KEY, Date.now().toString());\n * } catch (error) {\n * console.error('Failed to save the last fetch date', error);\n * return BackgroundTaskResult.Failed;\n * }\n * return BackgroundTaskResult.Success;\n * });\n * ```\n *\n * You can now use the `registerTaskAsync` function to register the task:\n *\n * ```ts\n * BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER, {});\n * ```\n */\nexport async function registerTaskAsync(\n taskName: string,\n options: BackgroundTaskOptions = {}\n): Promise<void> {\n if (!ExpoBackgroundTaskModule.registerTaskAsync) {\n throw new UnavailabilityError('BackgroundTask', 'registerTaskAsync');\n }\n if (!TaskManager.isTaskDefined(taskName)) {\n throw new Error(\n `Task '${taskName}' is not defined. You must define a task using TaskManager.defineTask before registering.`\n );\n }\n console.log('Calling ExpoBackgroundTaskModule.registerTaskAsync', { taskName, options });\n await ExpoBackgroundTaskModule.registerTaskAsync(taskName, options);\n}\n\n// @needsAudit\n/**\n * Unregisters a background task, so the application will no longer be executing this task.\n * @param taskName Name of the task to unregister.\n * @return A promise which fulfils when the task is fully unregistered.\n */\nexport async function unregisterTaskAsync(taskName: string): Promise<void> {\n if (!ExpoBackgroundTaskModule.unregisterTaskAsync) {\n throw new UnavailabilityError('BackgroundTask', 'unregisterTaskAsync');\n }\n console.log('Calling ExpoBackgroundTaskModule.unregisterTaskAsync', taskName);\n await ExpoBackgroundTaskModule.unregisterTaskAsync(taskName);\n}\n\n// @needsAudit\n/**\n * When in debug mode this function will trigger running the background tasks.\n * This function will only work for apps built in debug mode.\n * @todo(chrfalch): When we have a usable devtools plugin we can enable this function.\n * @returns A promise which fulfils when the task is triggered.\n */\n// export async function triggerTaskWorkerForTestingAsync(): Promise<boolean> {\n// if (__DEV__) {\n// if (!ExpoBackgroundTaskModule.triggerTaskWorkerForTestingAsync) {\n// throw new UnavailabilityError('BackgroundTask', 'triggerTaskWorkerForTestingAsync');\n// }\n// console.log('Calling triggerTaskWorkerForTestingAsync');\n// return await ExpoBackgroundTaskModule.triggerTaskWorkerForTestingAsync();\n// } else {\n// return Promise.resolve(false);\n// }\n// }\n\n// Export types\nexport {\n BackgroundTaskStatus,\n BackgroundTaskResult,\n BackgroundTaskOptions,\n} from './BackgroundTask.types';\n"]}