expo-notifications 0.29.5 → 0.29.7
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 +11 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/notifications/notifications/RemoteMessageSerializer.java +2 -1
- package/android/src/main/java/expo/modules/notifications/notifications/background/BackgroundRemoteNotificationTaskConsumer.java +5 -0
- package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoHandlingDelegate.kt +4 -4
- package/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt +10 -2
- package/build/registerTaskAsync.d.ts +9 -4
- package/build/registerTaskAsync.d.ts.map +1 -1
- package/build/registerTaskAsync.js +9 -4
- package/build/registerTaskAsync.js.map +1 -1
- package/package.json +2 -2
- package/plugin/build/withNotifications.d.ts +8 -0
- package/plugin/build/withNotificationsIOS.d.ts +0 -3
- package/plugin/build/withNotificationsIOS.js +24 -4
- package/plugin/src/withNotifications.ts +9 -0
- package/plugin/src/withNotificationsIOS.ts +35 -2
- package/src/registerTaskAsync.ts +9 -4
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,17 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 0.29.7 — 2024-11-13
|
|
14
|
+
|
|
15
|
+
_This version does not introduce any user-facing changes._
|
|
16
|
+
|
|
17
|
+
## 0.29.6 — 2024-11-10
|
|
18
|
+
|
|
19
|
+
### 🎉 New features
|
|
20
|
+
|
|
21
|
+
- [android] run notification tasks from killed state ([#32531](https://github.com/expo/expo/pull/32531) by [@vonovak](https://github.com/vonovak))
|
|
22
|
+
- add `enableBackgroundRemoteNotifications` option to config plugin ([#32716](https://github.com/expo/expo/pull/32716) by [@vonovak](https://github.com/vonovak))
|
|
23
|
+
|
|
13
24
|
## 0.29.5 — 2024-11-07
|
|
14
25
|
|
|
15
26
|
### 🛠 Breaking changes
|
package/android/build.gradle
CHANGED
|
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
|
|
|
2
2
|
apply plugin: 'kotlin-parcelize'
|
|
3
3
|
|
|
4
4
|
group = 'host.exp.exponent'
|
|
5
|
-
version = '0.29.
|
|
5
|
+
version = '0.29.7'
|
|
6
6
|
|
|
7
7
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
8
8
|
apply from: expoModulesCorePlugin
|
|
@@ -15,7 +15,7 @@ android {
|
|
|
15
15
|
namespace "expo.modules.notifications"
|
|
16
16
|
defaultConfig {
|
|
17
17
|
versionCode 21
|
|
18
|
-
versionName '0.29.
|
|
18
|
+
versionName '0.29.7'
|
|
19
19
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
20
20
|
}
|
|
21
21
|
|
package/android/src/main/java/expo/modules/notifications/notifications/RemoteMessageSerializer.java
CHANGED
|
@@ -6,6 +6,7 @@ import com.google.firebase.messaging.RemoteMessage;
|
|
|
6
6
|
|
|
7
7
|
import java.util.Map;
|
|
8
8
|
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
9
10
|
import androidx.annotation.Nullable;
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -19,7 +20,7 @@ public class RemoteMessageSerializer {
|
|
|
19
20
|
* @param message {@link RemoteMessage} to serialize
|
|
20
21
|
* @return Serialized message
|
|
21
22
|
*/
|
|
22
|
-
public static Bundle toBundle(RemoteMessage message) {
|
|
23
|
+
public static @NonNull Bundle toBundle(RemoteMessage message) {
|
|
23
24
|
Bundle serializedMessage = new Bundle();
|
|
24
25
|
serializedMessage.putString("collapseKey", message.getCollapseKey());
|
|
25
26
|
serializedMessage.putBundle("data", toBundle(message.getData()));
|
|
@@ -6,6 +6,7 @@ import android.content.Context;
|
|
|
6
6
|
import android.os.Bundle;
|
|
7
7
|
import android.os.PersistableBundle;
|
|
8
8
|
import android.util.Log;
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
9
10
|
|
|
10
11
|
import org.json.JSONException;
|
|
11
12
|
import org.json.JSONObject;
|
|
@@ -120,5 +121,9 @@ public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer imple
|
|
|
120
121
|
return bundle;
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
public void executeTask(@NonNull Bundle bundle) {
|
|
125
|
+
mTask.execute(bundle, null);
|
|
126
|
+
}
|
|
127
|
+
|
|
123
128
|
//endregion
|
|
124
129
|
}
|
package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoHandlingDelegate.kt
CHANGED
|
@@ -45,7 +45,7 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
sListenersReferences[listener] = WeakReference(listener)
|
|
48
|
-
if (
|
|
48
|
+
if (sPendingNotificationResponses.isNotEmpty()) {
|
|
49
49
|
val responseIterator = sPendingNotificationResponses.iterator()
|
|
50
50
|
while (responseIterator.hasNext()) {
|
|
51
51
|
listener.onNotificationResponseReceived(responseIterator.next())
|
|
@@ -139,11 +139,11 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
|
|
|
139
139
|
if (notificationResponse.action.opensAppToForeground()) {
|
|
140
140
|
openAppToForeground(context, notificationResponse)
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
if (
|
|
142
|
+
val listeners = getListeners()
|
|
143
|
+
if (listeners.isEmpty()) {
|
|
144
144
|
sPendingNotificationResponses.add(notificationResponse)
|
|
145
145
|
} else {
|
|
146
|
-
|
|
146
|
+
listeners.forEach {
|
|
147
147
|
it.onNotificationResponseReceived(notificationResponse)
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -2,6 +2,7 @@ package expo.modules.notifications.service.delegates
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import com.google.firebase.messaging.RemoteMessage
|
|
5
|
+
import expo.modules.interfaces.taskManager.TaskServiceProviderHelper
|
|
5
6
|
import expo.modules.notifications.notifications.RemoteMessageSerializer
|
|
6
7
|
import expo.modules.notifications.notifications.background.BackgroundRemoteNotificationTaskConsumer
|
|
7
8
|
import expo.modules.notifications.notifications.debug.DebugLogging
|
|
@@ -94,9 +95,16 @@ open class FirebaseMessagingDelegate(protected val context: Context) : FirebaseM
|
|
|
94
95
|
val notification = createNotification(remoteMessage)
|
|
95
96
|
DebugLogging.logNotification("FirebaseMessagingDelegate.onMessageReceived: notification", notification)
|
|
96
97
|
NotificationsService.receive(context, notification)
|
|
97
|
-
|
|
98
|
+
runTaskManagerTasks(remoteMessage)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private fun runTaskManagerTasks(remoteMessage: RemoteMessage) {
|
|
102
|
+
// getTaskServiceImpl() has a side effect:
|
|
103
|
+
// the TaskService constructor calls restoreTasks which then constructs a BackgroundRemoteNotificationTaskConsumer,
|
|
104
|
+
// and the getBackgroundTasks() call below doesn't return an empty collection.
|
|
105
|
+
TaskServiceProviderHelper.getTaskServiceImpl(context.applicationContext)
|
|
98
106
|
getBackgroundTasks().forEach {
|
|
99
|
-
it.
|
|
107
|
+
it.executeTask(RemoteMessageSerializer.toBundle(remoteMessage))
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
110
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Call `registerTaskAsync` to set a callback (task) that will run in response to when a notification is received while the app is in foreground, background, or terminated.
|
|
3
|
+
* When app is terminated, only a [data message](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) (Android) / [background notification](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#Create-a-background-notification) (iOS) triggers the task execution.
|
|
4
|
+
* However, the OS may decide not to deliver the notification to your app in some cases (e.g. when the device is in Doze mode on Android, or when you send too many notifications - Apple recommends to not ["send more than two or three per hour"](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#overview)).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Under the hood, this function is run using `expo-task-manager`. You **must** define the task first, with [`TaskManager.defineTask`](./task-manager#taskmanagerdefinetasktaskname-taskexecutor) and register it with `registerTaskAsync`.
|
|
7
|
+
*
|
|
8
|
+
* Make sure you define and register the task in the module scope of a JS module which is required early by your app (e.g. in the `index.js` file).
|
|
9
|
+
* `expo-task-manager` loads your app's JS bundle in the background and executes the task, as well as any side effects which may happen as a consequence of requiring any JS modules.
|
|
10
|
+
*
|
|
11
|
+
* The callback function you define with `TaskManager.defineTask` receives an object with the following fields:
|
|
7
12
|
* - `data`: The remote payload delivered by either FCM (Android) or APNs (iOS). See [`PushNotificationTrigger`](#pushnotificationtrigger) for details.
|
|
8
13
|
* - `error`: The error (if any) that occurred during execution of the task.
|
|
9
14
|
* - `executionInfo`: JSON object of additional info related to the task, including the `taskName`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerTaskAsync.d.ts","sourceRoot":"","sources":["../src/registerTaskAsync.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"registerTaskAsync.d.ts","sourceRoot":"","sources":["../src/registerTaskAsync.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAA8B,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E"}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { UnavailabilityError } from 'expo-modules-core';
|
|
2
2
|
import BackgroundNotificationTasksModule from './BackgroundNotificationTasksModule';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Call `registerTaskAsync` to set a callback (task) that will run in response to when a notification is received while the app is in foreground, background, or terminated.
|
|
5
|
+
* When app is terminated, only a [data message](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) (Android) / [background notification](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#Create-a-background-notification) (iOS) triggers the task execution.
|
|
6
|
+
* However, the OS may decide not to deliver the notification to your app in some cases (e.g. when the device is in Doze mode on Android, or when you send too many notifications - Apple recommends to not ["send more than two or three per hour"](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#overview)).
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Under the hood, this function is run using `expo-task-manager`. You **must** define the task first, with [`TaskManager.defineTask`](./task-manager#taskmanagerdefinetasktaskname-taskexecutor) and register it with `registerTaskAsync`.
|
|
9
|
+
*
|
|
10
|
+
* Make sure you define and register the task in the module scope of a JS module which is required early by your app (e.g. in the `index.js` file).
|
|
11
|
+
* `expo-task-manager` loads your app's JS bundle in the background and executes the task, as well as any side effects which may happen as a consequence of requiring any JS modules.
|
|
12
|
+
*
|
|
13
|
+
* The callback function you define with `TaskManager.defineTask` receives an object with the following fields:
|
|
9
14
|
* - `data`: The remote payload delivered by either FCM (Android) or APNs (iOS). See [`PushNotificationTrigger`](#pushnotificationtrigger) for details.
|
|
10
15
|
* - `error`: The error (if any) that occurred during execution of the task.
|
|
11
16
|
* - `executionInfo`: JSON object of additional info related to the task, including the `taskName`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerTaskAsync.js","sourceRoot":"","sources":["../src/registerTaskAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,iCAAiC,MAAM,qCAAqC,CAAC;AAEpF
|
|
1
|
+
{"version":3,"file":"registerTaskAsync.js","sourceRoot":"","sources":["../src/registerTaskAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,iCAAiC,MAAM,qCAAqC,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IAC9D,IAAI,CAAC,iCAAiC,CAAC,iBAAiB,EAAE;QACxD,MAAM,IAAI,mBAAmB,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;KACrE;IAED,OAAO,MAAM,iCAAiC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\n\nimport BackgroundNotificationTasksModule from './BackgroundNotificationTasksModule';\n\n/**\n * Call `registerTaskAsync` to set a callback (task) that will run in response to when a notification is received while the app is in foreground, background, or terminated.\n * When app is terminated, only a [data message](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) (Android) / [background notification](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#Create-a-background-notification) (iOS) triggers the task execution.\n * However, the OS may decide not to deliver the notification to your app in some cases (e.g. when the device is in Doze mode on Android, or when you send too many notifications - Apple recommends to not [\"send more than two or three per hour\"](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#overview)).\n *\n * Under the hood, this function is run using `expo-task-manager`. You **must** define the task first, with [`TaskManager.defineTask`](./task-manager#taskmanagerdefinetasktaskname-taskexecutor) and register it with `registerTaskAsync`.\n *\n * Make sure you define and register the task in the module scope of a JS module which is required early by your app (e.g. in the `index.js` file).\n * `expo-task-manager` loads your app's JS bundle in the background and executes the task, as well as any side effects which may happen as a consequence of requiring any JS modules.\n *\n * The callback function you define with `TaskManager.defineTask` receives an object with the following fields:\n * - `data`: The remote payload delivered by either FCM (Android) or APNs (iOS). See [`PushNotificationTrigger`](#pushnotificationtrigger) for details.\n * - `error`: The error (if any) that occurred during execution of the task.\n * - `executionInfo`: JSON object of additional info related to the task, including the `taskName`.\n * @param taskName The string you passed to `TaskManager.defineTask` as the `taskName` parameter.\n *\n * @example\n * ```ts\n * import * as TaskManager from 'expo-task-manager';\n * import * as Notifications from 'expo-notifications';\n *\n * const BACKGROUND_NOTIFICATION_TASK = 'BACKGROUND-NOTIFICATION-TASK';\n *\n * TaskManager.defineTask(BACKGROUND_NOTIFICATION_TASK, ({ data, error, executionInfo }) => {\n * console.log('Received a notification in the background!');\n * // Do something with the notification data\n * });\n *\n * Notifications.registerTaskAsync(BACKGROUND_NOTIFICATION_TASK);\n * ```\n * @header inBackground\n */\nexport default async function registerTaskAsync(taskName: string): Promise<null> {\n if (!BackgroundNotificationTasksModule.registerTaskAsync) {\n throw new UnavailabilityError('Notifications', 'registerTaskAsync');\n }\n\n return await BackgroundNotificationTasksModule.registerTaskAsync(taskName);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-notifications",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.7",
|
|
4
4
|
"description": "Provides an API to fetch push notification tokens and to present, schedule, receive, and respond to notifications.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"react": "*",
|
|
56
56
|
"react-native": "*"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "2c50bd7f0abaefb6fabcfd6d3935066724990b33"
|
|
59
59
|
}
|
|
@@ -28,6 +28,14 @@ export type NotificationsPluginProps = {
|
|
|
28
28
|
* @platform ios
|
|
29
29
|
*/
|
|
30
30
|
mode?: 'development' | 'production';
|
|
31
|
+
/**
|
|
32
|
+
* Whether to enable background remote notifications, as described in [Apple documentation](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app).
|
|
33
|
+
*
|
|
34
|
+
* This sets the `UIBackgroundModes` key in the `Info.plist` to include `remote-notification`.
|
|
35
|
+
* @default false
|
|
36
|
+
* @platform ios
|
|
37
|
+
*/
|
|
38
|
+
enableBackgroundRemoteNotifications?: boolean;
|
|
31
39
|
};
|
|
32
40
|
declare const _default: ConfigPlugin<void | NotificationsPluginProps>;
|
|
33
41
|
export default _default;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { ConfigPlugin, XcodeProject } from 'expo/config-plugins';
|
|
2
2
|
import { NotificationsPluginProps } from './withNotifications';
|
|
3
3
|
export declare const withNotificationsIOS: ConfigPlugin<NotificationsPluginProps>;
|
|
4
|
-
export declare const withNotificationSounds: ConfigPlugin<{
|
|
5
|
-
sounds: string[];
|
|
6
|
-
}>;
|
|
7
4
|
/**
|
|
8
5
|
* Save sound files to the Xcode project root and add them to the Xcode project.
|
|
9
6
|
*/
|
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setNotificationSounds = exports.
|
|
3
|
+
exports.setNotificationSounds = exports.withNotificationsIOS = void 0;
|
|
4
4
|
const config_plugins_1 = require("expo/config-plugins");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const ERROR_MSG_PREFIX = 'An error occurred while configuring iOS notifications. ';
|
|
8
|
-
const withNotificationsIOS = (config, { mode = 'development', sounds = [] }) => {
|
|
8
|
+
const withNotificationsIOS = (config, { mode = 'development', sounds = [], enableBackgroundRemoteNotifications }) => {
|
|
9
9
|
config = (0, config_plugins_1.withEntitlementsPlist)(config, (config) => {
|
|
10
10
|
if (!config.modResults['aps-environment']) {
|
|
11
11
|
config.modResults['aps-environment'] = mode;
|
|
12
12
|
}
|
|
13
13
|
return config;
|
|
14
14
|
});
|
|
15
|
-
config =
|
|
15
|
+
config = withNotificationSounds(config, { sounds });
|
|
16
|
+
config = withBackgroundRemoteNotifications(config, enableBackgroundRemoteNotifications);
|
|
16
17
|
return config;
|
|
17
18
|
};
|
|
18
19
|
exports.withNotificationsIOS = withNotificationsIOS;
|
|
20
|
+
const withBackgroundRemoteNotifications = (config, enableBackgroundRemoteNotifications) => {
|
|
21
|
+
if (!(enableBackgroundRemoteNotifications === undefined ||
|
|
22
|
+
typeof enableBackgroundRemoteNotifications === 'boolean')) {
|
|
23
|
+
throw new Error(ERROR_MSG_PREFIX +
|
|
24
|
+
`"enableBackgroundRemoteNotifications" has an invalid value: ${enableBackgroundRemoteNotifications}. Expected a boolean.`);
|
|
25
|
+
}
|
|
26
|
+
if (!enableBackgroundRemoteNotifications) {
|
|
27
|
+
return config;
|
|
28
|
+
}
|
|
29
|
+
return (0, config_plugins_1.withInfoPlist)(config, (config) => {
|
|
30
|
+
if (!Array.isArray(config.modResults.UIBackgroundModes)) {
|
|
31
|
+
config.modResults.UIBackgroundModes = [];
|
|
32
|
+
}
|
|
33
|
+
const notificationBackgroundMode = 'remote-notification';
|
|
34
|
+
if (!config.modResults.UIBackgroundModes.includes(notificationBackgroundMode)) {
|
|
35
|
+
config.modResults.UIBackgroundModes.push(notificationBackgroundMode);
|
|
36
|
+
}
|
|
37
|
+
return config;
|
|
38
|
+
});
|
|
39
|
+
};
|
|
19
40
|
const withNotificationSounds = (config, { sounds }) => {
|
|
20
41
|
return (0, config_plugins_1.withXcodeProject)(config, (config) => {
|
|
21
42
|
setNotificationSounds(config.modRequest.projectRoot, {
|
|
@@ -26,7 +47,6 @@ const withNotificationSounds = (config, { sounds }) => {
|
|
|
26
47
|
return config;
|
|
27
48
|
});
|
|
28
49
|
};
|
|
29
|
-
exports.withNotificationSounds = withNotificationSounds;
|
|
30
50
|
/**
|
|
31
51
|
* Save sound files to the Xcode project root and add them to the Xcode project.
|
|
32
52
|
*/
|
|
@@ -34,6 +34,15 @@ export type NotificationsPluginProps = {
|
|
|
34
34
|
* @platform ios
|
|
35
35
|
*/
|
|
36
36
|
mode?: 'development' | 'production';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Whether to enable background remote notifications, as described in [Apple documentation](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app).
|
|
40
|
+
*
|
|
41
|
+
* This sets the `UIBackgroundModes` key in the `Info.plist` to include `remote-notification`.
|
|
42
|
+
* @default false
|
|
43
|
+
* @platform ios
|
|
44
|
+
*/
|
|
45
|
+
enableBackgroundRemoteNotifications?: boolean;
|
|
37
46
|
};
|
|
38
47
|
|
|
39
48
|
const withNotifications: ConfigPlugin<NotificationsPluginProps | void> = (config, props) => {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
IOSConfig,
|
|
5
5
|
withXcodeProject,
|
|
6
6
|
XcodeProject,
|
|
7
|
+
withInfoPlist,
|
|
7
8
|
} from 'expo/config-plugins';
|
|
8
9
|
import { copyFileSync } from 'fs';
|
|
9
10
|
import { basename, resolve } from 'path';
|
|
@@ -14,7 +15,7 @@ const ERROR_MSG_PREFIX = 'An error occurred while configuring iOS notifications.
|
|
|
14
15
|
|
|
15
16
|
export const withNotificationsIOS: ConfigPlugin<NotificationsPluginProps> = (
|
|
16
17
|
config,
|
|
17
|
-
{ mode = 'development', sounds = [] }
|
|
18
|
+
{ mode = 'development', sounds = [], enableBackgroundRemoteNotifications }
|
|
18
19
|
) => {
|
|
19
20
|
config = withEntitlementsPlist(config, (config) => {
|
|
20
21
|
if (!config.modResults['aps-environment']) {
|
|
@@ -23,10 +24,42 @@ export const withNotificationsIOS: ConfigPlugin<NotificationsPluginProps> = (
|
|
|
23
24
|
return config;
|
|
24
25
|
});
|
|
25
26
|
config = withNotificationSounds(config, { sounds });
|
|
27
|
+
config = withBackgroundRemoteNotifications(config, enableBackgroundRemoteNotifications);
|
|
28
|
+
|
|
26
29
|
return config;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
const withBackgroundRemoteNotifications: ConfigPlugin<boolean | undefined> = (
|
|
33
|
+
config,
|
|
34
|
+
enableBackgroundRemoteNotifications
|
|
35
|
+
) => {
|
|
36
|
+
if (
|
|
37
|
+
!(
|
|
38
|
+
enableBackgroundRemoteNotifications === undefined ||
|
|
39
|
+
typeof enableBackgroundRemoteNotifications === 'boolean'
|
|
40
|
+
)
|
|
41
|
+
) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
ERROR_MSG_PREFIX +
|
|
44
|
+
`"enableBackgroundRemoteNotifications" has an invalid value: ${enableBackgroundRemoteNotifications}. Expected a boolean.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
if (!enableBackgroundRemoteNotifications) {
|
|
48
|
+
return config;
|
|
49
|
+
}
|
|
50
|
+
return withInfoPlist(config, (config) => {
|
|
51
|
+
if (!Array.isArray(config.modResults.UIBackgroundModes)) {
|
|
52
|
+
config.modResults.UIBackgroundModes = [];
|
|
53
|
+
}
|
|
54
|
+
const notificationBackgroundMode = 'remote-notification';
|
|
55
|
+
if (!config.modResults.UIBackgroundModes.includes(notificationBackgroundMode)) {
|
|
56
|
+
config.modResults.UIBackgroundModes.push(notificationBackgroundMode);
|
|
57
|
+
}
|
|
58
|
+
return config;
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const withNotificationSounds: ConfigPlugin<{ sounds: string[] }> = (config, { sounds }) => {
|
|
30
63
|
return withXcodeProject(config, (config) => {
|
|
31
64
|
setNotificationSounds(config.modRequest.projectRoot, {
|
|
32
65
|
sounds,
|
package/src/registerTaskAsync.ts
CHANGED
|
@@ -3,11 +3,16 @@ import { UnavailabilityError } from 'expo-modules-core';
|
|
|
3
3
|
import BackgroundNotificationTasksModule from './BackgroundNotificationTasksModule';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Call `registerTaskAsync` to set a callback (task) that will run in response to when a notification is received while the app is in foreground, background, or terminated.
|
|
7
|
+
* When app is terminated, only a [data message](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages) (Android) / [background notification](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#Create-a-background-notification) (iOS) triggers the task execution.
|
|
8
|
+
* However, the OS may decide not to deliver the notification to your app in some cases (e.g. when the device is in Doze mode on Android, or when you send too many notifications - Apple recommends to not ["send more than two or three per hour"](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app#overview)).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Under the hood, this function is run using `expo-task-manager`. You **must** define the task first, with [`TaskManager.defineTask`](./task-manager#taskmanagerdefinetasktaskname-taskexecutor) and register it with `registerTaskAsync`.
|
|
11
|
+
*
|
|
12
|
+
* Make sure you define and register the task in the module scope of a JS module which is required early by your app (e.g. in the `index.js` file).
|
|
13
|
+
* `expo-task-manager` loads your app's JS bundle in the background and executes the task, as well as any side effects which may happen as a consequence of requiring any JS modules.
|
|
14
|
+
*
|
|
15
|
+
* The callback function you define with `TaskManager.defineTask` receives an object with the following fields:
|
|
11
16
|
* - `data`: The remote payload delivered by either FCM (Android) or APNs (iOS). See [`PushNotificationTrigger`](#pushnotificationtrigger) for details.
|
|
12
17
|
* - `error`: The error (if any) that occurred during execution of the task.
|
|
13
18
|
* - `executionInfo`: JSON object of additional info related to the task, including the `taskName`.
|