expo-notifications 0.24.2 → 0.25.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.
- package/CHANGELOG.md +14 -0
- package/android/build.gradle +49 -30
- package/android/src/main/java/expo/modules/notifications/Exceptions.kt +22 -0
- package/android/src/main/java/expo/modules/notifications/NotificationsPackage.java +3 -33
- package/android/src/main/java/expo/modules/notifications/Utils.kt +19 -0
- package/android/src/main/java/expo/modules/notifications/badge/BadgeModule.kt +15 -13
- package/android/src/main/java/expo/modules/notifications/notifications/background/BackgroundRemoteNotificationTaskConsumer.java +2 -6
- package/android/src/main/java/expo/modules/notifications/notifications/background/ExpoBackgroundNotificationTasksModule.kt +12 -23
- package/android/src/main/java/expo/modules/notifications/notifications/categories/ExpoNotificationCategoriesModule.kt +149 -0
- package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelGroupManagerModule.kt +42 -49
- package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelManagerModule.kt +45 -51
- package/android/src/main/java/expo/modules/notifications/notifications/emitting/NotificationsEmitter.kt +21 -20
- package/android/src/main/java/expo/modules/notifications/notifications/handling/NotificationsHandler.kt +51 -37
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/ExpoNotificationPresentationModule.kt +113 -0
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java +1 -5
- package/android/src/main/java/expo/modules/notifications/notifications/scheduling/NotificationScheduler.kt +235 -0
- package/android/src/main/java/expo/modules/notifications/permissions/NotificationPermissionsModule.kt +36 -56
- package/android/src/main/java/expo/modules/notifications/serverregistration/ServerRegistrationModule.kt +21 -18
- package/android/src/main/java/expo/modules/notifications/service/NotificationsService.kt +1 -0
- package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoPresentationDelegate.kt +0 -6
- package/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.kt +51 -58
- package/build/BackgroundNotificationTasksModule.native.d.ts.map +1 -1
- package/build/BackgroundNotificationTasksModule.native.js +2 -2
- package/build/BackgroundNotificationTasksModule.native.js.map +1 -1
- package/build/BadgeModule.native.d.ts.map +1 -1
- package/build/BadgeModule.native.js +4 -3
- package/build/BadgeModule.native.js.map +1 -1
- package/build/NotificationCategoriesModule.native.d.ts.map +1 -1
- package/build/NotificationCategoriesModule.native.js +2 -2
- package/build/NotificationCategoriesModule.native.js.map +1 -1
- package/build/NotificationChannelGroupManager.native.d.ts.map +1 -1
- package/build/NotificationChannelGroupManager.native.js +2 -2
- package/build/NotificationChannelGroupManager.native.js.map +1 -1
- package/build/NotificationChannelManager.native.d.ts.map +1 -1
- package/build/NotificationChannelManager.native.js +2 -2
- package/build/NotificationChannelManager.native.js.map +1 -1
- package/build/NotificationPermissionsModule.native.d.ts.map +1 -1
- package/build/NotificationPermissionsModule.native.js +2 -2
- package/build/NotificationPermissionsModule.native.js.map +1 -1
- package/build/NotificationPresenterModule.native.d.ts.map +1 -1
- package/build/NotificationPresenterModule.native.js +2 -2
- package/build/NotificationPresenterModule.native.js.map +1 -1
- package/build/NotificationScheduler.native.d.ts.map +1 -1
- package/build/NotificationScheduler.native.js +2 -2
- package/build/NotificationScheduler.native.js.map +1 -1
- package/build/NotificationsEmitterModule.native.d.ts.map +1 -1
- package/build/NotificationsEmitterModule.native.js +2 -2
- package/build/NotificationsEmitterModule.native.js.map +1 -1
- package/build/NotificationsHandlerModule.native.d.ts.map +1 -1
- package/build/NotificationsHandlerModule.native.js +2 -2
- package/build/NotificationsHandlerModule.native.js.map +1 -1
- package/build/PushTokenManager.native.d.ts.map +1 -1
- package/build/PushTokenManager.native.js +2 -2
- package/build/PushTokenManager.native.js.map +1 -1
- package/build/ServerRegistrationModule.native.d.ts.map +1 -1
- package/build/ServerRegistrationModule.native.js +2 -2
- package/build/ServerRegistrationModule.native.js.map +1 -1
- package/expo-module.config.json +20 -0
- package/ios/EXNotifications/Notifications/Background/EXBackgroundRemoteNotificationConsumer.m +2 -4
- package/package.json +4 -4
- package/src/BackgroundNotificationTasksModule.native.ts +4 -2
- package/src/BadgeModule.native.ts +5 -3
- package/src/NotificationCategoriesModule.native.ts +4 -2
- package/src/NotificationChannelGroupManager.native.ts +4 -2
- package/src/NotificationChannelManager.native.ts +2 -2
- package/src/NotificationPermissionsModule.native.ts +4 -2
- package/src/NotificationPresenterModule.native.ts +2 -2
- package/src/NotificationScheduler.native.ts +2 -2
- package/src/NotificationsEmitterModule.native.ts +2 -2
- package/src/NotificationsHandlerModule.native.ts +2 -2
- package/src/PushTokenManager.native.ts +2 -2
- package/src/ServerRegistrationModule.native.ts +4 -2
- package/android/src/main/java/expo/modules/notifications/notifications/categories/ExpoNotificationCategoriesModule.java +0 -124
- package/android/src/main/java/expo/modules/notifications/notifications/presentation/ExpoNotificationPresentationModule.java +0 -116
- package/android/src/main/java/expo/modules/notifications/notifications/scheduling/NotificationScheduler.java +0 -222
- package/unimodule.json +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,20 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 0.25.0 — 2023-10-17
|
|
14
|
+
|
|
15
|
+
### 🛠 Breaking changes
|
|
16
|
+
|
|
17
|
+
- Dropped support for Android SDK 21 and 22. ([#24201](https://github.com/expo/expo/pull/24201) by [@behenate](https://github.com/behenate))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- Send background notifications through when the app is in the foreground ([#24684](https://github.com/expo/expo/pull/24684) by [@kadikraman](https://github.com/kadikraman))
|
|
22
|
+
|
|
23
|
+
### 💡 Others
|
|
24
|
+
|
|
25
|
+
- Migrated codebase to use Expo Modules API. ([#24499](https://github.com/expo/expo/pull/24499) by [@lukmccall](https://github.com/lukmccall))
|
|
26
|
+
|
|
13
27
|
## 0.24.2 — 2023-09-18
|
|
14
28
|
|
|
15
29
|
_This version does not introduce any user-facing changes._
|
package/android/build.gradle
CHANGED
|
@@ -3,15 +3,20 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven-publish'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '0.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
version = '0.25.0'
|
|
7
|
+
|
|
8
|
+
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
9
|
+
if (expoModulesCorePlugin.exists()) {
|
|
10
|
+
apply from: expoModulesCorePlugin
|
|
11
|
+
applyKotlinExpoModulesCorePlugin()
|
|
12
|
+
// Remove this check, but keep the contents after SDK49 support is dropped
|
|
13
|
+
if (safeExtGet("expoProvidesDefaultConfig", false)) {
|
|
14
|
+
useExpoPublishing()
|
|
15
|
+
useCoreDependencies()
|
|
13
16
|
}
|
|
17
|
+
}
|
|
14
18
|
|
|
19
|
+
buildscript {
|
|
15
20
|
// Simple helper that allows the root project to override versions declared by this library.
|
|
16
21
|
ext.safeExtGet = { prop, fallback ->
|
|
17
22
|
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
@@ -35,23 +40,44 @@ buildscript {
|
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
// Remove this if and it's contents, when support for SDK49 is dropped
|
|
44
|
+
if (!safeExtGet("expoProvidesDefaultConfig", false)) {
|
|
45
|
+
afterEvaluate {
|
|
46
|
+
publishing {
|
|
47
|
+
publications {
|
|
48
|
+
release(MavenPublication) {
|
|
49
|
+
from components.release
|
|
50
|
+
}
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
repositories {
|
|
53
|
+
maven {
|
|
54
|
+
url = mavenLocal().url
|
|
55
|
+
}
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
android {
|
|
54
|
-
|
|
62
|
+
// Remove this if and it's contents, when support for SDK49 is dropped
|
|
63
|
+
if (!safeExtGet("expoProvidesDefaultConfig", false)) {
|
|
64
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 33)
|
|
65
|
+
|
|
66
|
+
defaultConfig {
|
|
67
|
+
minSdkVersion safeExtGet("minSdkVersion", 23)
|
|
68
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
publishing {
|
|
72
|
+
singleVariant("release") {
|
|
73
|
+
withSourcesJar()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
lintOptions {
|
|
78
|
+
abortOnError false
|
|
79
|
+
}
|
|
80
|
+
}
|
|
55
81
|
|
|
56
82
|
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
|
|
57
83
|
if (agpVersion.tokenize('.')[0].toInteger() < 8) {
|
|
@@ -67,34 +93,27 @@ android {
|
|
|
67
93
|
|
|
68
94
|
namespace "expo.modules.notifications"
|
|
69
95
|
defaultConfig {
|
|
70
|
-
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
71
|
-
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
72
96
|
versionCode 21
|
|
73
|
-
versionName '0.
|
|
97
|
+
versionName '0.25.0'
|
|
74
98
|
}
|
|
75
99
|
|
|
76
|
-
lintOptions {
|
|
77
|
-
abortOnError false
|
|
78
|
-
}
|
|
79
|
-
publishing {
|
|
80
|
-
singleVariant("release") {
|
|
81
|
-
withSourcesJar()
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
100
|
buildFeatures {
|
|
85
101
|
buildConfig true
|
|
86
102
|
}
|
|
87
103
|
}
|
|
88
104
|
|
|
89
105
|
dependencies {
|
|
90
|
-
|
|
106
|
+
// Remove this if and it's contents, when support for SDK49 is dropped
|
|
107
|
+
if (!safeExtGet("expoProvidesDefaultConfig", false)) {
|
|
108
|
+
implementation project(':expo-modules-core')
|
|
109
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
|
|
110
|
+
}
|
|
91
111
|
|
|
92
112
|
api 'androidx.core:core:1.5.0'
|
|
93
113
|
api 'androidx.lifecycle:lifecycle-runtime:2.2.0'
|
|
94
114
|
api 'androidx.lifecycle:lifecycle-process:2.2.0'
|
|
95
115
|
api 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
|
|
96
116
|
|
|
97
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
|
|
98
117
|
|
|
99
118
|
api 'com.google.firebase:firebase-messaging:22.0.0'
|
|
100
119
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package expo.modules.notifications
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.exception.CodedException
|
|
4
|
+
import kotlin.reflect.KClass
|
|
5
|
+
|
|
6
|
+
class ModuleNotFoundException(moduleClass: KClass<*>) :
|
|
7
|
+
CodedException(message = "$moduleClass module not found")
|
|
8
|
+
|
|
9
|
+
class NotificationWasAlreadyHandledException(val id: String) : CodedException("Failed to handle notification $id, it has already been handled.")
|
|
10
|
+
|
|
11
|
+
fun expo.modules.kotlin.Promise.toLegacyPromise(): expo.modules.core.Promise {
|
|
12
|
+
val newPromise = this
|
|
13
|
+
return object : expo.modules.core.Promise {
|
|
14
|
+
override fun resolve(value: Any?) {
|
|
15
|
+
newPromise.resolve(value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun reject(c: String?, m: String?, e: Throwable?) {
|
|
19
|
+
newPromise.reject(c ?: "unknown", m, e)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -2,50 +2,20 @@ package expo.modules.notifications;
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
|
|
5
|
+
import java.util.Arrays;
|
|
6
|
+
import java.util.List;
|
|
7
|
+
|
|
5
8
|
import expo.modules.core.BasePackage;
|
|
6
9
|
import expo.modules.core.ExportedModule;
|
|
7
10
|
import expo.modules.core.interfaces.InternalModule;
|
|
8
11
|
import expo.modules.core.interfaces.SingletonModule;
|
|
9
|
-
|
|
10
|
-
import java.util.Arrays;
|
|
11
|
-
import java.util.List;
|
|
12
|
-
|
|
13
|
-
import expo.modules.notifications.badge.BadgeModule;
|
|
14
|
-
import expo.modules.notifications.serverregistration.ServerRegistrationModule;
|
|
15
12
|
import expo.modules.notifications.notifications.NotificationManager;
|
|
16
|
-
import expo.modules.notifications.notifications.background.ExpoBackgroundNotificationTasksModule;
|
|
17
13
|
import expo.modules.notifications.notifications.categories.ExpoNotificationCategoriesModule;
|
|
18
14
|
import expo.modules.notifications.notifications.categories.serializers.ExpoNotificationsCategoriesSerializer;
|
|
19
15
|
import expo.modules.notifications.notifications.channels.AndroidXNotificationsChannelsProvider;
|
|
20
|
-
import expo.modules.notifications.notifications.channels.NotificationChannelGroupManagerModule;
|
|
21
|
-
import expo.modules.notifications.notifications.channels.NotificationChannelManagerModule;
|
|
22
|
-
import expo.modules.notifications.notifications.emitting.NotificationsEmitter;
|
|
23
|
-
import expo.modules.notifications.notifications.handling.NotificationsHandler;
|
|
24
|
-
import expo.modules.notifications.notifications.presentation.ExpoNotificationPresentationModule;
|
|
25
|
-
import expo.modules.notifications.notifications.scheduling.NotificationScheduler;
|
|
26
|
-
import expo.modules.notifications.permissions.NotificationPermissionsModule;
|
|
27
16
|
import expo.modules.notifications.tokens.PushTokenManager;
|
|
28
|
-
import expo.modules.notifications.tokens.PushTokenModule;
|
|
29
17
|
|
|
30
18
|
public class NotificationsPackage extends BasePackage {
|
|
31
|
-
@Override
|
|
32
|
-
public List<ExportedModule> createExportedModules(Context context) {
|
|
33
|
-
return Arrays.asList(
|
|
34
|
-
new BadgeModule(context),
|
|
35
|
-
new PushTokenModule(context),
|
|
36
|
-
new NotificationsEmitter(context),
|
|
37
|
-
new NotificationsHandler(context),
|
|
38
|
-
new NotificationScheduler(context),
|
|
39
|
-
new ServerRegistrationModule(context),
|
|
40
|
-
new NotificationPermissionsModule(context),
|
|
41
|
-
new NotificationChannelManagerModule(context),
|
|
42
|
-
new ExpoNotificationPresentationModule(context),
|
|
43
|
-
new NotificationChannelGroupManagerModule(context),
|
|
44
|
-
new ExpoNotificationCategoriesModule(context),
|
|
45
|
-
new ExpoBackgroundNotificationTasksModule(context)
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
19
|
@Override
|
|
50
20
|
public List<SingletonModule> createSingletonModules(Context context) {
|
|
51
21
|
return Arrays.asList(
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package expo.modules.notifications
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import android.os.Handler
|
|
5
|
+
import android.os.ResultReceiver
|
|
6
|
+
|
|
7
|
+
typealias ResultReceiverBody = (resultCode: Int, resultData: Bundle?) -> Unit
|
|
8
|
+
|
|
9
|
+
internal fun createDefaultResultReceiver(
|
|
10
|
+
handler: Handler?,
|
|
11
|
+
body: ResultReceiverBody,
|
|
12
|
+
): ResultReceiver {
|
|
13
|
+
return object : ResultReceiver(handler) {
|
|
14
|
+
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
|
|
15
|
+
super.onReceiveResult(resultCode, resultData)
|
|
16
|
+
body(resultCode, resultData)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
package expo.modules.notifications.badge
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import expo.modules.
|
|
5
|
-
import expo.modules.
|
|
6
|
-
import expo.modules.core.interfaces.ExpoMethod
|
|
3
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
4
|
+
import expo.modules.kotlin.modules.Module
|
|
5
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
7
6
|
|
|
8
|
-
class BadgeModule
|
|
9
|
-
override fun
|
|
7
|
+
class BadgeModule : Module() {
|
|
8
|
+
override fun definition() = ModuleDefinition {
|
|
9
|
+
Name("ExpoBadgeModule")
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
11
|
+
AsyncFunction("getBadgeCountAsync") {
|
|
12
|
+
BadgeHelper.badgeCount
|
|
13
|
+
}
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
AsyncFunction("setBadgeCountAsync") { badgeCount: Int ->
|
|
16
|
+
BadgeHelper.setBadgeCount(
|
|
17
|
+
appContext.reactContext ?: throw Exceptions.ReactContextLost(),
|
|
18
|
+
badgeCount
|
|
19
|
+
)
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
}
|
|
@@ -7,9 +7,6 @@ import android.os.Bundle;
|
|
|
7
7
|
import android.os.PersistableBundle;
|
|
8
8
|
import android.util.Log;
|
|
9
9
|
|
|
10
|
-
import androidx.lifecycle.Lifecycle;
|
|
11
|
-
import androidx.lifecycle.ProcessLifecycleOwner;
|
|
12
|
-
|
|
13
10
|
import org.json.JSONException;
|
|
14
11
|
import org.json.JSONObject;
|
|
15
12
|
|
|
@@ -26,7 +23,7 @@ import expo.modules.interfaces.taskManager.TaskInterface;
|
|
|
26
23
|
import expo.modules.interfaces.taskManager.TaskManagerUtilsInterface;
|
|
27
24
|
|
|
28
25
|
/**
|
|
29
|
-
* Represents a task to be run when the app is
|
|
26
|
+
* Represents a task to be run when the app is receives a remote push
|
|
30
27
|
* notification. Map of current tasks is maintained in {@link FirebaseMessagingDelegate}.
|
|
31
28
|
*/
|
|
32
29
|
public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer implements TaskConsumerInterface {
|
|
@@ -59,9 +56,8 @@ public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer imple
|
|
|
59
56
|
|
|
60
57
|
public void scheduleJob(Bundle bundle) {
|
|
61
58
|
Context context = getContext();
|
|
62
|
-
boolean isInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
|
|
63
59
|
|
|
64
|
-
if (context != null && mTask != null
|
|
60
|
+
if (context != null && mTask != null) {
|
|
65
61
|
PersistableBundle data = new PersistableBundle();
|
|
66
62
|
// Bundles are not persistable, so let's convert to a JSON string
|
|
67
63
|
data.putString(NOTIFICATION_KEY, bundleToJson(bundle).toString());
|
|
@@ -1,44 +1,33 @@
|
|
|
1
1
|
package expo.modules.notifications.notifications.background
|
|
2
2
|
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import expo.modules.core.ExportedModule
|
|
5
|
-
import expo.modules.core.ModuleRegistry
|
|
6
|
-
import expo.modules.core.Promise
|
|
7
|
-
import expo.modules.core.interfaces.ExpoMethod
|
|
8
3
|
import expo.modules.interfaces.taskManager.TaskManagerInterface
|
|
4
|
+
import expo.modules.kotlin.modules.Module
|
|
5
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
6
|
+
import expo.modules.notifications.ModuleNotFoundException
|
|
9
7
|
|
|
10
|
-
class ExpoBackgroundNotificationTasksModule
|
|
8
|
+
class ExpoBackgroundNotificationTasksModule : Module() {
|
|
11
9
|
private lateinit var taskManager: TaskManagerInterface
|
|
12
|
-
override fun getName(): String = "ExpoBackgroundNotificationTasksModule"
|
|
13
10
|
|
|
14
|
-
override fun
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
override fun definition() = ModuleDefinition {
|
|
12
|
+
Name("ExpoBackgroundNotificationTasksModule")
|
|
13
|
+
OnCreate {
|
|
14
|
+
taskManager = appContext.legacyModule()
|
|
15
|
+
?: throw ModuleNotFoundException(TaskManagerInterface::class)
|
|
16
|
+
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
fun registerTaskAsync(taskName: String?, promise: Promise) {
|
|
20
|
-
try {
|
|
18
|
+
AsyncFunction("registerTaskAsync") { taskName: String ->
|
|
21
19
|
taskManager.registerTask(
|
|
22
20
|
taskName,
|
|
23
21
|
BackgroundRemoteNotificationTaskConsumer::class.java,
|
|
24
22
|
emptyMap()
|
|
25
23
|
)
|
|
26
|
-
promise.resolve(null)
|
|
27
|
-
} catch (e: Exception) {
|
|
28
|
-
promise.reject(e)
|
|
29
24
|
}
|
|
30
|
-
}
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
fun unregisterTaskAsync(taskName: String?, promise: Promise) {
|
|
34
|
-
try {
|
|
26
|
+
AsyncFunction("unregisterTaskAsync") { taskName: String ->
|
|
35
27
|
taskManager.unregisterTask(
|
|
36
28
|
taskName,
|
|
37
29
|
BackgroundRemoteNotificationTaskConsumer::class.java
|
|
38
30
|
)
|
|
39
|
-
promise.resolve(null)
|
|
40
|
-
} catch (e: Exception) {
|
|
41
|
-
promise.reject(e)
|
|
42
31
|
}
|
|
43
32
|
}
|
|
44
33
|
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
package expo.modules.notifications.notifications.categories
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.os.Bundle
|
|
5
|
+
import expo.modules.core.errors.InvalidArgumentException
|
|
6
|
+
import expo.modules.kotlin.Promise
|
|
7
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
8
|
+
import expo.modules.kotlin.modules.Module
|
|
9
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
10
|
+
import expo.modules.kotlin.records.Field
|
|
11
|
+
import expo.modules.kotlin.records.Record
|
|
12
|
+
import expo.modules.kotlin.records.Required
|
|
13
|
+
import expo.modules.notifications.ModuleNotFoundException
|
|
14
|
+
import expo.modules.notifications.ResultReceiverBody
|
|
15
|
+
import expo.modules.notifications.createDefaultResultReceiver
|
|
16
|
+
import expo.modules.notifications.notifications.categories.serializers.NotificationsCategoriesSerializer
|
|
17
|
+
import expo.modules.notifications.notifications.model.NotificationAction
|
|
18
|
+
import expo.modules.notifications.notifications.model.NotificationCategory
|
|
19
|
+
import expo.modules.notifications.notifications.model.TextInputNotificationAction
|
|
20
|
+
import expo.modules.notifications.service.NotificationsService
|
|
21
|
+
import expo.modules.notifications.service.NotificationsService.Companion.deleteCategory
|
|
22
|
+
import expo.modules.notifications.service.NotificationsService.Companion.getCategories
|
|
23
|
+
import expo.modules.notifications.service.NotificationsService.Companion.setCategory
|
|
24
|
+
|
|
25
|
+
class NotificationActionRecord : Record {
|
|
26
|
+
@Field
|
|
27
|
+
@Required
|
|
28
|
+
val identifier: String = ""
|
|
29
|
+
|
|
30
|
+
@Field
|
|
31
|
+
@Required
|
|
32
|
+
val buttonTitle: String = ""
|
|
33
|
+
|
|
34
|
+
@Field
|
|
35
|
+
val textInput: TextInput? = null
|
|
36
|
+
|
|
37
|
+
@Field
|
|
38
|
+
val options = Options()
|
|
39
|
+
|
|
40
|
+
class TextInput : Record {
|
|
41
|
+
@Field
|
|
42
|
+
@Required
|
|
43
|
+
val placeholder: String = ""
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
class Options : Record {
|
|
47
|
+
@Field
|
|
48
|
+
val opensAppToForeground = true
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
open class ExpoNotificationCategoriesModule : Module() {
|
|
53
|
+
|
|
54
|
+
protected val serializer by lazy {
|
|
55
|
+
appContext.legacyModule<NotificationsCategoriesSerializer>()
|
|
56
|
+
?: throw ModuleNotFoundException(NotificationsCategoriesSerializer::class)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private val context: Context
|
|
60
|
+
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
61
|
+
|
|
62
|
+
override fun definition() = ModuleDefinition {
|
|
63
|
+
Name("ExpoNotificationCategoriesModule")
|
|
64
|
+
|
|
65
|
+
AsyncFunction("getNotificationCategoriesAsync") { promise: Promise ->
|
|
66
|
+
getCategories(
|
|
67
|
+
context,
|
|
68
|
+
createResultReceiver { resultCode: Int, resultData: Bundle? ->
|
|
69
|
+
val categories = resultData?.getParcelableArrayList<NotificationCategory>(NotificationsService.NOTIFICATION_CATEGORIES_KEY)
|
|
70
|
+
if (resultCode == NotificationsService.SUCCESS_CODE && categories != null) {
|
|
71
|
+
promise.resolve(serializeCategories(categories))
|
|
72
|
+
} else {
|
|
73
|
+
promise.reject("ERR_CATEGORIES_FETCH_FAILED", "A list of notification categories could not be fetched.", null)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
AsyncFunction("setNotificationCategoryAsync", this@ExpoNotificationCategoriesModule::setNotificationCategoryAsync)
|
|
80
|
+
|
|
81
|
+
AsyncFunction("deleteNotificationCategoryAsync", this@ExpoNotificationCategoriesModule::deleteNotificationCategoryAsync)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private fun createResultReceiver(body: ResultReceiverBody) =
|
|
85
|
+
createDefaultResultReceiver(null, body)
|
|
86
|
+
|
|
87
|
+
open fun setNotificationCategoryAsync(
|
|
88
|
+
identifier: String,
|
|
89
|
+
actionArguments: List<NotificationActionRecord>,
|
|
90
|
+
categoryOptions: Map<String, Any?>?,
|
|
91
|
+
promise: Promise
|
|
92
|
+
) {
|
|
93
|
+
val actions = mutableListOf<NotificationAction>()
|
|
94
|
+
for (actionMap in actionArguments) {
|
|
95
|
+
val textInputOptions = actionMap.textInput
|
|
96
|
+
if (textInputOptions != null) {
|
|
97
|
+
actions.add(
|
|
98
|
+
TextInputNotificationAction(
|
|
99
|
+
actionMap.identifier,
|
|
100
|
+
actionMap.buttonTitle,
|
|
101
|
+
actionMap.options.opensAppToForeground,
|
|
102
|
+
textInputOptions.placeholder
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
} else {
|
|
106
|
+
actions.add(
|
|
107
|
+
NotificationAction(
|
|
108
|
+
actionMap.identifier,
|
|
109
|
+
actionMap.buttonTitle,
|
|
110
|
+
actionMap.options.opensAppToForeground,
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (actions.isEmpty()) {
|
|
116
|
+
throw InvalidArgumentException("Invalid arguments provided for notification category. Must provide at least one action.")
|
|
117
|
+
}
|
|
118
|
+
setCategory(
|
|
119
|
+
context,
|
|
120
|
+
NotificationCategory(identifier, actions),
|
|
121
|
+
createResultReceiver { resultCode: Int, resultData: Bundle? ->
|
|
122
|
+
val category = resultData?.getParcelable<NotificationCategory>(NotificationsService.NOTIFICATION_CATEGORY_KEY)
|
|
123
|
+
if (resultCode == NotificationsService.SUCCESS_CODE && category != null) {
|
|
124
|
+
promise.resolve(serializer.toBundle(category))
|
|
125
|
+
} else {
|
|
126
|
+
promise.reject("ERR_CATEGORY_SET_FAILED", "The provided category could not be set.", null)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
open fun deleteNotificationCategoryAsync(identifier: String, promise: Promise) {
|
|
133
|
+
deleteCategory(
|
|
134
|
+
context,
|
|
135
|
+
identifier,
|
|
136
|
+
createResultReceiver { resultCode: Int, resultData: Bundle? ->
|
|
137
|
+
if (resultCode == NotificationsService.SUCCESS_CODE) {
|
|
138
|
+
promise.resolve(resultData?.getBoolean(NotificationsService.SUCCEEDED_KEY))
|
|
139
|
+
} else {
|
|
140
|
+
promise.reject("ERR_CATEGORY_DELETE_FAILED", "The category could not be deleted.", null)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
protected open fun serializeCategories(categories: Collection<NotificationCategory>): List<Bundle?> {
|
|
147
|
+
return categories.map(serializer::toBundle)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -1,74 +1,67 @@
|
|
|
1
1
|
package expo.modules.notifications.notifications.channels
|
|
2
2
|
|
|
3
|
-
import android.content.Context
|
|
4
3
|
import android.os.Build
|
|
5
|
-
import expo.modules.core.ExportedModule
|
|
6
|
-
import expo.modules.core.ModuleRegistry
|
|
7
|
-
import expo.modules.core.Promise
|
|
8
4
|
import expo.modules.core.arguments.ReadableArguments
|
|
9
|
-
import expo.modules.
|
|
5
|
+
import expo.modules.kotlin.modules.Module
|
|
6
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
7
|
+
import expo.modules.notifications.ModuleNotFoundException
|
|
10
8
|
import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager
|
|
11
9
|
import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer
|
|
12
10
|
|
|
13
11
|
/**
|
|
14
12
|
* An exported module responsible for exposing methods for managing notification channel groups.
|
|
15
13
|
*/
|
|
16
|
-
class NotificationChannelGroupManagerModule
|
|
14
|
+
class NotificationChannelGroupManagerModule : Module() {
|
|
17
15
|
private lateinit var groupManager: NotificationsChannelGroupManager
|
|
18
16
|
private lateinit var groupSerializer: NotificationsChannelGroupSerializer
|
|
19
17
|
|
|
20
|
-
override fun
|
|
21
|
-
|
|
22
|
-
groupManager = provider.groupManager
|
|
23
|
-
groupSerializer = provider.groupSerializer
|
|
24
|
-
}
|
|
18
|
+
override fun definition() = ModuleDefinition {
|
|
19
|
+
Name("ExpoNotificationChannelGroupManager")
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
OnCreate {
|
|
22
|
+
val provider = appContext.legacyModule<NotificationsChannelsProvider>()
|
|
23
|
+
?: throw ModuleNotFoundException(NotificationsChannelsProvider::class)
|
|
24
|
+
groupManager = provider.groupManager
|
|
25
|
+
groupSerializer = provider.groupSerializer
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
AsyncFunction("getNotificationChannelGroupAsync") { groupId: String ->
|
|
29
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
30
|
+
val group = groupManager.getNotificationChannelGroup(groupId)
|
|
31
|
+
groupSerializer.toBundle(group)
|
|
32
|
+
} else {
|
|
33
|
+
null
|
|
34
|
+
}
|
|
33
35
|
}
|
|
34
|
-
val group = groupManager.getNotificationChannelGroup(groupId)
|
|
35
|
-
promise.resolve(groupSerializer.toBundle(group))
|
|
36
|
-
}
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
AsyncFunction("getNotificationChannelGroupsAsync") {
|
|
38
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
39
|
+
groupManager
|
|
40
|
+
.notificationChannelGroups
|
|
41
|
+
.map(groupSerializer::toBundle)
|
|
42
|
+
} else {
|
|
43
|
+
null
|
|
44
|
+
}
|
|
43
45
|
}
|
|
44
|
-
val serializedChannels = groupManager
|
|
45
|
-
.notificationChannelGroups
|
|
46
|
-
.map(groupSerializer::toBundle)
|
|
47
|
-
promise.resolve(serializedChannels)
|
|
48
|
-
}
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
AsyncFunction("setNotificationChannelGroupAsync") { groupId: String, groupOptions: ReadableArguments ->
|
|
48
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
49
|
+
val group = groupManager.createNotificationChannelGroup(
|
|
50
|
+
groupId,
|
|
51
|
+
getNameFromOptions(groupOptions),
|
|
52
|
+
groupOptions
|
|
53
|
+
)
|
|
54
|
+
groupSerializer.toBundle(group)
|
|
55
|
+
} else {
|
|
56
|
+
null
|
|
57
|
+
}
|
|
55
58
|
}
|
|
56
|
-
val group = groupManager.createNotificationChannelGroup(
|
|
57
|
-
groupId,
|
|
58
|
-
getNameFromOptions(groupOptions),
|
|
59
|
-
groupOptions
|
|
60
|
-
)
|
|
61
|
-
promise.resolve(groupSerializer.toBundle(group))
|
|
62
|
-
}
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return
|
|
60
|
+
AsyncFunction("deleteNotificationChannelGroupAsync") { groupId: String ->
|
|
61
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
62
|
+
groupManager.deleteNotificationChannelGroup(groupId)
|
|
63
|
+
}
|
|
69
64
|
}
|
|
70
|
-
groupManager.deleteNotificationChannelGroup(groupId)
|
|
71
|
-
promise.resolve(null)
|
|
72
65
|
}
|
|
73
66
|
|
|
74
67
|
private fun getNameFromOptions(groupOptions: ReadableArguments): String {
|