expo-notifications 1.0.0-canary-20240912-1059f85 → 1.0.0-canary-20241008-90b13ad
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 +29 -4
- package/android/build.gradle +10 -7
- package/android/src/main/java/expo/modules/notifications/Utils.kt +2 -2
- package/android/src/main/java/expo/modules/notifications/notifications/NotificationManager.java +8 -0
- package/android/src/main/java/expo/modules/notifications/notifications/NotificationSerializer.java +13 -11
- package/android/src/main/java/expo/modules/notifications/notifications/SoundResolver.java +1 -1
- package/android/src/main/java/expo/modules/notifications/notifications/background/BackgroundRemoteNotificationTaskConsumer.java +2 -1
- package/android/src/main/java/expo/modules/notifications/notifications/channels/AbstractNotificationsChannelsProvider.java +0 -60
- package/android/src/main/java/expo/modules/notifications/notifications/channels/AndroidXNotificationsChannelsProvider.kt +26 -0
- package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationsChannelsProvider.kt +13 -0
- package/android/src/main/java/expo/modules/notifications/notifications/channels/managers/AndroidXNotificationsChannelGroupManager.java +1 -2
- package/android/src/main/java/expo/modules/notifications/notifications/debug/DebugLogging.kt +3 -5
- package/android/src/main/java/expo/modules/notifications/notifications/emitting/NotificationsEmitter.kt +5 -0
- package/android/src/main/java/expo/modules/notifications/notifications/handling/NotificationsHandler.kt +3 -1
- package/android/src/main/java/expo/modules/notifications/notifications/handling/SingleNotificationHandlerTask.java +2 -4
- package/android/src/main/java/expo/modules/notifications/notifications/interfaces/INotificationContent.kt +38 -0
- package/android/src/main/java/expo/modules/notifications/notifications/interfaces/NotificationBuilder.kt +26 -0
- package/android/src/main/java/expo/modules/notifications/notifications/interfaces/NotificationListener.java +1 -1
- package/android/src/main/java/expo/modules/notifications/notifications/interfaces/NotificationTrigger.java +0 -3
- package/android/src/main/java/expo/modules/notifications/notifications/model/Notification.java +7 -7
- package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationAction.java +3 -0
- package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationCategory.java +2 -0
- package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationContent.java +64 -55
- package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationRequest.java +4 -3
- package/android/src/main/java/expo/modules/notifications/notifications/model/RemoteNotificationContent.kt +99 -0
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/ExpoNotificationPresentationModule.kt +2 -2
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/BaseNotificationBuilder.kt +148 -0
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/DownloadImage.kt +23 -0
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.kt +395 -0
- package/android/src/main/java/expo/modules/notifications/notifications/scheduling/NotificationScheduler.kt +18 -0
- package/android/src/main/java/expo/modules/notifications/notifications/triggers/MonthlyTrigger.java +85 -0
- package/android/src/main/java/expo/modules/notifications/service/NotificationsService.kt +11 -6
- package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoHandlingDelegate.kt +11 -0
- package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoPresentationDelegate.kt +25 -17
- package/android/src/main/java/expo/modules/notifications/service/delegates/FirebaseMessagingDelegate.kt +10 -22
- package/build/NotificationScheduler.types.d.ts +32 -11
- package/build/NotificationScheduler.types.d.ts.map +1 -1
- package/build/NotificationScheduler.types.js.map +1 -1
- package/build/Notifications.types.d.ts +99 -35
- package/build/Notifications.types.d.ts.map +1 -1
- package/build/Notifications.types.js +14 -0
- package/build/Notifications.types.js.map +1 -1
- package/build/NotificationsEmitter.d.ts +11 -1
- package/build/NotificationsEmitter.d.ts.map +1 -1
- package/build/NotificationsEmitter.js +36 -3
- package/build/NotificationsEmitter.js.map +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +9 -0
- package/build/index.js.map +1 -1
- package/build/scheduleNotificationAsync.d.ts +1 -1
- package/build/scheduleNotificationAsync.d.ts.map +1 -1
- package/build/scheduleNotificationAsync.js +155 -110
- package/build/scheduleNotificationAsync.js.map +1 -1
- package/build/useLastNotificationResponse.d.ts.map +1 -1
- package/build/useLastNotificationResponse.js +5 -1
- package/build/useLastNotificationResponse.js.map +1 -1
- package/ios/EXNotifications/Notifications/Emitter/EXNotificationsEmitter.h +1 -0
- package/ios/EXNotifications/Notifications/Emitter/EXNotificationsEmitter.m +8 -1
- package/ios/EXNotifications/Notifications/Scheduling/EXNotificationSchedulerModule.m +16 -0
- package/package.json +7 -7
- package/plugin/build/withNotificationsAndroid.d.ts +5 -5
- package/plugin/build/withNotificationsAndroid.js +18 -16
- package/plugin/build/withNotificationsIOS.js +3 -1
- package/plugin/src/withNotificationsAndroid.ts +18 -18
- package/plugin/src/withNotificationsIOS.ts +3 -1
- package/src/NotificationScheduler.types.ts +41 -22
- package/src/Notifications.types.ts +100 -40
- package/src/NotificationsEmitter.ts +39 -3
- package/src/index.ts +13 -0
- package/src/scheduleNotificationAsync.ts +198 -152
- package/src/useLastNotificationResponse.ts +5 -0
- package/android/src/main/java/expo/modules/notifications/notifications/JSONNotificationContentBuilder.java +0 -203
- package/android/src/main/java/expo/modules/notifications/notifications/channels/AndroidXNotificationsChannelsProvider.java +0 -38
- package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationsChannelsProvider.java +0 -13
- package/android/src/main/java/expo/modules/notifications/notifications/interfaces/NotificationBuilder.java +0 -35
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/BaseNotificationBuilder.java +0 -50
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/CategoryAwareNotificationBuilder.java +0 -80
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ChannelAwareNotificationBuilder.java +0 -134
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java +0 -292
package/CHANGELOG.md
CHANGED
|
@@ -5,21 +5,46 @@
|
|
|
5
5
|
### 🛠 Breaking changes
|
|
6
6
|
|
|
7
7
|
- Bumped iOS deployment target to 15.1. ([#30840](https://github.com/expo/expo/pull/30840), [#30862](https://github.com/expo/expo/pull/30862) by [@tsapeta](https://github.com/tsapeta))
|
|
8
|
+
- Simplify calendar trigger input types. ([#31598](https://github.com/expo/expo/pull/31598) by [@douglowder](https://github.com/douglowder))
|
|
8
9
|
|
|
9
10
|
### 🎉 New features
|
|
10
11
|
|
|
12
|
+
- Add clearLastNotificationResponseAsync to API. ([#31607](https://github.com/expo/expo/pull/31607) by [@douglowder](https://github.com/douglowder))
|
|
13
|
+
- New monthly trigger type for scheduled notifications. ([#31823](https://github.com/expo/expo/pull/31823) by [@douglowder](https://github.com/douglowder))
|
|
14
|
+
|
|
11
15
|
### 🐛 Bug fixes
|
|
12
16
|
|
|
13
|
-
-
|
|
17
|
+
- throw improved error on invalid subscription in removeNotificationSubscription ([#31842](https://github.com/expo/expo/pull/31842) by [@vonovak](https://github.com/vonovak))
|
|
18
|
+
- [android] fix notifications actions not being presented ([#31795](https://github.com/expo/expo/pull/31795) by [@vonovak](https://github.com/vonovak))
|
|
14
19
|
- Add missing `react` and `react-native` peer dependencies for isolated modules. ([#30478](https://github.com/expo/expo/pull/30478) by [@byCedric](https://github.com/byCedric))
|
|
15
|
-
- [
|
|
16
|
-
- [Android] Fix content.data in scheduled notifications surfaced to JS. ([#31048](https://github.com/expo/expo/pull/31048) by [@douglowder](https://github.com/douglowder))
|
|
17
|
-
- [Android] fix local notifications with null trigger. ([#31157](https://github.com/expo/expo/pull/31157) by [@douglowder](https://github.com/douglowder))
|
|
20
|
+
- [iOS] do not overwrite existing aps entitlement. ([#31892](https://github.com/expo/expo/pull/31892) by [@douglowder](https://github.com/douglowder))
|
|
18
21
|
|
|
19
22
|
### 💡 Others
|
|
20
23
|
|
|
24
|
+
- [android] refactor ExpoNotificationBuilder ([#31838](https://github.com/expo/expo/pull/31838) by [@vonovak](https://github.com/vonovak))
|
|
25
|
+
- Warn about limited support in Expo Go ([#31573](https://github.com/expo/expo/pull/31573) by [@vonovak](https://github.com/vonovak))
|
|
21
26
|
- Keep using the legacy event emitter as the module is not fully migrated to Expo Modules API. ([#28946](https://github.com/expo/expo/pull/28946) by [@tsapeta](https://github.com/tsapeta))
|
|
22
27
|
|
|
28
|
+
## 0.28.17 - 2024-09-17
|
|
29
|
+
|
|
30
|
+
### 🐛 Bug fixes
|
|
31
|
+
|
|
32
|
+
- [Android] image was missing on android when in foreground ([#31405](https://github.com/expo/expo/pull/31405) by [@vonovak](https://github.com/vonovak))
|
|
33
|
+
- [Android] fix local notifications with null trigger. ([#31157](https://github.com/expo/expo/pull/31157) by [@douglowder](https://github.com/douglowder))
|
|
34
|
+
- [Android] Take `channelId` into account when presenting notifications. ([#31201](https://github.com/expo/expo/pull/31201) by [@vonovak](https://github.com/vonovak))
|
|
35
|
+
|
|
36
|
+
## 0.28.16 - 2024-08-21
|
|
37
|
+
|
|
38
|
+
### 🐛 Bug fixes
|
|
39
|
+
|
|
40
|
+
- [Android] Fix content.data in scheduled notifications surfaced to JS. ([#31048](https://github.com/expo/expo/pull/31048) by [@douglowder](https://github.com/douglowder))
|
|
41
|
+
|
|
42
|
+
## 0.28.15 - 2024-08-05
|
|
43
|
+
|
|
44
|
+
### 🐛 Bug fixes
|
|
45
|
+
|
|
46
|
+
- [Android] Eliminate unsupported types when processing notification intents from onCreate/onNewIntent. ([#30750](https://github.com/expo/expo/pull/30750) by [@douglowder](https://github.com/douglowder))
|
|
47
|
+
|
|
23
48
|
## 0.28.14 - 2024-07-30
|
|
24
49
|
|
|
25
50
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -15,6 +15,7 @@ android {
|
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 21
|
|
17
17
|
versionName '0.28.3'
|
|
18
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
buildFeatures {
|
|
@@ -34,17 +35,19 @@ android {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
dependencies {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
implementation 'androidx.core:core:1.6.0'
|
|
39
|
+
implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0'
|
|
40
|
+
implementation 'androidx.lifecycle:lifecycle-process:2.2.0'
|
|
41
|
+
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
|
|
42
|
+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
|
|
41
43
|
|
|
44
|
+
// release notes in https://firebase.google.com/support/release-notes/android - cmd + f "Cloud Messaging version"
|
|
45
|
+
implementation 'com.google.firebase:firebase-messaging:24.0.1'
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
api 'me.leolin:ShortcutBadger:1.1.22@aar'
|
|
47
|
+
implementation 'me.leolin:ShortcutBadger:1.1.22@aar'
|
|
46
48
|
|
|
47
49
|
if (project.findProject(':expo-modules-test-core')) {
|
|
48
50
|
testImplementation project(':expo-modules-test-core')
|
|
51
|
+
androidTestImplementation project(':expo-modules-test-core')
|
|
49
52
|
}
|
|
50
53
|
}
|
|
@@ -90,11 +90,11 @@ internal fun isValidJSONString(test: Any?): Boolean {
|
|
|
90
90
|
when (test is String) {
|
|
91
91
|
true -> {
|
|
92
92
|
try {
|
|
93
|
-
JSONObject(test
|
|
93
|
+
JSONObject(test)
|
|
94
94
|
return true
|
|
95
95
|
} catch (objectEx: JSONException) {
|
|
96
96
|
try {
|
|
97
|
-
JSONArray(test
|
|
97
|
+
JSONArray(test)
|
|
98
98
|
return true
|
|
99
99
|
} catch (arrayEx: JSONException) {
|
|
100
100
|
return false
|
package/android/src/main/java/expo/modules/notifications/notifications/NotificationManager.java
CHANGED
|
@@ -30,6 +30,10 @@ public class NotificationManager implements SingletonModule, expo.modules.notifi
|
|
|
30
30
|
public NotificationManager() {
|
|
31
31
|
mListenerReferenceMap = new WeakHashMap<>();
|
|
32
32
|
|
|
33
|
+
// TODO @vonovak there's a chain of listeners:
|
|
34
|
+
// ExpoHandlingDelegate -> NotificationManager -> NotificationsEmitter
|
|
35
|
+
// -> NotificationsHandler
|
|
36
|
+
// it seems it could be shorter?
|
|
33
37
|
// Registers this singleton instance in static ExpoHandlingDelegate listeners collection.
|
|
34
38
|
// Since it doesn't hold strong reference to the object this should be safe.
|
|
35
39
|
ExpoHandlingDelegate.Companion.addListener(this);
|
|
@@ -81,6 +85,10 @@ public class NotificationManager implements SingletonModule, expo.modules.notifi
|
|
|
81
85
|
* Calls {@link NotificationListener#onNotificationReceived(Notification)} on all values
|
|
82
86
|
* of {@link NotificationManager#mListenerReferenceMap}.
|
|
83
87
|
*
|
|
88
|
+
* In practice, that means calling {@link NotificationsEmitter} (just emits an event to JS) and
|
|
89
|
+
* {@link NotificationsHandler} which calls `handleNotification` in JS to determine the behavior.
|
|
90
|
+
* Then `SingleNotificationHandlerTask.processNotificationWithBehavior` may present it.
|
|
91
|
+
*
|
|
84
92
|
* @param notification Notification received
|
|
85
93
|
*/
|
|
86
94
|
public void onNotificationReceived(Notification notification) {
|
package/android/src/main/java/expo/modules/notifications/notifications/NotificationSerializer.java
CHANGED
|
@@ -3,7 +3,6 @@ package expo.modules.notifications.notifications;
|
|
|
3
3
|
import static expo.modules.notifications.UtilsKt.filteredBundleForJSTypeConverter;
|
|
4
4
|
import static expo.modules.notifications.UtilsKt.isValidJSONString;
|
|
5
5
|
|
|
6
|
-
import android.os.Build;
|
|
7
6
|
import android.os.Bundle;
|
|
8
7
|
|
|
9
8
|
import androidx.annotation.Nullable;
|
|
@@ -22,10 +21,10 @@ import java.util.List;
|
|
|
22
21
|
import java.util.Map;
|
|
23
22
|
import java.util.Set;
|
|
24
23
|
|
|
24
|
+
import expo.modules.notifications.notifications.interfaces.INotificationContent;
|
|
25
25
|
import expo.modules.notifications.notifications.interfaces.NotificationTrigger;
|
|
26
26
|
import expo.modules.notifications.notifications.interfaces.SchedulableNotificationTrigger;
|
|
27
27
|
import expo.modules.notifications.notifications.model.Notification;
|
|
28
|
-
import expo.modules.notifications.notifications.model.NotificationContent;
|
|
29
28
|
import expo.modules.notifications.notifications.model.NotificationRequest;
|
|
30
29
|
import expo.modules.notifications.notifications.model.NotificationResponse;
|
|
31
30
|
import expo.modules.notifications.notifications.model.TextInputNotificationResponse;
|
|
@@ -33,6 +32,7 @@ import expo.modules.notifications.notifications.model.triggers.FirebaseNotificat
|
|
|
33
32
|
|
|
34
33
|
import expo.modules.notifications.notifications.triggers.DailyTrigger;
|
|
35
34
|
import expo.modules.notifications.notifications.triggers.DateTrigger;
|
|
35
|
+
import expo.modules.notifications.notifications.triggers.MonthlyTrigger;
|
|
36
36
|
import expo.modules.notifications.notifications.triggers.TimeIntervalTrigger;
|
|
37
37
|
import expo.modules.notifications.notifications.triggers.WeeklyTrigger;
|
|
38
38
|
import expo.modules.notifications.notifications.triggers.YearlyTrigger;
|
|
@@ -51,7 +51,7 @@ public class NotificationSerializer {
|
|
|
51
51
|
public static Bundle toBundle(Notification notification) {
|
|
52
52
|
Bundle serializedNotification = new Bundle();
|
|
53
53
|
serializedNotification.putBundle("request", toBundle(notification.getNotificationRequest()));
|
|
54
|
-
serializedNotification.putLong("date", notification.
|
|
54
|
+
serializedNotification.putLong("date", notification.getOriginDate().getTime());
|
|
55
55
|
return serializedNotification;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -99,10 +99,10 @@ public class NotificationSerializer {
|
|
|
99
99
|
return result;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
public static Bundle toBundle(
|
|
102
|
+
public static Bundle toBundle(INotificationContent content) {
|
|
103
103
|
Bundle serializedContent = new Bundle();
|
|
104
104
|
serializedContent.putString("title", content.getTitle());
|
|
105
|
-
serializedContent.putString("subtitle", content.
|
|
105
|
+
serializedContent.putString("subtitle", content.getSubText());
|
|
106
106
|
serializedContent.putString("body", content.getText());
|
|
107
107
|
if (content.getColor() != null) {
|
|
108
108
|
serializedContent.putString("color", String.format("#%08X", content.getColor().intValue()));
|
|
@@ -113,9 +113,9 @@ public class NotificationSerializer {
|
|
|
113
113
|
} else {
|
|
114
114
|
serializedContent.putString("badge", null);
|
|
115
115
|
}
|
|
116
|
-
if (content.
|
|
116
|
+
if (content.getShouldPlayDefaultSound()) {
|
|
117
117
|
serializedContent.putString("sound", "default");
|
|
118
|
-
} else if (content.
|
|
118
|
+
} else if (content.getSoundName() != null) {
|
|
119
119
|
serializedContent.putString("sound", "custom");
|
|
120
120
|
} else {
|
|
121
121
|
serializedContent.putString("sound", null);
|
|
@@ -212,6 +212,11 @@ public class NotificationSerializer {
|
|
|
212
212
|
bundle.putInt("weekday", ((WeeklyTrigger) trigger).getWeekday());
|
|
213
213
|
bundle.putInt("hour", ((WeeklyTrigger) trigger).getHour());
|
|
214
214
|
bundle.putInt("minute", ((WeeklyTrigger) trigger).getMinute());
|
|
215
|
+
} else if (trigger instanceof MonthlyTrigger) {
|
|
216
|
+
bundle.putString("type", "monthly");
|
|
217
|
+
bundle.putInt("day", ((MonthlyTrigger) trigger).getDay());
|
|
218
|
+
bundle.putInt("hour", ((MonthlyTrigger) trigger).getHour());
|
|
219
|
+
bundle.putInt("minute", ((MonthlyTrigger) trigger).getMinute());
|
|
215
220
|
} else if (trigger instanceof YearlyTrigger) {
|
|
216
221
|
bundle.putString("type", "yearly");
|
|
217
222
|
bundle.putInt("day", ((YearlyTrigger) trigger).getDay());
|
|
@@ -228,10 +233,7 @@ public class NotificationSerializer {
|
|
|
228
233
|
|
|
229
234
|
@Nullable
|
|
230
235
|
private static String getChannelId(NotificationTrigger trigger) {
|
|
231
|
-
|
|
232
|
-
return trigger.getNotificationChannel();
|
|
233
|
-
}
|
|
234
|
-
return null;
|
|
236
|
+
return trigger.getNotificationChannel();
|
|
235
237
|
}
|
|
236
238
|
|
|
237
239
|
@NotNull
|
|
@@ -9,7 +9,7 @@ import androidx.annotation.Nullable;
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A shared logic between ContentBuilders ({@link ArgumentsNotificationContentBuilder}
|
|
12
|
-
* and {@link
|
|
12
|
+
* and {@link RemoteNotificationContent}) for resolving sounds based on the "soundName" property.
|
|
13
13
|
*/
|
|
14
14
|
public class SoundResolver {
|
|
15
15
|
private Context mContext;
|
|
@@ -25,9 +25,10 @@ import expo.modules.interfaces.taskManager.TaskManagerUtilsInterface;
|
|
|
25
25
|
/**
|
|
26
26
|
* Represents a task to be run when the app is receives a remote push
|
|
27
27
|
* notification. Map of current tasks is maintained in {@link FirebaseMessagingDelegate}.
|
|
28
|
+
*
|
|
29
|
+
* Instances are instantiated by expo task manager, after being registered in ExpoBackgroundNotificationTasksModule
|
|
28
30
|
*/
|
|
29
31
|
public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer implements TaskConsumerInterface {
|
|
30
|
-
private static final String TAG = BackgroundRemoteNotificationTaskConsumer.class.getSimpleName();
|
|
31
32
|
private static final String NOTIFICATION_KEY = "notification";
|
|
32
33
|
|
|
33
34
|
private TaskInterface mTask;
|
|
@@ -2,25 +2,13 @@ package expo.modules.notifications.notifications.channels;
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
|
|
5
|
-
import expo.modules.core.ModuleRegistry;
|
|
6
5
|
import expo.modules.core.interfaces.InternalModule;
|
|
7
6
|
|
|
8
7
|
import java.util.Collections;
|
|
9
8
|
import java.util.List;
|
|
10
9
|
|
|
11
|
-
import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager;
|
|
12
|
-
import expo.modules.notifications.notifications.channels.managers.NotificationsChannelManager;
|
|
13
|
-
import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer;
|
|
14
|
-
import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer;
|
|
15
|
-
|
|
16
10
|
public abstract class AbstractNotificationsChannelsProvider implements NotificationsChannelsProvider, InternalModule {
|
|
17
11
|
protected final Context mContext;
|
|
18
|
-
private NotificationsChannelManager mChannelManager;
|
|
19
|
-
private NotificationsChannelGroupManager mChannelGroupManager;
|
|
20
|
-
private NotificationsChannelSerializer mChannelSerializer;
|
|
21
|
-
private NotificationsChannelGroupSerializer mChannelGroupSerializer;
|
|
22
|
-
|
|
23
|
-
private ModuleRegistry mModuleRegistry;
|
|
24
12
|
|
|
25
13
|
public AbstractNotificationsChannelsProvider(Context context) {
|
|
26
14
|
mContext = context;
|
|
@@ -30,52 +18,4 @@ public abstract class AbstractNotificationsChannelsProvider implements Notificat
|
|
|
30
18
|
return Collections.singletonList(NotificationsChannelsProvider.class);
|
|
31
19
|
}
|
|
32
20
|
|
|
33
|
-
@Override
|
|
34
|
-
public void onCreate(ModuleRegistry moduleRegistry) {
|
|
35
|
-
mModuleRegistry = moduleRegistry;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public final ModuleRegistry getModuleRegistry() {
|
|
39
|
-
return mModuleRegistry;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@Override
|
|
43
|
-
public final NotificationsChannelManager getChannelManager() {
|
|
44
|
-
if (mChannelManager == null) {
|
|
45
|
-
mChannelManager = createChannelManager();
|
|
46
|
-
}
|
|
47
|
-
return mChannelManager;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
@Override
|
|
51
|
-
public final NotificationsChannelGroupManager getGroupManager() {
|
|
52
|
-
if (mChannelGroupManager == null) {
|
|
53
|
-
mChannelGroupManager = createChannelGroupManager();
|
|
54
|
-
}
|
|
55
|
-
return mChannelGroupManager;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
@Override
|
|
59
|
-
public final NotificationsChannelSerializer getChannelSerializer() {
|
|
60
|
-
if (mChannelSerializer == null) {
|
|
61
|
-
mChannelSerializer = createChannelSerializer();
|
|
62
|
-
}
|
|
63
|
-
return mChannelSerializer;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
@Override
|
|
67
|
-
public final NotificationsChannelGroupSerializer getGroupSerializer() {
|
|
68
|
-
if (mChannelGroupSerializer == null) {
|
|
69
|
-
mChannelGroupSerializer = createChannelGroupSerializer();
|
|
70
|
-
}
|
|
71
|
-
return mChannelGroupSerializer;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
protected abstract NotificationsChannelManager createChannelManager();
|
|
75
|
-
|
|
76
|
-
protected abstract NotificationsChannelGroupManager createChannelGroupManager();
|
|
77
|
-
|
|
78
|
-
protected abstract NotificationsChannelSerializer createChannelSerializer();
|
|
79
|
-
|
|
80
|
-
protected abstract NotificationsChannelGroupSerializer createChannelGroupSerializer();
|
|
81
21
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package expo.modules.notifications.notifications.channels
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import expo.modules.notifications.notifications.channels.managers.AndroidXNotificationsChannelGroupManager
|
|
5
|
+
import expo.modules.notifications.notifications.channels.managers.AndroidXNotificationsChannelManager
|
|
6
|
+
import expo.modules.notifications.notifications.channels.serializers.ExpoNotificationsChannelGroupSerializer
|
|
7
|
+
import expo.modules.notifications.notifications.channels.serializers.ExpoNotificationsChannelSerializer
|
|
8
|
+
|
|
9
|
+
class AndroidXNotificationsChannelsProvider(context: Context) : AbstractNotificationsChannelsProvider(context) {
|
|
10
|
+
|
|
11
|
+
override val groupManager by lazy {
|
|
12
|
+
AndroidXNotificationsChannelGroupManager(context)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
override val channelManager by lazy {
|
|
16
|
+
AndroidXNotificationsChannelManager(context, groupManager)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override val channelSerializer by lazy {
|
|
20
|
+
ExpoNotificationsChannelSerializer()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
override val groupSerializer by lazy {
|
|
24
|
+
ExpoNotificationsChannelGroupSerializer(channelSerializer)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package expo.modules.notifications.notifications.channels
|
|
2
|
+
|
|
3
|
+
import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager
|
|
4
|
+
import expo.modules.notifications.notifications.channels.managers.NotificationsChannelManager
|
|
5
|
+
import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer
|
|
6
|
+
import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer
|
|
7
|
+
|
|
8
|
+
interface NotificationsChannelsProvider {
|
|
9
|
+
val channelManager: NotificationsChannelManager
|
|
10
|
+
val groupManager: NotificationsChannelGroupManager
|
|
11
|
+
val channelSerializer: NotificationsChannelSerializer
|
|
12
|
+
val groupSerializer: NotificationsChannelGroupSerializer
|
|
13
|
+
}
|
|
@@ -54,10 +54,9 @@ public class AndroidXNotificationsChannelGroupManager implements NotificationsCh
|
|
|
54
54
|
// Processing options
|
|
55
55
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
56
56
|
protected void configureGroupWithOptions(Object maybeGroup, ReadableArguments groupOptions) {
|
|
57
|
-
if (!(maybeGroup instanceof NotificationChannelGroup)) {
|
|
57
|
+
if (!(maybeGroup instanceof NotificationChannelGroup group)) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
NotificationChannelGroup group = (NotificationChannelGroup) maybeGroup;
|
|
61
60
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
62
61
|
if (groupOptions.containsKey(DESCRIPTION_KEY)) {
|
|
63
62
|
group.setDescription(groupOptions.getString(DESCRIPTION_KEY));
|
package/android/src/main/java/expo/modules/notifications/notifications/debug/DebugLogging.kt
CHANGED
|
@@ -61,7 +61,6 @@ object DebugLogging {
|
|
|
61
61
|
Log.i("expo-notifications", logMessage)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
@RequiresApi(Build.VERSION_CODES.O)
|
|
65
64
|
fun logNotification(caller: String, notification: Notification) {
|
|
66
65
|
if (!BuildConfig.DEBUG) {
|
|
67
66
|
// Do not log for release/production builds
|
|
@@ -71,14 +70,13 @@ object DebugLogging {
|
|
|
71
70
|
"""
|
|
72
71
|
$caller:
|
|
73
72
|
notification.notificationRequest.content.title: ${notification.notificationRequest.content.title}
|
|
74
|
-
notification.notificationRequest.content.
|
|
73
|
+
notification.notificationRequest.content.subText: ${notification.notificationRequest.content.subText}
|
|
75
74
|
notification.notificationRequest.content.text: ${notification.notificationRequest.content.text}
|
|
76
|
-
notification.notificationRequest.content.sound: ${notification.notificationRequest.content.
|
|
75
|
+
notification.notificationRequest.content.sound: ${notification.notificationRequest.content.soundName}
|
|
77
76
|
notification.notificationRequest.content.channelID: ${notification.notificationRequest.trigger.notificationChannel}
|
|
78
77
|
notification.notificationRequest.content.body: ${notification.notificationRequest.content.body}
|
|
79
78
|
notification.notificationRequest.content.color: ${notification.notificationRequest.content.color}
|
|
80
|
-
notification.notificationRequest.content.vibrationPattern: ${notification.notificationRequest.content.vibrationPattern
|
|
81
|
-
notification.notificationRequest.trigger.notificationChannel: ${notification.notificationRequest.trigger.notificationChannel}
|
|
79
|
+
notification.notificationRequest.content.vibrationPattern: ${notification.notificationRequest.content.vibrationPattern?.contentToString()}
|
|
82
80
|
notification.notificationRequest.identifier: ${notification.notificationRequest.identifier}
|
|
83
81
|
""".trimIndent()
|
|
84
82
|
|
|
@@ -41,6 +41,11 @@ open class NotificationsEmitter : Module(), NotificationListener {
|
|
|
41
41
|
AsyncFunction<Bundle?>("getLastNotificationResponseAsync") {
|
|
42
42
|
lastNotificationResponseBundle
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
AsyncFunction("clearLastNotificationResponseAsync") {
|
|
46
|
+
lastNotificationResponseBundle = null
|
|
47
|
+
null
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
/**
|
|
@@ -99,7 +99,7 @@ open class NotificationsHandler : Module(), NotificationListener {
|
|
|
99
99
|
?: throw NotificationWasAlreadyHandledException(identifier)
|
|
100
100
|
|
|
101
101
|
with(behavior) {
|
|
102
|
-
task.
|
|
102
|
+
task.processNotificationWithBehavior(
|
|
103
103
|
NotificationBehavior(shouldShowAlert, shouldPlaySound, shouldSetBadge, priority),
|
|
104
104
|
promise
|
|
105
105
|
)
|
|
@@ -110,6 +110,8 @@ open class NotificationsHandler : Module(), NotificationListener {
|
|
|
110
110
|
* Callback called by [NotificationManager] to inform its listeners of new messages.
|
|
111
111
|
* Starts up a new [SingleNotificationHandlerTask] which will take it on from here.
|
|
112
112
|
*
|
|
113
|
+
* SingleNotificationHandlerTask.processNotificationWithBehavior can then present it
|
|
114
|
+
*
|
|
113
115
|
* @param notification Notification received
|
|
114
116
|
*/
|
|
115
117
|
override fun onNotificationReceived(notification: Notification) {
|
|
@@ -34,7 +34,6 @@ public class SingleNotificationHandlerTask {
|
|
|
34
34
|
private Handler mHandler;
|
|
35
35
|
private EventEmitter mEventEmitter;
|
|
36
36
|
private Notification mNotification;
|
|
37
|
-
private NotificationBehavior mBehavior;
|
|
38
37
|
private Context mContext;
|
|
39
38
|
private NotificationsHandler mDelegate;
|
|
40
39
|
|
|
@@ -88,12 +87,11 @@ public class SingleNotificationHandlerTask {
|
|
|
88
87
|
* @param behavior Behavior requested by the app
|
|
89
88
|
* @param promise Promise to fulfill once the behavior is applied to the notification.
|
|
90
89
|
*/
|
|
91
|
-
/* package */ void
|
|
92
|
-
mBehavior = behavior;
|
|
90
|
+
/* package */ void processNotificationWithBehavior(final NotificationBehavior behavior, final Promise promise) {
|
|
93
91
|
mHandler.post(new Runnable() {
|
|
94
92
|
@Override
|
|
95
93
|
public void run() {
|
|
96
|
-
NotificationsService.Companion.present(mContext, mNotification,
|
|
94
|
+
NotificationsService.Companion.present(mContext, mNotification, behavior, new ResultReceiver(mHandler) {
|
|
97
95
|
@Override
|
|
98
96
|
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
|
99
97
|
super.onReceiveResult(resultCode, resultData);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package expo.modules.notifications.notifications.interfaces
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.os.Parcelable
|
|
6
|
+
import expo.modules.notifications.notifications.enums.NotificationPriority
|
|
7
|
+
import org.json.JSONObject
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This interface is implemented by classes representing notification content.
|
|
11
|
+
* I.e. local notifications [NotificationContent] and remote notifications [RemoteNotificationContent].
|
|
12
|
+
*
|
|
13
|
+
* The reason the two classes exist is that one is persisted locally in SharedPreferences, and the other is not.
|
|
14
|
+
* The first is therefore a bit "fragile" and harder to refactor, while the second is easier to change.
|
|
15
|
+
* This interface exists to provide a common API for both classes.
|
|
16
|
+
* */
|
|
17
|
+
interface INotificationContent : Parcelable {
|
|
18
|
+
val title: String?
|
|
19
|
+
val text: String?
|
|
20
|
+
val subText: String?
|
|
21
|
+
val badgeCount: Number?
|
|
22
|
+
val shouldPlayDefaultSound: Boolean
|
|
23
|
+
|
|
24
|
+
// soundName is better off as a string (was an Uri) because in RemoteNotification we can obtain the sound name
|
|
25
|
+
// in local notification we store the uri and derive the sound name from it
|
|
26
|
+
val soundName: String?
|
|
27
|
+
val shouldUseDefaultVibrationPattern: Boolean
|
|
28
|
+
val vibrationPattern: LongArray?
|
|
29
|
+
val body: JSONObject?
|
|
30
|
+
val priority: NotificationPriority?
|
|
31
|
+
val color: Number?
|
|
32
|
+
val isAutoDismiss: Boolean
|
|
33
|
+
val categoryId: String?
|
|
34
|
+
val isSticky: Boolean
|
|
35
|
+
|
|
36
|
+
fun containsImage(): Boolean
|
|
37
|
+
suspend fun getImage(context: Context): Bitmap?
|
|
38
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package expo.modules.notifications.notifications.interfaces
|
|
2
|
+
|
|
3
|
+
import expo.modules.notifications.notifications.model.Notification
|
|
4
|
+
import expo.modules.notifications.notifications.model.NotificationBehavior
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* An object capable of building a [Notification] based
|
|
8
|
+
* on a [NotificationContent] spec.
|
|
9
|
+
*/
|
|
10
|
+
interface NotificationBuilder {
|
|
11
|
+
/**
|
|
12
|
+
* Pass in a [NotificationBehavior] if you want to override the behavior
|
|
13
|
+
* of the notification, i.e. whether it should show a heads-up alert, set badge, etc.
|
|
14
|
+
*
|
|
15
|
+
* @param behavior [NotificationBehavior] to which the presentation effect should conform.
|
|
16
|
+
* @return The same instance of [NotificationBuilder] updated with the remote message.
|
|
17
|
+
*/
|
|
18
|
+
fun setAllowedBehavior(behavior: NotificationBehavior?): NotificationBuilder
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Builds the Android notification based on passed in data.
|
|
22
|
+
*
|
|
23
|
+
* @return Built notification.
|
|
24
|
+
*/
|
|
25
|
+
suspend fun build(): android.app.Notification
|
|
26
|
+
}
|
|
@@ -13,7 +13,7 @@ import expo.modules.notifications.notifications.model.NotificationResponse;
|
|
|
13
13
|
*/
|
|
14
14
|
public interface NotificationListener {
|
|
15
15
|
/**
|
|
16
|
-
* Callback called when new notification is received.
|
|
16
|
+
* Callback called when new notification is received while the app is in foreground.
|
|
17
17
|
*
|
|
18
18
|
* @param notification Notification received
|
|
19
19
|
*/
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
package expo.modules.notifications.notifications.interfaces;
|
|
2
2
|
|
|
3
|
-
import android.os.Build;
|
|
4
3
|
import android.os.Parcelable;
|
|
5
4
|
|
|
6
5
|
import androidx.annotation.Nullable;
|
|
7
|
-
import androidx.annotation.RequiresApi;
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* An interface specifying source of the notification, to be implemented
|
|
@@ -12,7 +10,6 @@ import androidx.annotation.RequiresApi;
|
|
|
12
10
|
*/
|
|
13
11
|
public interface NotificationTrigger extends Parcelable {
|
|
14
12
|
@Nullable
|
|
15
|
-
@RequiresApi(api = Build.VERSION_CODES.O)
|
|
16
13
|
default String getNotificationChannel() {
|
|
17
14
|
return null;
|
|
18
15
|
}
|
package/android/src/main/java/expo/modules/notifications/notifications/model/Notification.java
CHANGED
|
@@ -6,11 +6,11 @@ import android.os.Parcelable;
|
|
|
6
6
|
import java.util.Date;
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* A class representing a single notification
|
|
9
|
+
* A class representing a single notification. Origin date ({@link #mOriginDate}) is time when it was sent (remote) or when it was posted (local).
|
|
10
10
|
*/
|
|
11
11
|
public class Notification implements Parcelable {
|
|
12
12
|
private NotificationRequest mRequest;
|
|
13
|
-
private Date
|
|
13
|
+
private Date mOriginDate;
|
|
14
14
|
|
|
15
15
|
public Notification(NotificationRequest request) {
|
|
16
16
|
this(request, new Date());
|
|
@@ -18,16 +18,16 @@ public class Notification implements Parcelable {
|
|
|
18
18
|
|
|
19
19
|
public Notification(NotificationRequest request, Date date) {
|
|
20
20
|
mRequest = request;
|
|
21
|
-
|
|
21
|
+
mOriginDate = date;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
protected Notification(Parcel in) {
|
|
25
25
|
mRequest = in.readParcelable(getClass().getClassLoader());
|
|
26
|
-
|
|
26
|
+
mOriginDate = new Date(in.readLong());
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
public Date
|
|
30
|
-
return
|
|
29
|
+
public Date getOriginDate() {
|
|
30
|
+
return mOriginDate;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
public NotificationRequest getNotificationRequest() {
|
|
@@ -54,6 +54,6 @@ public class Notification implements Parcelable {
|
|
|
54
54
|
@Override
|
|
55
55
|
public void writeToParcel(Parcel dest, int flags) {
|
|
56
56
|
dest.writeParcelable(mRequest, 0);
|
|
57
|
-
dest.writeLong(
|
|
57
|
+
dest.writeLong(mOriginDate.getTime());
|
|
58
58
|
}
|
|
59
59
|
}
|
package/android/src/main/java/expo/modules/notifications/notifications/model/NotificationAction.java
CHANGED
|
@@ -7,6 +7,9 @@ import java.io.Serializable;
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A class representing a single notification action button.
|
|
10
|
+
*
|
|
11
|
+
* TODO vonovak: no need to implement serializable, parcelable is enough for storing
|
|
12
|
+
*
|
|
10
13
|
*/
|
|
11
14
|
public class NotificationAction implements Parcelable, Serializable {
|
|
12
15
|
private final String mIdentifier;
|
|
@@ -9,6 +9,8 @@ import java.util.List;
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A class representing a collection of notification actions.
|
|
12
|
+
*
|
|
13
|
+
* TODO vonovak: no need to implement serializable, parcelable is enough for storing
|
|
12
14
|
*/
|
|
13
15
|
public class NotificationCategory implements Parcelable, Serializable {
|
|
14
16
|
private final String mIdentifier;
|