expo-notifications 0.24.1 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/notifications/badge/BadgeHelper.kt +24 -0
  4. package/android/src/main/java/expo/modules/notifications/badge/BadgeModule.kt +2 -19
  5. package/android/src/main/java/expo/modules/notifications/notifications/background/ExpoBackgroundNotificationTasksModule.kt +44 -0
  6. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelGroupManagerModule.kt +77 -0
  7. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelManagerModule.kt +89 -0
  8. package/android/src/main/java/expo/modules/notifications/notifications/emitting/NotificationsEmitter.kt +77 -0
  9. package/android/src/main/java/expo/modules/notifications/notifications/handling/NotificationsHandler.kt +113 -0
  10. package/android/src/main/java/expo/modules/notifications/notifications/handling/SingleNotificationHandlerTask.java +1 -1
  11. package/android/src/main/java/expo/modules/notifications/serverregistration/ServerRegistrationModule.kt +29 -0
  12. package/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.kt +98 -0
  13. package/package.json +2 -2
  14. package/android/src/main/java/expo/modules/notifications/notifications/background/ExpoBackgroundNotificationTasksModule.java +0 -50
  15. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelGroupManagerModule.java +0 -98
  16. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelManagerModule.java +0 -109
  17. package/android/src/main/java/expo/modules/notifications/notifications/emitting/NotificationsEmitter.java +0 -98
  18. package/android/src/main/java/expo/modules/notifications/notifications/handling/NotificationsHandler.java +0 -136
  19. package/android/src/main/java/expo/modules/notifications/serverregistration/ServerRegistrationModule.java +0 -41
  20. package/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java +0 -116
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.24.2 — 2023-09-18
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 0.24.1 — 2023-09-15
14
18
 
15
19
  ### 💡 Others
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.24.1'
6
+ version = '0.24.2'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -70,7 +70,7 @@ android {
70
70
  minSdkVersion safeExtGet("minSdkVersion", 21)
71
71
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
72
72
  versionCode 21
73
- versionName '0.24.1'
73
+ versionName '0.24.2'
74
74
  }
75
75
 
76
76
  lintOptions {
@@ -0,0 +1,24 @@
1
+ package expo.modules.notifications.badge
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import me.leolin.shortcutbadger.ShortcutBadgeException
6
+ import me.leolin.shortcutbadger.ShortcutBadger
7
+
8
+ object BadgeHelper {
9
+ var badgeCount = 0
10
+ get() = synchronized(this) { field }
11
+ private set(value) = synchronized(this) { field = value }
12
+
13
+ fun setBadgeCount(context: Context, badgeCount: Int): Boolean {
14
+ return try {
15
+ ShortcutBadger.applyCountOrThrow(context.applicationContext, badgeCount)
16
+ BadgeHelper.badgeCount = badgeCount
17
+ true
18
+ } catch (e: ShortcutBadgeException) {
19
+ Log.d("expo-notifications", "Could not have set badge count: ${e.message}", e)
20
+ e.printStackTrace()
21
+ false
22
+ }
23
+ }
24
+ }
@@ -1,37 +1,20 @@
1
1
  package expo.modules.notifications.badge
2
2
 
3
3
  import android.content.Context
4
- import android.util.Log
5
4
  import expo.modules.core.ExportedModule
6
5
  import expo.modules.core.Promise
7
6
  import expo.modules.core.interfaces.ExpoMethod
8
- import me.leolin.shortcutbadger.ShortcutBadgeException
9
- import me.leolin.shortcutbadger.ShortcutBadger
10
7
 
11
8
  class BadgeModule(context: Context) : ExportedModule(context) {
12
9
  override fun getName(): String = "ExpoBadgeModule"
13
10
 
14
11
  @ExpoMethod
15
12
  fun getBadgeCountAsync(promise: Promise) {
16
- promise.resolve(badgeCount)
13
+ promise.resolve(BadgeHelper.badgeCount)
17
14
  }
18
15
 
19
16
  @ExpoMethod
20
17
  fun setBadgeCountAsync(badgeCount: Int, promise: Promise) {
21
- try {
22
- ShortcutBadger.applyCountOrThrow(context.applicationContext, badgeCount)
23
- BadgeModule.badgeCount = badgeCount
24
- promise.resolve(true)
25
- } catch (e: ShortcutBadgeException) {
26
- Log.d("expo-notifications", "Could not have set badge count: ${e.message}", e)
27
- e.printStackTrace()
28
- promise.resolve(false)
29
- }
30
- }
31
-
32
- companion object {
33
- var badgeCount = 0
34
- get() = synchronized(this) { field }
35
- set(value) = synchronized(this) { field = value }
18
+ promise.resolve(BadgeHelper.setBadgeCount(context, badgeCount))
36
19
  }
37
20
  }
@@ -0,0 +1,44 @@
1
+ package expo.modules.notifications.notifications.background
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
+ import expo.modules.interfaces.taskManager.TaskManagerInterface
9
+
10
+ class ExpoBackgroundNotificationTasksModule(context: Context?) : ExportedModule(context) {
11
+ private lateinit var taskManager: TaskManagerInterface
12
+ override fun getName(): String = "ExpoBackgroundNotificationTasksModule"
13
+
14
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
15
+ taskManager = moduleRegistry.getModule(TaskManagerInterface::class.java)
16
+ }
17
+
18
+ @ExpoMethod
19
+ fun registerTaskAsync(taskName: String?, promise: Promise) {
20
+ try {
21
+ taskManager.registerTask(
22
+ taskName,
23
+ BackgroundRemoteNotificationTaskConsumer::class.java,
24
+ emptyMap()
25
+ )
26
+ promise.resolve(null)
27
+ } catch (e: Exception) {
28
+ promise.reject(e)
29
+ }
30
+ }
31
+
32
+ @ExpoMethod
33
+ fun unregisterTaskAsync(taskName: String?, promise: Promise) {
34
+ try {
35
+ taskManager.unregisterTask(
36
+ taskName,
37
+ BackgroundRemoteNotificationTaskConsumer::class.java
38
+ )
39
+ promise.resolve(null)
40
+ } catch (e: Exception) {
41
+ promise.reject(e)
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,77 @@
1
+ package expo.modules.notifications.notifications.channels
2
+
3
+ import android.content.Context
4
+ import android.os.Build
5
+ import expo.modules.core.ExportedModule
6
+ import expo.modules.core.ModuleRegistry
7
+ import expo.modules.core.Promise
8
+ import expo.modules.core.arguments.ReadableArguments
9
+ import expo.modules.core.interfaces.ExpoMethod
10
+ import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager
11
+ import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer
12
+
13
+ /**
14
+ * An exported module responsible for exposing methods for managing notification channel groups.
15
+ */
16
+ class NotificationChannelGroupManagerModule(context: Context) : ExportedModule(context) {
17
+ private lateinit var groupManager: NotificationsChannelGroupManager
18
+ private lateinit var groupSerializer: NotificationsChannelGroupSerializer
19
+
20
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
21
+ val provider = moduleRegistry.getModule(NotificationsChannelsProvider::class.java)
22
+ groupManager = provider.groupManager
23
+ groupSerializer = provider.groupSerializer
24
+ }
25
+
26
+ override fun getName(): String = "ExpoNotificationChannelGroupManager"
27
+
28
+ @ExpoMethod
29
+ fun getNotificationChannelGroupAsync(groupId: String, promise: Promise) {
30
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
31
+ promise.resolve(null)
32
+ return
33
+ }
34
+ val group = groupManager.getNotificationChannelGroup(groupId)
35
+ promise.resolve(groupSerializer.toBundle(group))
36
+ }
37
+
38
+ @ExpoMethod
39
+ fun getNotificationChannelGroupsAsync(promise: Promise) {
40
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
41
+ promise.resolve(null)
42
+ return
43
+ }
44
+ val serializedChannels = groupManager
45
+ .notificationChannelGroups
46
+ .map(groupSerializer::toBundle)
47
+ promise.resolve(serializedChannels)
48
+ }
49
+
50
+ @ExpoMethod
51
+ fun setNotificationChannelGroupAsync(groupId: String, groupOptions: ReadableArguments, promise: Promise) {
52
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
53
+ promise.resolve(null)
54
+ return
55
+ }
56
+ val group = groupManager.createNotificationChannelGroup(
57
+ groupId,
58
+ getNameFromOptions(groupOptions),
59
+ groupOptions
60
+ )
61
+ promise.resolve(groupSerializer.toBundle(group))
62
+ }
63
+
64
+ @ExpoMethod
65
+ fun deleteNotificationChannelGroupAsync(groupId: String, promise: Promise) {
66
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
67
+ promise.resolve(null)
68
+ return
69
+ }
70
+ groupManager.deleteNotificationChannelGroup(groupId)
71
+ promise.resolve(null)
72
+ }
73
+
74
+ private fun getNameFromOptions(groupOptions: ReadableArguments): String {
75
+ return groupOptions.getString(NotificationsChannelGroupSerializer.NAME_KEY)
76
+ }
77
+ }
@@ -0,0 +1,89 @@
1
+ package expo.modules.notifications.notifications.channels
2
+
3
+ import android.content.Context
4
+ import android.os.Build
5
+ import androidx.annotation.RequiresApi
6
+ import expo.modules.core.ExportedModule
7
+ import expo.modules.core.ModuleRegistry
8
+ import expo.modules.core.Promise
9
+ import expo.modules.core.arguments.ReadableArguments
10
+ import expo.modules.core.interfaces.ExpoMethod
11
+ import expo.modules.notifications.notifications.channels.managers.NotificationsChannelManager
12
+ import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer
13
+ import expo.modules.notifications.notifications.enums.NotificationImportance
14
+ import java.util.Collections
15
+ import java.util.Objects
16
+
17
+ /**
18
+ * An exported module responsible for exposing methods for managing notification channels.
19
+ */
20
+ open class NotificationChannelManagerModule(context: Context?) : ExportedModule(context) {
21
+ private lateinit var channelManager: NotificationsChannelManager
22
+ private lateinit var channelSerializer: NotificationsChannelSerializer
23
+
24
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
25
+ val provider = moduleRegistry.getModule(NotificationsChannelsProvider::class.java)
26
+ channelManager = provider.channelManager
27
+ channelSerializer = provider.channelSerializer
28
+ }
29
+
30
+ override fun getName(): String = "ExpoNotificationChannelManager"
31
+
32
+ @ExpoMethod
33
+ fun getNotificationChannelAsync(channelId: String, promise: Promise) {
34
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
35
+ promise.resolve(null)
36
+ return
37
+ }
38
+ val notificationChannel = channelManager.getNotificationChannel(channelId)
39
+ promise.resolve(channelSerializer.toBundle(notificationChannel))
40
+ }
41
+
42
+ @ExpoMethod
43
+ fun getNotificationChannelsAsync(promise: Promise) {
44
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
45
+ promise.resolve(Collections.EMPTY_LIST)
46
+ return
47
+ }
48
+ val serializedChannels = channelManager
49
+ .notificationChannels
50
+ .map(channelSerializer::toBundle)
51
+ promise.resolve(serializedChannels)
52
+ }
53
+
54
+ @ExpoMethod
55
+ fun setNotificationChannelAsync(channelId: String, channelOptions: ReadableArguments, promise: Promise) {
56
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
57
+ promise.resolve(null)
58
+ return
59
+ }
60
+ val channel = channelManager.createNotificationChannel(
61
+ channelId,
62
+ getNameFromOptions(channelOptions),
63
+ getImportanceFromOptions(channelOptions),
64
+ channelOptions
65
+ )
66
+ promise.resolve(channelSerializer.toBundle(channel))
67
+ }
68
+
69
+ @ExpoMethod
70
+ fun deleteNotificationChannelAsync(channelId: String, promise: Promise) {
71
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
72
+ promise.resolve(null)
73
+ return
74
+ }
75
+ channelManager.deleteNotificationChannel(channelId)
76
+ promise.resolve(null)
77
+ }
78
+
79
+ private fun getNameFromOptions(channelOptions: ReadableArguments): CharSequence {
80
+ return channelOptions.getString(NotificationsChannelSerializer.NAME_KEY)
81
+ }
82
+
83
+ @RequiresApi(api = Build.VERSION_CODES.N)
84
+ private fun getImportanceFromOptions(channelOptions: ReadableArguments): Int {
85
+ val enumValue = channelOptions.getInt(NotificationsChannelSerializer.IMPORTANCE_KEY, NotificationImportance.DEFAULT.enumValue)
86
+ val importance = Objects.requireNonNull(NotificationImportance.fromEnumValue(enumValue))
87
+ return importance.nativeValue
88
+ }
89
+ }
@@ -0,0 +1,77 @@
1
+ package expo.modules.notifications.notifications.emitting
2
+
3
+ import android.content.Context
4
+ import android.os.Bundle
5
+ import expo.modules.core.ExportedModule
6
+ import expo.modules.core.ModuleRegistry
7
+ import expo.modules.core.Promise
8
+ import expo.modules.core.interfaces.ExpoMethod
9
+ import expo.modules.core.interfaces.services.EventEmitter
10
+ import expo.modules.notifications.notifications.NotificationSerializer
11
+ import expo.modules.notifications.notifications.interfaces.NotificationListener
12
+ import expo.modules.notifications.notifications.interfaces.NotificationManager
13
+ import expo.modules.notifications.notifications.model.Notification
14
+ import expo.modules.notifications.notifications.model.NotificationResponse
15
+
16
+ private const val NEW_MESSAGE_EVENT_NAME = "onDidReceiveNotification"
17
+ private const val NEW_RESPONSE_EVENT_NAME = "onDidReceiveNotificationResponse"
18
+ private const val MESSAGES_DELETED_EVENT_NAME = "onNotificationsDeleted"
19
+
20
+ open class NotificationsEmitter(context: Context) : ExportedModule(context), NotificationListener {
21
+ private lateinit var notificationManager: NotificationManager
22
+ private var lastNotificationResponse: NotificationResponse? = null
23
+ private var eventEmitter: EventEmitter? = null
24
+ override fun getName(): String = "ExpoNotificationsEmitter"
25
+
26
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
27
+ eventEmitter = moduleRegistry.getModule(EventEmitter::class.java)
28
+
29
+ // Register the module as a listener in NotificationManager singleton module.
30
+ // Deregistration happens in onDestroy callback.
31
+ notificationManager = requireNotNull(moduleRegistry.getSingletonModule("NotificationManager", NotificationManager::class.java))
32
+ notificationManager.addListener(this)
33
+ }
34
+
35
+ override fun onDestroy() {
36
+ notificationManager.removeListener(this)
37
+ }
38
+
39
+ @ExpoMethod
40
+ fun getLastNotificationResponseAsync(promise: Promise) {
41
+ promise.resolve(lastNotificationResponse?.let(NotificationSerializer::toBundle))
42
+ }
43
+
44
+ /**
45
+ * Callback called when [NotificationManager] gets notified of a new notification.
46
+ * Emits a [NEW_MESSAGE_EVENT_NAME] event.
47
+ *
48
+ * @param notification Notification received
49
+ */
50
+ override fun onNotificationReceived(notification: Notification) {
51
+ eventEmitter?.emit(NEW_MESSAGE_EVENT_NAME, NotificationSerializer.toBundle(notification))
52
+ }
53
+
54
+ /**
55
+ * Callback called when [NotificationManager] gets notified of a new notification response.
56
+ * Emits a [NEW_RESPONSE_EVENT_NAME] event.
57
+ *
58
+ * @param response Notification response received
59
+ * @return Whether notification has been handled
60
+ */
61
+ override fun onNotificationResponseReceived(response: NotificationResponse): Boolean {
62
+ lastNotificationResponse = response
63
+ eventEmitter?.let {
64
+ it.emit(NEW_RESPONSE_EVENT_NAME, NotificationSerializer.toBundle(response))
65
+ return true
66
+ }
67
+ return false
68
+ }
69
+
70
+ /**
71
+ * Callback called when [NotificationManager] gets informed of the fact of message dropping.
72
+ * Emits a [MESSAGES_DELETED_EVENT_NAME] event.
73
+ */
74
+ override fun onNotificationsDropped() {
75
+ eventEmitter?.emit(MESSAGES_DELETED_EVENT_NAME, Bundle.EMPTY)
76
+ }
77
+ }
@@ -0,0 +1,113 @@
1
+ package expo.modules.notifications.notifications.handling
2
+
3
+ import android.content.Context
4
+ import android.os.Handler
5
+ import android.os.HandlerThread
6
+ import expo.modules.core.ExportedModule
7
+ import expo.modules.core.ModuleRegistry
8
+ import expo.modules.core.Promise
9
+ import expo.modules.core.arguments.ReadableArguments
10
+ import expo.modules.core.interfaces.ExpoMethod
11
+ import expo.modules.notifications.notifications.interfaces.NotificationListener
12
+ import expo.modules.notifications.notifications.interfaces.NotificationManager
13
+ import expo.modules.notifications.notifications.model.Notification
14
+ import expo.modules.notifications.notifications.model.NotificationBehavior
15
+
16
+ private const val SHOULD_SHOW_ALERT_KEY = "shouldShowAlert"
17
+ private const val SHOULD_PLAY_SOUND_KEY = "shouldPlaySound"
18
+ private const val SHOULD_SET_BADGE_KEY = "shouldSetBadge"
19
+ private const val PRIORITY_KEY = "priority"
20
+
21
+ /**
22
+ * [NotificationListener] responsible for managing app's reaction to incoming
23
+ * notification.
24
+ *
25
+ *
26
+ * It is responsible for managing lifecycles of [SingleNotificationHandlerTask]s
27
+ * which are responsible: one for each notification. This module serves as holder
28
+ * for all of them and a proxy through which app responds with the behavior.
29
+ */
30
+ open class NotificationsHandler(context: Context) : ExportedModule(context), NotificationListener {
31
+ private lateinit var notificationManager: NotificationManager
32
+ private lateinit var moduleRegistry: ModuleRegistry
33
+
34
+ /**
35
+ * [HandlerThread] which is the host to the notifications handler.
36
+ */
37
+ private lateinit var notificationsHandlerThread: HandlerThread
38
+
39
+ /**
40
+ * [Handler] on which lifecycle events are executed.
41
+ */
42
+ private lateinit var handler: Handler
43
+
44
+ private val tasksMap = mutableMapOf<String, SingleNotificationHandlerTask>()
45
+
46
+ override fun getName(): String = "ExpoNotificationsHandlerModule"
47
+
48
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
49
+ this.moduleRegistry = moduleRegistry
50
+
51
+ // Register the module as a listener in NotificationManager singleton module.
52
+ // Deregistration happens in onDestroy callback.
53
+ notificationManager = requireNotNull(moduleRegistry.getSingletonModule("NotificationManager", NotificationManager::class.java))
54
+ notificationManager.addListener(this)
55
+ notificationsHandlerThread = HandlerThread("NotificationsHandlerThread - " + this.javaClass.toString())
56
+ notificationsHandlerThread.start()
57
+ handler = Handler(notificationsHandlerThread.looper)
58
+ }
59
+
60
+ override fun onDestroy() {
61
+ notificationManager.removeListener(this)
62
+
63
+ tasksMap.values.forEach(SingleNotificationHandlerTask::stop)
64
+
65
+ // We don't have to use `quitSafely` here, cause all tasks were stopped
66
+ notificationsHandlerThread.quit()
67
+ }
68
+
69
+ /**
70
+ * Called by the app with [ReadableArguments] representing requested behavior
71
+ * that should be applied to the notification.
72
+ *
73
+ * @param identifier Identifier of the task which asked for behavior.
74
+ * @param behavior Behavior to apply to the notification.
75
+ * @param promise Promise to resolve once the notification is successfully presented
76
+ * or fails to be presented.
77
+ */
78
+ @ExpoMethod
79
+ fun handleNotificationAsync(identifier: String, behavior: ReadableArguments, promise: Promise) {
80
+ val task = tasksMap[identifier]
81
+ if (task == null) {
82
+ promise.reject("ERR_NOTIFICATION_HANDLED", "Failed to handle notification $identifier, it has already been handled.")
83
+ return
84
+ }
85
+ val shouldShowAlert = behavior.getBoolean(SHOULD_SHOW_ALERT_KEY)
86
+ val shouldPlaySound = behavior.getBoolean(SHOULD_PLAY_SOUND_KEY)
87
+ val shouldSetBadge = behavior.getBoolean(SHOULD_SET_BADGE_KEY)
88
+ val priorityOverride = behavior.getString(PRIORITY_KEY)
89
+ task.handleResponse(NotificationBehavior(shouldShowAlert, shouldPlaySound, shouldSetBadge, priorityOverride), promise)
90
+ }
91
+
92
+ /**
93
+ * Callback called by [NotificationManager] to inform its listeners of new messages.
94
+ * Starts up a new [SingleNotificationHandlerTask] which will take it on from here.
95
+ *
96
+ * @param notification Notification received
97
+ */
98
+ override fun onNotificationReceived(notification: Notification) {
99
+ val task = SingleNotificationHandlerTask(context, handler, moduleRegistry, notification, this)
100
+ tasksMap[task.identifier] = task
101
+ task.start()
102
+ }
103
+
104
+ /**
105
+ * Callback called once [SingleNotificationHandlerTask] finishes.
106
+ * A cue for removal of the task.
107
+ *
108
+ * @param task Task that just fulfilled its responsibility.
109
+ */
110
+ fun onTaskFinished(task: SingleNotificationHandlerTask) {
111
+ tasksMap.remove(task.identifier)
112
+ }
113
+ }
@@ -17,7 +17,7 @@ import expo.modules.notifications.service.NotificationsService;
17
17
  /**
18
18
  * A "task" responsible for managing response to a single notification.
19
19
  */
20
- /* package */ class SingleNotificationHandlerTask {
20
+ public class SingleNotificationHandlerTask {
21
21
  /**
22
22
  * Name of the event asking the delegate for behavior.
23
23
  */
@@ -0,0 +1,29 @@
1
+ package expo.modules.notifications.serverregistration
2
+
3
+ import android.content.Context
4
+ import expo.modules.core.ExportedModule
5
+ import expo.modules.core.Promise
6
+ import expo.modules.core.interfaces.ExpoMethod
7
+
8
+ open class ServerRegistrationModule(context: Context) : ExportedModule(context) {
9
+ protected val installationId = InstallationId(context)
10
+ private val mRegistrationInfo = RegistrationInfo(context)
11
+
12
+ override fun getName(): String = "NotificationsServerRegistrationModule"
13
+
14
+ @ExpoMethod
15
+ open fun getInstallationIdAsync(promise: Promise) {
16
+ promise.resolve(installationId.orCreateUUID)
17
+ }
18
+
19
+ @ExpoMethod
20
+ fun getRegistrationInfoAsync(promise: Promise) {
21
+ promise.resolve(mRegistrationInfo.get())
22
+ }
23
+
24
+ @ExpoMethod
25
+ fun setRegistrationInfoAsync(registrationInfo: String?, promise: Promise) {
26
+ mRegistrationInfo.set(registrationInfo)
27
+ promise.resolve(null)
28
+ }
29
+ }
@@ -0,0 +1,98 @@
1
+ package expo.modules.notifications.tokens
2
+
3
+ import android.content.Context
4
+ import android.os.Bundle
5
+ import com.google.firebase.messaging.FirebaseMessaging
6
+ import expo.modules.core.ExportedModule
7
+ import expo.modules.core.ModuleRegistry
8
+ import expo.modules.core.Promise
9
+ import expo.modules.core.interfaces.ExpoMethod
10
+ import expo.modules.core.interfaces.services.EventEmitter
11
+ import expo.modules.notifications.tokens.interfaces.PushTokenListener
12
+ import expo.modules.notifications.tokens.interfaces.PushTokenManager
13
+
14
+ private const val NEW_TOKEN_EVENT_NAME = "onDevicePushToken"
15
+ private const val NEW_TOKEN_EVENT_TOKEN_KEY = "devicePushToken"
16
+ private const val REGISTRATION_FAIL_CODE = "E_REGISTRATION_FAILED"
17
+ private const val UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE = "E_UNREGISTER_FOR_NOTIFICATIONS_FAILED"
18
+
19
+ class PushTokenModule(context: Context) : ExportedModule(context), PushTokenListener {
20
+ private lateinit var tokenManager: PushTokenManager
21
+ private var eventEmitter: EventEmitter? = null
22
+ override fun getName(): String = "ExpoPushTokenManager"
23
+
24
+ override fun onCreate(moduleRegistry: ModuleRegistry) {
25
+ eventEmitter = moduleRegistry.getModule(EventEmitter::class.java)
26
+
27
+ // Register the module as a listener in PushTokenManager singleton module.
28
+ // Deregistration happens in onDestroy callback.
29
+ tokenManager = requireNotNull(
30
+ moduleRegistry.getSingletonModule("PushTokenManager", PushTokenManager::class.java)
31
+ )
32
+ tokenManager.addListener(this)
33
+ }
34
+
35
+ override fun onDestroy() {
36
+ tokenManager.removeListener(this)
37
+ }
38
+
39
+ /**
40
+ * Fetches Firebase push token and resolves the promise.
41
+ *
42
+ * @param promise Promise to be resolved with the token.
43
+ */
44
+ @ExpoMethod
45
+ fun getDevicePushTokenAsync(promise: Promise) {
46
+ FirebaseMessaging.getInstance().token
47
+ .addOnCompleteListener { task ->
48
+ if (!task.isSuccessful) {
49
+ val exception = task.exception
50
+ if (exception == null) {
51
+ promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed.")
52
+ } else {
53
+ promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed: ${exception.message}", exception)
54
+ }
55
+ return@addOnCompleteListener
56
+ }
57
+ val token = task.result
58
+ if (token == null) {
59
+ promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed. Invalid token.")
60
+ return@addOnCompleteListener
61
+ }
62
+
63
+ promise.resolve(token)
64
+ onNewToken(token)
65
+ }
66
+ }
67
+
68
+ @ExpoMethod
69
+ fun unregisterForNotificationsAsync(promise: Promise) {
70
+ FirebaseMessaging.getInstance().deleteToken()
71
+ .addOnCompleteListener { task ->
72
+ if (!task.isSuccessful) {
73
+ val exception = task.exception
74
+ if (exception == null) {
75
+ promise.reject(UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE, "Unregistering for notifications failed.")
76
+ } else {
77
+ promise.reject(UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE, "Unregistering for notifications failed: ${exception.message}", exception)
78
+ }
79
+ return@addOnCompleteListener
80
+ }
81
+ promise.resolve(null)
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Callback called when [PushTokenManager] gets notified of a new token.
87
+ * Emits a [NEW_TOKEN_EVENT_NAME] event.
88
+ *
89
+ * @param token New push token.
90
+ */
91
+ override fun onNewToken(token: String) {
92
+ eventEmitter?.let {
93
+ val eventBody = Bundle()
94
+ eventBody.putString(NEW_TOKEN_EVENT_TOKEN_KEY, token)
95
+ it.emit(NEW_TOKEN_EVENT_NAME, eventBody)
96
+ }
97
+ }
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-notifications",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Notifications module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -57,5 +57,5 @@
57
57
  "peerDependencies": {
58
58
  "expo": "*"
59
59
  },
60
- "gitHead": "2bd82552d004cba40601572c8f141f063150620c"
60
+ "gitHead": "62f76105dfb436f7144440d6e6077d4ff3263842"
61
61
  }
@@ -1,50 +0,0 @@
1
- package expo.modules.notifications.notifications.background;
2
-
3
- import android.content.Context;
4
-
5
- import expo.modules.core.ExportedModule;
6
- import expo.modules.core.ModuleRegistry;
7
- import expo.modules.core.Promise;
8
- import expo.modules.core.interfaces.ExpoMethod;
9
- import expo.modules.interfaces.taskManager.TaskManagerInterface;
10
-
11
- import java.util.Collections;
12
-
13
- public class ExpoBackgroundNotificationTasksModule extends ExportedModule {
14
- private TaskManagerInterface mTaskManager;
15
-
16
- public ExpoBackgroundNotificationTasksModule(Context context) {
17
- super(context);
18
- }
19
-
20
- @Override
21
- public String getName() {
22
- return "ExpoBackgroundNotificationTasksModule";
23
- }
24
-
25
- @Override
26
- public void onCreate(ModuleRegistry moduleRegistry) {
27
- mTaskManager = moduleRegistry.getModule(TaskManagerInterface.class);
28
- }
29
-
30
- @ExpoMethod
31
- public void registerTaskAsync(String taskName, final Promise promise) {
32
- try {
33
- mTaskManager.registerTask(
34
- taskName, BackgroundRemoteNotificationTaskConsumer.class, Collections.emptyMap());
35
- promise.resolve(null);
36
- } catch (Exception e) {
37
- promise.reject(e);
38
- }
39
- }
40
-
41
- @ExpoMethod
42
- public void unregisterTaskAsync(String taskName, final Promise promise) {
43
- try {
44
- mTaskManager.unregisterTask(taskName, BackgroundRemoteNotificationTaskConsumer.class);
45
- promise.resolve(null);
46
- } catch (Exception e) {
47
- promise.reject(e);
48
- }
49
- }
50
- }
@@ -1,98 +0,0 @@
1
- package expo.modules.notifications.notifications.channels;
2
-
3
- import android.app.NotificationChannelGroup;
4
- import android.content.Context;
5
- import android.os.Bundle;
6
-
7
- import expo.modules.core.ExportedModule;
8
- import expo.modules.core.ModuleRegistry;
9
- import expo.modules.core.Promise;
10
- import expo.modules.core.arguments.ReadableArguments;
11
- import expo.modules.core.interfaces.ExpoMethod;
12
-
13
- import java.util.ArrayList;
14
- import java.util.List;
15
-
16
- import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager;
17
- import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer;
18
-
19
- import static expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer.NAME_KEY;
20
-
21
- /**
22
- * An exported module responsible for exposing methods for managing notification channel groups.
23
- */
24
- public class NotificationChannelGroupManagerModule extends ExportedModule {
25
- private final static String EXPORTED_NAME = "ExpoNotificationChannelGroupManager";
26
-
27
- private NotificationsChannelGroupManager mGroupManager;
28
- private NotificationsChannelGroupSerializer mGroupSerializer;
29
-
30
- public NotificationChannelGroupManagerModule(Context context) {
31
- super(context);
32
- }
33
-
34
- @Override
35
- public void onCreate(ModuleRegistry moduleRegistry) {
36
- NotificationsChannelsProvider provider = moduleRegistry.getModule(NotificationsChannelsProvider.class);
37
- mGroupManager = provider.getGroupManager();
38
- mGroupSerializer = provider.getGroupSerializer();
39
- }
40
-
41
- @Override
42
- public String getName() {
43
- return EXPORTED_NAME;
44
- }
45
-
46
- @ExpoMethod
47
- public void getNotificationChannelGroupAsync(String groupId, Promise promise) {
48
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
49
- promise.resolve(null);
50
- return;
51
- }
52
-
53
- NotificationChannelGroup group = mGroupManager.getNotificationChannelGroup(groupId);
54
- promise.resolve(mGroupSerializer.toBundle(group));
55
- }
56
-
57
- @ExpoMethod
58
- public void getNotificationChannelGroupsAsync(Promise promise) {
59
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
60
- promise.resolve(null);
61
- return;
62
- }
63
-
64
- List<NotificationChannelGroup> existingChannels = mGroupManager.getNotificationChannelGroups();
65
- List<Bundle> serializedChannels = new ArrayList<>(existingChannels.size());
66
- for (NotificationChannelGroup channelGroup : existingChannels) {
67
- serializedChannels.add(mGroupSerializer.toBundle(channelGroup));
68
- }
69
- promise.resolve(serializedChannels);
70
- }
71
-
72
- @ExpoMethod
73
- public void setNotificationChannelGroupAsync(String groupId, ReadableArguments groupOptions, Promise promise) {
74
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
75
- promise.resolve(null);
76
- return;
77
- }
78
-
79
- NotificationChannelGroup group = mGroupManager.createNotificationChannelGroup(groupId, getNameFromOptions(groupOptions), groupOptions);
80
- promise.resolve(mGroupSerializer.toBundle(group));
81
- }
82
-
83
- @ExpoMethod
84
- public void deleteNotificationChannelGroupAsync(String groupId, Promise promise) {
85
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
86
- promise.resolve(null);
87
- return;
88
- }
89
-
90
- mGroupManager.deleteNotificationChannelGroup(groupId);
91
- promise.resolve(null);
92
- }
93
-
94
-
95
- protected CharSequence getNameFromOptions(ReadableArguments groupOptions) {
96
- return groupOptions.getString(NAME_KEY);
97
- }
98
- }
@@ -1,109 +0,0 @@
1
- package expo.modules.notifications.notifications.channels;
2
-
3
- import android.app.NotificationChannel;
4
- import android.content.Context;
5
- import android.os.Build;
6
- import android.os.Bundle;
7
-
8
- import expo.modules.core.ExportedModule;
9
- import expo.modules.core.ModuleRegistry;
10
- import expo.modules.core.Promise;
11
- import expo.modules.core.arguments.ReadableArguments;
12
- import expo.modules.core.interfaces.ExpoMethod;
13
-
14
- import java.util.ArrayList;
15
- import java.util.Collections;
16
- import java.util.List;
17
- import java.util.Objects;
18
-
19
- import androidx.annotation.RequiresApi;
20
- import expo.modules.notifications.notifications.channels.managers.NotificationsChannelManager;
21
- import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer;
22
- import expo.modules.notifications.notifications.enums.NotificationImportance;
23
-
24
- import static expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer.IMPORTANCE_KEY;
25
- import static expo.modules.notifications.notifications.channels.serializers.NotificationsChannelSerializer.NAME_KEY;
26
-
27
- /**
28
- * An exported module responsible for exposing methods for managing notification channels.
29
- */
30
- public class NotificationChannelManagerModule extends ExportedModule {
31
- private final static String EXPORTED_NAME = "ExpoNotificationChannelManager";
32
-
33
- private NotificationsChannelManager mChannelManager;
34
- private NotificationsChannelSerializer mChannelSerializer;
35
-
36
- public NotificationChannelManagerModule(Context context) {
37
- super(context);
38
- }
39
-
40
- @Override
41
- public void onCreate(ModuleRegistry moduleRegistry) {
42
- NotificationsChannelsProvider provider = moduleRegistry.getModule(NotificationsChannelsProvider.class);
43
- mChannelManager = provider.getChannelManager();
44
- mChannelSerializer = provider.getChannelSerializer();
45
- }
46
-
47
- @Override
48
- public String getName() {
49
- return EXPORTED_NAME;
50
- }
51
-
52
- @ExpoMethod
53
- public void getNotificationChannelAsync(String channelId, Promise promise) {
54
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
55
- promise.resolve(null);
56
- return;
57
- }
58
-
59
- promise.resolve(mChannelSerializer.toBundle(mChannelManager.getNotificationChannel(channelId)));
60
- }
61
-
62
- @ExpoMethod
63
- public void getNotificationChannelsAsync(Promise promise) {
64
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
65
- promise.resolve(Collections.EMPTY_LIST);
66
- return;
67
- }
68
-
69
- List<NotificationChannel> existingChannels = mChannelManager.getNotificationChannels();
70
- List<Bundle> serializedChannels = new ArrayList<>(existingChannels.size());
71
- for (NotificationChannel channel : existingChannels) {
72
- serializedChannels.add(mChannelSerializer.toBundle(channel));
73
- }
74
- promise.resolve(serializedChannels);
75
- }
76
-
77
- @ExpoMethod
78
- public void setNotificationChannelAsync(String channelId, ReadableArguments channelOptions, Promise promise) {
79
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
80
- promise.resolve(null);
81
- return;
82
- }
83
-
84
- NotificationChannel channel = mChannelManager.createNotificationChannel(channelId, getNameFromOptions(channelOptions), getImportanceFromOptions(channelOptions), channelOptions);
85
- promise.resolve(mChannelSerializer.toBundle(channel));
86
- }
87
-
88
- @ExpoMethod
89
- public void deleteNotificationChannelAsync(String channelId, Promise promise) {
90
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O) {
91
- promise.resolve(null);
92
- return;
93
- }
94
-
95
- mChannelManager.deleteNotificationChannel(channelId);
96
- promise.resolve(null);
97
- }
98
-
99
- protected CharSequence getNameFromOptions(ReadableArguments channelOptions) {
100
- return channelOptions.getString(NAME_KEY);
101
- }
102
-
103
- @RequiresApi(api = Build.VERSION_CODES.N)
104
- protected int getImportanceFromOptions(ReadableArguments channelOptions) {
105
- int enumValue = channelOptions.getInt(IMPORTANCE_KEY, NotificationImportance.DEFAULT.getEnumValue());
106
- NotificationImportance importance = Objects.requireNonNull(NotificationImportance.fromEnumValue(enumValue));
107
- return importance.getNativeValue();
108
- }
109
- }
@@ -1,98 +0,0 @@
1
- package expo.modules.notifications.notifications.emitting;
2
-
3
- import android.content.Context;
4
- import android.os.Bundle;
5
-
6
- import expo.modules.core.ExportedModule;
7
- import expo.modules.core.ModuleRegistry;
8
- import expo.modules.core.Promise;
9
- import expo.modules.core.interfaces.ExpoMethod;
10
- import expo.modules.core.interfaces.services.EventEmitter;
11
-
12
- import expo.modules.notifications.notifications.NotificationSerializer;
13
- import expo.modules.notifications.notifications.interfaces.NotificationListener;
14
- import expo.modules.notifications.notifications.interfaces.NotificationManager;
15
- import expo.modules.notifications.notifications.model.Notification;
16
- import expo.modules.notifications.notifications.model.NotificationResponse;
17
-
18
- public class NotificationsEmitter extends ExportedModule implements NotificationListener {
19
- private final static String EXPORTED_NAME = "ExpoNotificationsEmitter";
20
-
21
- private final static String NEW_MESSAGE_EVENT_NAME = "onDidReceiveNotification";
22
- private final static String NEW_RESPONSE_EVENT_NAME = "onDidReceiveNotificationResponse";
23
- private final static String MESSAGES_DELETED_EVENT_NAME = "onNotificationsDeleted";
24
-
25
- private NotificationManager mNotificationManager;
26
- private NotificationResponse mLastNotificationResponse;
27
- private EventEmitter mEventEmitter;
28
-
29
- public NotificationsEmitter(Context context) {
30
- super(context);
31
- }
32
-
33
- @Override
34
- public String getName() {
35
- return EXPORTED_NAME;
36
- }
37
-
38
- @Override
39
- public void onCreate(ModuleRegistry moduleRegistry) {
40
- mEventEmitter = moduleRegistry.getModule(EventEmitter.class);
41
-
42
- // Register the module as a listener in NotificationManager singleton module.
43
- // Deregistration happens in onDestroy callback.
44
- mNotificationManager = moduleRegistry.getSingletonModule("NotificationManager", NotificationManager.class);
45
- mNotificationManager.addListener(this);
46
- }
47
-
48
- @Override
49
- public void onDestroy() {
50
- mNotificationManager.removeListener(this);
51
- }
52
-
53
- @ExpoMethod
54
- public void getLastNotificationResponseAsync(Promise promise) {
55
- promise.resolve(mLastNotificationResponse != null ? NotificationSerializer.toBundle(mLastNotificationResponse) : null);
56
- }
57
-
58
- /**
59
- * Callback called when {@link NotificationManager} gets notified of a new notification.
60
- * Emits a {@link NotificationsEmitter#NEW_MESSAGE_EVENT_NAME} event.
61
- *
62
- * @param notification Notification received
63
- */
64
- @Override
65
- public void onNotificationReceived(Notification notification) {
66
- if (mEventEmitter != null) {
67
- mEventEmitter.emit(NEW_MESSAGE_EVENT_NAME, NotificationSerializer.toBundle(notification));
68
- }
69
- }
70
-
71
- /**
72
- * Callback called when {@link NotificationManager} gets notified of a new notification response.
73
- * Emits a {@link NotificationsEmitter#NEW_RESPONSE_EVENT_NAME} event.
74
- *
75
- * @param response Notification response received
76
- * @return Whether notification has been handled
77
- */
78
- @Override
79
- public boolean onNotificationResponseReceived(NotificationResponse response) {
80
- mLastNotificationResponse = response;
81
- if (mEventEmitter != null) {
82
- mEventEmitter.emit(NEW_RESPONSE_EVENT_NAME, NotificationSerializer.toBundle(response));
83
- return true;
84
- }
85
- return false;
86
- }
87
-
88
- /**
89
- * Callback called when {@link NotificationManager} gets informed of the fact of message dropping.
90
- * Emits a {@link NotificationsEmitter#MESSAGES_DELETED_EVENT_NAME} event.
91
- */
92
- @Override
93
- public void onNotificationsDropped() {
94
- if (mEventEmitter != null) {
95
- mEventEmitter.emit(MESSAGES_DELETED_EVENT_NAME, Bundle.EMPTY);
96
- }
97
- }
98
- }
@@ -1,136 +0,0 @@
1
- package expo.modules.notifications.notifications.handling;
2
-
3
- import android.content.Context;
4
- import android.os.Handler;
5
- import android.os.HandlerThread;
6
-
7
- import expo.modules.core.ExportedModule;
8
- import expo.modules.core.ModuleRegistry;
9
- import expo.modules.core.Promise;
10
- import expo.modules.core.arguments.ReadableArguments;
11
- import expo.modules.core.interfaces.ExpoMethod;
12
-
13
- import java.util.Collection;
14
- import java.util.HashMap;
15
- import java.util.Map;
16
-
17
- import expo.modules.notifications.notifications.emitting.NotificationsEmitter;
18
- import expo.modules.notifications.notifications.interfaces.NotificationListener;
19
- import expo.modules.notifications.notifications.interfaces.NotificationManager;
20
- import expo.modules.notifications.notifications.model.Notification;
21
- import expo.modules.notifications.notifications.model.NotificationBehavior;
22
- import expo.modules.notifications.notifications.model.NotificationResponse;
23
-
24
- /**
25
- * {@link NotificationListener} responsible for managing app's reaction to incoming
26
- * notification.
27
- * <p>
28
- * It is responsible for managing lifecycles of {@link SingleNotificationHandlerTask}s
29
- * which are responsible: one for each notification. This module serves as holder
30
- * for all of them and a proxy through which app responds with the behavior.
31
- */
32
- public class NotificationsHandler extends ExportedModule implements NotificationListener {
33
- private final static String EXPORTED_NAME = "ExpoNotificationsHandlerModule";
34
-
35
- private static final String SHOULD_SHOW_ALERT_KEY = "shouldShowAlert";
36
- private static final String SHOULD_PLAY_SOUND_KEY = "shouldPlaySound";
37
- private static final String SHOULD_SET_BADGE_KEY = "shouldSetBadge";
38
- private static final String PRIORITY_KEY = "priority";
39
-
40
- private NotificationManager mNotificationManager;
41
- private ModuleRegistry mModuleRegistry;
42
-
43
- /**
44
- * {@link HandlerThread} which is the host to the notifications handler.
45
- */
46
- private HandlerThread mNotificationsHandlerThread = null;
47
-
48
- /**
49
- * {@link Handler} on which lifecycle events are executed.
50
- */
51
- private Handler mHandler = null;
52
-
53
- private Map<String, SingleNotificationHandlerTask> mTasksMap = new HashMap<>();
54
-
55
- public NotificationsHandler(Context context) {
56
- super(context);
57
- }
58
-
59
- @Override
60
- public String getName() {
61
- return EXPORTED_NAME;
62
- }
63
-
64
- @Override
65
- public void onCreate(ModuleRegistry moduleRegistry) {
66
- mModuleRegistry = moduleRegistry;
67
-
68
- // Register the module as a listener in NotificationManager singleton module.
69
- // Deregistration happens in onDestroy callback.
70
- mNotificationManager = moduleRegistry.getSingletonModule("NotificationManager", NotificationManager.class);
71
- mNotificationManager.addListener(this);
72
-
73
- mNotificationsHandlerThread = new HandlerThread("NotificationsHandlerThread - " + this.getClass().toString());
74
- mNotificationsHandlerThread.start();
75
- mHandler = new Handler(mNotificationsHandlerThread.getLooper());
76
- }
77
-
78
- @Override
79
- public void onDestroy() {
80
- mNotificationManager.removeListener(this);
81
- Collection<SingleNotificationHandlerTask> tasks = mTasksMap.values();
82
- for (SingleNotificationHandlerTask task : tasks) {
83
- task.stop();
84
- }
85
-
86
- // We don't have to use `quitSafely` here, cause all tasks were stopped
87
- mNotificationsHandlerThread.quit();
88
- }
89
-
90
- /**
91
- * Called by the app with {@link ReadableArguments} representing requested behavior
92
- * that should be applied to the notification.
93
- *
94
- * @param identifier Identifier of the task which asked for behavior.
95
- * @param behavior Behavior to apply to the notification.
96
- * @param promise Promise to resolve once the notification is successfully presented
97
- * or fails to be presented.
98
- */
99
- @ExpoMethod
100
- public void handleNotificationAsync(String identifier, final ReadableArguments behavior, Promise promise) {
101
- SingleNotificationHandlerTask task = mTasksMap.get(identifier);
102
- if (task == null) {
103
- String message = String.format("Failed to handle notification %s, it has already been handled.", identifier);
104
- promise.reject("ERR_NOTIFICATION_HANDLED", message);
105
- return;
106
- }
107
- boolean shouldShowAlert = behavior.getBoolean(SHOULD_SHOW_ALERT_KEY);
108
- boolean shouldPlaySound = behavior.getBoolean(SHOULD_PLAY_SOUND_KEY);
109
- boolean shouldSetBadge = behavior.getBoolean(SHOULD_SET_BADGE_KEY);
110
- String priorityOverride = behavior.getString(PRIORITY_KEY);
111
- task.handleResponse(new NotificationBehavior(shouldShowAlert, shouldPlaySound, shouldSetBadge, priorityOverride), promise);
112
- }
113
-
114
- /**
115
- * Callback called by {@link NotificationManager} to inform its listeners of new messages.
116
- * Starts up a new {@link SingleNotificationHandlerTask} which will take it on from here.
117
- *
118
- * @param notification Notification received
119
- */
120
- @Override
121
- public void onNotificationReceived(Notification notification) {
122
- SingleNotificationHandlerTask task = new SingleNotificationHandlerTask(getContext(), mHandler, mModuleRegistry, notification, this);
123
- mTasksMap.put(task.getIdentifier(), task);
124
- task.start();
125
- }
126
-
127
- /**
128
- * Callback called once {@link SingleNotificationHandlerTask} finishes.
129
- * A cue for removal of the task.
130
- *
131
- * @param task Task that just fulfilled its responsibility.
132
- */
133
- void onTaskFinished(SingleNotificationHandlerTask task) {
134
- mTasksMap.remove(task.getIdentifier());
135
- }
136
- }
@@ -1,41 +0,0 @@
1
- package expo.modules.notifications.serverregistration;
2
-
3
- import android.content.Context;
4
-
5
- import expo.modules.core.ExportedModule;
6
- import expo.modules.core.Promise;
7
- import expo.modules.core.interfaces.ExpoMethod;
8
-
9
- public class ServerRegistrationModule extends ExportedModule {
10
- private static final String EXPORTED_NAME = "NotificationsServerRegistrationModule";
11
-
12
- protected InstallationId mInstallationId;
13
- private RegistrationInfo mRegistrationInfo;
14
-
15
- public ServerRegistrationModule(Context context) {
16
- super(context);
17
- mInstallationId = new InstallationId(context);
18
- mRegistrationInfo = new RegistrationInfo(context);
19
- }
20
-
21
- @Override
22
- public String getName() {
23
- return EXPORTED_NAME;
24
- }
25
-
26
- @ExpoMethod
27
- public void getInstallationIdAsync(Promise promise) {
28
- promise.resolve(mInstallationId.getOrCreateUUID());
29
- }
30
-
31
- @ExpoMethod
32
- public void getRegistrationInfoAsync(Promise promise) {
33
- promise.resolve(mRegistrationInfo.get());
34
- }
35
-
36
- @ExpoMethod
37
- public void setRegistrationInfoAsync(String registrationInfo, Promise promise) {
38
- mRegistrationInfo.set(registrationInfo);
39
- promise.resolve(null);
40
- }
41
- }
@@ -1,116 +0,0 @@
1
- package expo.modules.notifications.tokens;
2
-
3
- import android.content.Context;
4
- import android.os.Bundle;
5
-
6
- import com.google.android.gms.tasks.OnCompleteListener;
7
- import com.google.android.gms.tasks.Task;
8
- import com.google.firebase.messaging.FirebaseMessaging;
9
-
10
- import expo.modules.core.ExportedModule;
11
- import expo.modules.core.ModuleRegistry;
12
- import expo.modules.core.Promise;
13
- import expo.modules.core.interfaces.ExpoMethod;
14
- import expo.modules.core.interfaces.services.EventEmitter;
15
-
16
- import androidx.annotation.NonNull;
17
- import expo.modules.notifications.tokens.interfaces.PushTokenListener;
18
- import expo.modules.notifications.tokens.interfaces.PushTokenManager;
19
-
20
- public class PushTokenModule extends ExportedModule implements PushTokenListener {
21
- private final static String EXPORTED_NAME = "ExpoPushTokenManager";
22
-
23
- private final static String NEW_TOKEN_EVENT_NAME = "onDevicePushToken";
24
- private final static String NEW_TOKEN_EVENT_TOKEN_KEY = "devicePushToken";
25
-
26
- private final static String REGISTRATION_FAIL_CODE = "E_REGISTRATION_FAILED";
27
- private final static String UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE = "E_UNREGISTER_FOR_NOTIFICATIONS_FAILED";
28
-
29
- private PushTokenManager mPushTokenManager;
30
- private EventEmitter mEventEmitter;
31
-
32
- public PushTokenModule(Context context) {
33
- super(context);
34
- }
35
-
36
- @Override
37
- public String getName() {
38
- return EXPORTED_NAME;
39
- }
40
-
41
-
42
- @Override
43
- public void onCreate(ModuleRegistry moduleRegistry) {
44
- mEventEmitter = moduleRegistry.getModule(EventEmitter.class);
45
-
46
- // Register the module as a listener in PushTokenManager singleton module.
47
- // Deregistration happens in onDestroy callback.
48
- mPushTokenManager = moduleRegistry.getSingletonModule("PushTokenManager", PushTokenManager.class);
49
- mPushTokenManager.addListener(this);
50
- }
51
-
52
- @Override
53
- public void onDestroy() {
54
- mPushTokenManager.removeListener(this);
55
- }
56
-
57
- /**
58
- * Fetches Firebase push token and resolves the promise.
59
- *
60
- * @param promise Promise to be resolved with the token.
61
- */
62
- @ExpoMethod
63
- public void getDevicePushTokenAsync(final Promise promise) {
64
- FirebaseMessaging.getInstance().getToken()
65
- .addOnCompleteListener(new OnCompleteListener<String>() {
66
- @Override
67
- public void onComplete(@NonNull Task<String> task) {
68
- if (!task.isSuccessful() || task.getResult() == null) {
69
- if (task.getException() == null) {
70
- promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed.");
71
- } else {
72
- promise.reject(REGISTRATION_FAIL_CODE, "Fetching the token failed: " + task.getException().getMessage(), task.getException());
73
- }
74
- return;
75
- }
76
-
77
- String token = task.getResult();
78
-
79
- promise.resolve(token);
80
- onNewToken(token);
81
- }
82
- });
83
- }
84
-
85
- @ExpoMethod
86
- public void unregisterForNotificationsAsync(final Promise promise) {
87
- FirebaseMessaging.getInstance().deleteToken()
88
- .addOnCompleteListener(task -> {
89
- if (!task.isSuccessful()) {
90
- if (task.getException() == null) {
91
- promise.reject(UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE, "Unregistering for notifications failed.");
92
- } else {
93
- promise.reject(UNREGISTER_FOR_NOTIFICATIONS_FAIL_CODE, "Unregistering for notifications failed: " + task.getException().getMessage(), task.getException());
94
- }
95
- return;
96
- }
97
-
98
- promise.resolve(null);
99
- });
100
- }
101
-
102
- /**
103
- * Callback called when {@link PushTokenManager} gets notified of a new token.
104
- * Emits a {@link PushTokenModule#NEW_TOKEN_EVENT_NAME} event.
105
- *
106
- * @param token New push token.
107
- */
108
- @Override
109
- public void onNewToken(String token) {
110
- if (mEventEmitter != null) {
111
- Bundle eventBody = new Bundle();
112
- eventBody.putString(NEW_TOKEN_EVENT_TOKEN_KEY, token);
113
- mEventEmitter.emit(NEW_TOKEN_EVENT_NAME, eventBody);
114
- }
115
- }
116
- }