expo-notifications 0.15.0 → 0.15.3

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 (32) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +2 -0
  3. package/android/build.gradle +7 -3
  4. package/android/src/main/AndroidManifest.xml +8 -0
  5. package/android/src/main/java/expo/modules/notifications/service/NotificationForwarderActivity.kt +30 -0
  6. package/android/src/main/java/expo/modules/notifications/service/NotificationsService.kt +60 -22
  7. package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoHandlingDelegate.kt +51 -15
  8. package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoSchedulingDelegate.kt +21 -6
  9. package/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.java +18 -0
  10. package/build/PushTokenManager.types.d.ts +1 -0
  11. package/build/PushTokenManager.types.d.ts.map +1 -1
  12. package/build/PushTokenManager.types.js.map +1 -1
  13. package/build/index.d.ts +1 -0
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js +1 -0
  16. package/build/index.js.map +1 -1
  17. package/build/unregisterForNotificationsAsync.d.ts +2 -0
  18. package/build/unregisterForNotificationsAsync.d.ts.map +1 -0
  19. package/build/unregisterForNotificationsAsync.js +9 -0
  20. package/build/unregisterForNotificationsAsync.js.map +1 -0
  21. package/ios/EXNotifications/PushToken/EXPushTokenModule.m +7 -0
  22. package/ios/EXNotifications.xcframework/Info.plist +5 -5
  23. package/ios/EXNotifications.xcframework/ios-arm64/EXNotifications.framework/EXNotifications +0 -0
  24. package/ios/EXNotifications.xcframework/ios-arm64/EXNotifications.framework/Info.plist +0 -0
  25. package/ios/EXNotifications.xcframework/ios-arm64_x86_64-simulator/EXNotifications.framework/EXNotifications +0 -0
  26. package/ios/EXNotifications.xcframework/ios-arm64_x86_64-simulator/EXNotifications.framework/Info.plist +0 -0
  27. package/package.json +2 -2
  28. package/src/PushTokenManager.types.ts +1 -0
  29. package/src/index.ts +1 -0
  30. package/src/unregisterForNotificationsAsync.ts +10 -0
  31. package/android/src/main/java/expo/modules/notifications/badge/SetBadgeCountNotificationEffect.java +0 -56
  32. package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/BadgeSettingNotificationBuilder.java +0 -66
package/CHANGELOG.md CHANGED
@@ -10,6 +10,31 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.15.3 — 2022-06-17
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fix app not bringing to foreground when clicking notification on Android 12+. ([#17686](https://github.com/expo/expo/pull/17686) by [@kudo](https://github.com/kudo))
18
+ - Fixed Android data-only FCM notifications (i.e. notifications without a title and message) appearing in the notification drawer ([#17707](https://github.com/expo/expo/pull/17707) by [@sausti](https://github.com/sausti))
19
+ - Add support for unregistering from push notifications on Android and iOS ([#17812](https://github.com/expo/expo/pull/17812) by [@sausti](https://github.com/sausti))
20
+ - Fix another Android 12+ trampoline issue from push notifications. ([#17871](https://github.com/expo/expo/pull/17871) by [@kudo](https://github.com/kudo))
21
+
22
+ ## 0.15.2 — 2022-05-05
23
+
24
+ ### 🐛 Bug fixes
25
+
26
+ - Fixed Android 12+ runtime crash caused by `PendingIntent` misconfiguration. ([#17333](https://github.com/expo/expo/pull/17333) by [@kudo](https://github.com/kudo))
27
+
28
+ ### ⚠️ Notices
29
+
30
+ - Fixed exception on Android 12+ devices for missing `SCHEDULE_EXACT_ALARM` permission. If `scheduleNotificationAsync` needs a precise timer, the `SCHEDULE_EXACT_ALARM` should be explicitly added to **AndroidManifest.xml**. ([#17334](https://github.com/expo/expo/pull/17334) by [@kudo](https://github.com/kudo))
31
+
32
+ ## 0.15.1 — 2022-04-27
33
+
34
+ ### 💡 Others
35
+
36
+ - Remove badge deadcode ([#17205](https://github.com/expo/expo/pull/17205) by [@wschurman](https://github.com/wschurman))
37
+
13
38
  ## 0.15.0 — 2022-04-18
14
39
 
15
40
  ### 🐛 Bug fixes
package/README.md CHANGED
@@ -47,6 +47,8 @@ In order to be able to receive push notifications on the device ensure that your
47
47
 
48
48
  This module requires permission to subscribe to device boot. It's used to setup the scheduled notifications right after the device (re)starts. The `RECEIVE_BOOT_COMPLETED` permission is added automatically.
49
49
 
50
+ **Note:** Starting from Android 12 (API level 31), to schedule the notification that triggers at the exact time, you need to add `<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>` to **AndroidManifest.xml**. You can read more about the exact alarm permission [here](https://developer.android.com/about/versions/12/behavior-changes-12#exact-alarm-permission).
51
+
50
52
  <details><summary><strong>Expand to view how the notification icon and the default color can be customized in a plain React Native app</strong></summary> <p>
51
53
 
52
54
  - **To customize the icon**:
@@ -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.15.0'
6
+ version = '0.15.3'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -74,7 +74,7 @@ android {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
75
  targetSdkVersion safeExtGet("targetSdkVersion", 31)
76
76
  versionCode 21
77
- versionName '0.15.0'
77
+ versionName '0.15.3'
78
78
  }
79
79
 
80
80
  lintOptions {
@@ -92,7 +92,11 @@ dependencies {
92
92
 
93
93
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
94
94
 
95
- api 'com.google.firebase:firebase-messaging:21.1.0'
95
+ api 'com.google.firebase:firebase-messaging:22.0.0'
96
96
 
97
97
  api 'me.leolin:ShortcutBadger:1.1.22@aar'
98
+
99
+ if (project.findProject(':expo-modules-test-core')) {
100
+ testImplementation project(':expo-modules-test-core')
101
+ }
98
102
  }
@@ -27,5 +27,13 @@
27
27
  <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
28
28
  </intent-filter>
29
29
  </receiver>
30
+
31
+ <activity android:name=".service.NotificationForwarderActivity"
32
+ android:theme="@android:style/Theme.Translucent.NoTitleBar"
33
+ android:exported="false"
34
+ android:excludeFromRecents="true"
35
+ android:noHistory="true"
36
+ android:launchMode="standard"
37
+ />
30
38
  </application>
31
39
  </manifest>
@@ -0,0 +1,30 @@
1
+ package expo.modules.notifications.service
2
+
3
+ import android.app.Activity
4
+ import android.content.Intent
5
+ import android.os.Bundle
6
+ import expo.modules.notifications.BuildConfig
7
+
8
+ /**
9
+ * An internal Activity that passes given Intent extras from
10
+ * [NotificationsService.createNotificationResponseIntent]
11
+ * and send broadcasts to [NotificationsService].
12
+ */
13
+ class NotificationForwarderActivity : Activity() {
14
+ override fun onCreate(savedInstanceState: Bundle?) {
15
+ super.onCreate(savedInstanceState)
16
+ val broadcastIntent =
17
+ NotificationsService.createNotificationResponseBroadcastIntent(applicationContext, intent.extras)
18
+ sendBroadcast(broadcastIntent)
19
+ finish()
20
+ }
21
+
22
+ override fun onNewIntent(intent: Intent?) {
23
+ super.onNewIntent(intent)
24
+ // This Activity is expected to launch with new task, supposedly
25
+ // there's no way for `onNewIntent` to be called.
26
+ if (BuildConfig.DEBUG) {
27
+ throw AssertionError()
28
+ }
29
+ }
30
+ }
@@ -7,20 +7,10 @@ import android.content.Context
7
7
  import android.content.Intent
8
8
  import android.content.pm.ActivityInfo
9
9
  import android.net.Uri
10
- import android.os.Bundle
11
- import android.os.Parcel
12
- import android.os.Parcelable
13
- import android.os.ResultReceiver
10
+ import android.os.*
14
11
  import android.util.Log
15
12
  import androidx.core.app.RemoteInput
16
- import expo.modules.notifications.notifications.model.Notification
17
- import expo.modules.notifications.notifications.model.NotificationAction
18
- import expo.modules.notifications.notifications.model.NotificationBehavior
19
- import expo.modules.notifications.notifications.model.NotificationCategory
20
- import expo.modules.notifications.notifications.model.NotificationRequest
21
- import expo.modules.notifications.notifications.model.NotificationResponse
22
- import expo.modules.notifications.notifications.model.TextInputNotificationAction
23
- import expo.modules.notifications.notifications.model.TextInputNotificationResponse
13
+ import expo.modules.notifications.notifications.model.*
24
14
  import expo.modules.notifications.service.delegates.ExpoCategoriesDelegate
25
15
  import expo.modules.notifications.service.delegates.ExpoHandlingDelegate
26
16
  import expo.modules.notifications.service.delegates.ExpoPresentationDelegate
@@ -424,11 +414,13 @@ open class NotificationsService : BroadcastReceiver() {
424
414
  intent.putExtra(IDENTIFIER_KEY, identifier)
425
415
  }
426
416
 
417
+ // We're defaulting to the behaviour prior API 31 (mutable) even though Android recommends immutability
418
+ val mutableFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
427
419
  return PendingIntent.getBroadcast(
428
420
  context,
429
421
  intent.component?.className?.hashCode() ?: NotificationsService::class.java.hashCode(),
430
422
  intent,
431
- PendingIntent.FLAG_UPDATE_CURRENT
423
+ PendingIntent.FLAG_UPDATE_CURRENT or mutableFlag
432
424
  )
433
425
  }
434
426
 
@@ -458,15 +450,67 @@ open class NotificationsService : BroadcastReceiver() {
458
450
  intent.putExtra(NOTIFICATION_ACTION_KEY, action as Parcelable)
459
451
  }
460
452
 
453
+ // Starting from Android 12,
454
+ // [notification trampolines](https://developer.android.com/about/versions/12/behavior-changes-12#identify-notification-trampolines)
455
+ // are not allowed. If the notification wants to open foreground app,
456
+ // we should use the dedicated Activity pendingIntent.
457
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && action.opensAppToForeground()) {
458
+ val notificationResponse = getNotificationResponseFromBroadcastIntent(intent)
459
+ return ExpoHandlingDelegate.createPendingIntentForOpeningApp(context, intent, notificationResponse)
460
+ }
461
+
462
+ // We're defaulting to the behaviour prior API 31 (mutable) even though Android recommends immutability
463
+ val mutableFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
461
464
  return PendingIntent.getBroadcast(
462
465
  context,
463
466
  intent.component?.className?.hashCode() ?: NotificationsService::class.java.hashCode(),
464
467
  intent,
465
- PendingIntent.FLAG_UPDATE_CURRENT
468
+ PendingIntent.FLAG_UPDATE_CURRENT or mutableFlag
466
469
  )
467
470
  }
468
471
 
469
- fun getNotificationResponseFromIntent(intent: Intent): NotificationResponse? {
472
+ /**
473
+ * Recreate an Intent from [createNotificationResponseIntent] extras
474
+ * for [NotificationForwarderActivity] to send broadcasts
475
+ */
476
+ fun createNotificationResponseBroadcastIntent(context: Context, extras: Bundle?): Intent {
477
+ val notification = extras?.getParcelable<Notification>(NOTIFICATION_KEY)
478
+ val action = extras?.getParcelable<NotificationAction>(NOTIFICATION_ACTION_KEY)
479
+ if (notification == null || action == null) {
480
+ throw IllegalArgumentException("notification and action should not be null")
481
+ }
482
+ val backgroundAction = NotificationAction(action.identifier, action.title, false)
483
+ val intent = Intent(
484
+ NOTIFICATION_EVENT_ACTION,
485
+ getUriBuilder()
486
+ .appendPath(notification.notificationRequest.identifier)
487
+ .appendPath("actions")
488
+ .appendPath(backgroundAction.identifier)
489
+ .build()
490
+ ).also { intent ->
491
+ findDesignatedBroadcastReceiver(context, intent)?.let {
492
+ intent.component = ComponentName(it.packageName, it.name)
493
+ }
494
+ intent.putExtra(EVENT_TYPE_KEY, RECEIVE_RESPONSE_TYPE)
495
+ intent.putExtra(NOTIFICATION_KEY, notification)
496
+ intent.putExtra(NOTIFICATION_ACTION_KEY, backgroundAction as Parcelable)
497
+ }
498
+ return intent
499
+ }
500
+
501
+ fun getNotificationResponseFromBroadcastIntent(intent: Intent): NotificationResponse {
502
+ val notification = intent.getParcelableExtra<Notification>(NOTIFICATION_KEY) ?: throw IllegalArgumentException("$NOTIFICATION_KEY not found in the intent extras.")
503
+ val action = intent.getParcelableExtra<NotificationAction>(NOTIFICATION_ACTION_KEY) ?: throw IllegalArgumentException("$NOTIFICATION_ACTION_KEY not found in the intent extras.")
504
+ val response = if (action is TextInputNotificationAction) {
505
+ val userText = action.placeholder ?: RemoteInput.getResultsFromIntent(intent).getString(USER_TEXT_RESPONSE_KEY)
506
+ TextInputNotificationResponse(action, notification, userText)
507
+ } else {
508
+ NotificationResponse(action, notification)
509
+ }
510
+ return response
511
+ }
512
+
513
+ fun getNotificationResponseFromOpenIntent(intent: Intent): NotificationResponse? {
470
514
  intent.getByteArrayExtra(NOTIFICATION_RESPONSE_KEY)?.let { return unmarshalObject(NotificationResponse.CREATOR, it) }
471
515
  intent.getByteArrayExtra(TEXT_INPUT_NOTIFICATION_RESPONSE_KEY)?.let { return unmarshalObject(TextInputNotificationResponse.CREATOR, it) }
472
516
  return null
@@ -646,13 +690,7 @@ open class NotificationsService : BroadcastReceiver() {
646
690
  )
647
691
 
648
692
  open fun onReceiveNotificationResponse(context: Context, intent: Intent) {
649
- val notification = intent.getParcelableExtra<Notification>(NOTIFICATION_KEY)!!
650
- val action = intent.getParcelableExtra<NotificationAction>(NOTIFICATION_ACTION_KEY)!!
651
- val response = if (action is TextInputNotificationAction) {
652
- TextInputNotificationResponse(action, notification, RemoteInput.getResultsFromIntent(intent).getString(USER_TEXT_RESPONSE_KEY))
653
- } else {
654
- NotificationResponse(action, notification)
655
- }
693
+ val response = getNotificationResponseFromBroadcastIntent(intent)
656
694
  getHandlingDelegate(context).handleNotificationResponse(response)
657
695
  }
658
696
 
@@ -1,13 +1,16 @@
1
1
  package expo.modules.notifications.service.delegates
2
2
 
3
+ import android.app.PendingIntent
3
4
  import android.content.Context
4
5
  import android.content.Intent
6
+ import android.os.Build
5
7
  import android.util.Log
6
8
  import androidx.lifecycle.Lifecycle
7
9
  import androidx.lifecycle.ProcessLifecycleOwner
8
10
  import expo.modules.notifications.notifications.NotificationManager
9
11
  import expo.modules.notifications.notifications.model.Notification
10
12
  import expo.modules.notifications.notifications.model.NotificationResponse
13
+ import expo.modules.notifications.service.NotificationForwarderActivity
11
14
  import expo.modules.notifications.service.NotificationsService
12
15
  import expo.modules.notifications.service.interfaces.HandlingDelegate
13
16
  import java.lang.ref.WeakReference
@@ -50,6 +53,44 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
50
53
  }
51
54
  }
52
55
  }
56
+
57
+ /**
58
+ * Create a PendingIntent to open app in foreground.
59
+ * We actually start two Activities
60
+ * - the foreground main Activity
61
+ * - the background [NotificationForwarderActivity] Activity that send notification clicked events through broadcast
62
+ */
63
+ fun createPendingIntentForOpeningApp(context: Context, broadcastIntent: Intent, notificationResponse: NotificationResponse): PendingIntent {
64
+ var intentFlags = PendingIntent.FLAG_UPDATE_CURRENT
65
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
66
+ // The intent may include `RemoteInput` from `TextInputNotificationAction`.
67
+ // For intent with RemoteInput, it should be mutable.
68
+ intentFlags = intentFlags or PendingIntent.FLAG_MUTABLE
69
+ }
70
+ val foregroundActivityIntent = getNotificationActionLauncher(context) ?: getMainActivityLauncher(context) ?: run {
71
+ Log.w("expo-notifications", "No launch intent found for application. Interacting with the notification won't open the app. The implementation uses `getLaunchIntentForPackage` to find appropriate activity.")
72
+ Intent()
73
+ }
74
+ foregroundActivityIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
75
+ NotificationsService.setNotificationResponseToIntent(foregroundActivityIntent, notificationResponse)
76
+ val backgroundActivityIntent = Intent(context, NotificationForwarderActivity::class.java)
77
+ backgroundActivityIntent.putExtras(broadcastIntent)
78
+ return PendingIntent.getActivities(context, 0, arrayOf(foregroundActivityIntent, backgroundActivityIntent), intentFlags)
79
+ }
80
+
81
+ private fun getNotificationActionLauncher(context: Context): Intent? {
82
+ Intent(OPEN_APP_INTENT_ACTION).also { intent ->
83
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
84
+ intent.setPackage(context.applicationContext.packageName)
85
+ context.packageManager.resolveActivity(intent, 0)?.let {
86
+ return intent
87
+ }
88
+ }
89
+ return null
90
+ }
91
+
92
+ private fun getMainActivityLauncher(context: Context) =
93
+ context.packageManager.getLaunchIntentForPackage(context.packageName)
53
94
  }
54
95
 
55
96
  fun isAppInForeground() = ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
@@ -61,11 +102,20 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
61
102
  getListeners().forEach {
62
103
  it.onNotificationReceived(notification)
63
104
  }
64
- } else {
105
+ } else if (notification.shouldPresent()) {
65
106
  NotificationsService.present(context, notification)
66
107
  }
67
108
  }
68
109
 
110
+ /**
111
+ * If the app is backgrounded, a notification is only presented if
112
+ * the title and or text is present. If both are null or empty, this is a "data-only" or "silent"
113
+ * notification that should not be presented to the user.
114
+ */
115
+ private fun Notification.shouldPresent(): Boolean {
116
+ return !(notificationRequest.content.title.isNullOrEmpty() && notificationRequest.content.text.isNullOrEmpty())
117
+ }
118
+
69
119
  override fun handleNotificationResponse(notificationResponse: NotificationResponse) {
70
120
  if (notificationResponse.action.opensAppToForeground()) {
71
121
  openAppToForeground(context, notificationResponse)
@@ -90,20 +140,6 @@ class ExpoHandlingDelegate(protected val context: Context) : HandlingDelegate {
90
140
  Log.w("expo-notifications", "No launch intent found for application. Interacting with the notification won't open the app. The implementation uses `getLaunchIntentForPackage` to find appropriate activity.")
91
141
  }
92
142
 
93
- private fun getNotificationActionLauncher(context: Context): Intent? {
94
- Intent(OPEN_APP_INTENT_ACTION).also { intent ->
95
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
96
- intent.setPackage(context.applicationContext.packageName)
97
- context.packageManager.resolveActivity(intent, 0)?.let {
98
- return intent
99
- }
100
- }
101
- return null
102
- }
103
-
104
- private fun getMainActivityLauncher(context: Context) =
105
- context.packageManager.getLaunchIntentForPackage(context.packageName)
106
-
107
143
  override fun handleNotificationsDropped() {
108
144
  getListeners().forEach {
109
145
  it.onNotificationsDropped()
@@ -1,7 +1,9 @@
1
1
  package expo.modules.notifications.service.delegates
2
2
 
3
3
  import android.app.AlarmManager
4
+ import android.app.PendingIntent
4
5
  import android.content.Context
6
+ import android.os.Build
5
7
  import android.util.Log
6
8
  import androidx.core.app.AlarmManagerCompat
7
9
  import expo.modules.notifications.notifications.interfaces.SchedulableNotificationTrigger
@@ -57,12 +59,7 @@ class ExpoSchedulingDelegate(protected val context: Context) : SchedulingDelegat
57
59
  NotificationsService.removeScheduledNotification(context, request.identifier)
58
60
  } else {
59
61
  store.saveNotificationRequest(request)
60
- AlarmManagerCompat.setExactAndAllowWhileIdle(
61
- alarmManager,
62
- AlarmManager.RTC_WAKEUP,
63
- nextTriggerDate.time,
64
- NotificationsService.createNotificationTrigger(context, request.identifier)
65
- )
62
+ setupAlarm(nextTriggerDate.time, NotificationsService.createNotificationTrigger(context, request.identifier))
66
63
  }
67
64
  }
68
65
  }
@@ -99,4 +96,22 @@ class ExpoSchedulingDelegate(protected val context: Context) : SchedulingDelegat
99
96
  alarmManager.cancel(NotificationsService.createNotificationTrigger(context, it))
100
97
  }
101
98
  }
99
+
100
+ private fun setupAlarm(triggerAtMillis: Long, operation: PendingIntent) {
101
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || alarmManager.canScheduleExactAlarms()) {
102
+ AlarmManagerCompat.setExactAndAllowWhileIdle(
103
+ alarmManager,
104
+ AlarmManager.RTC_WAKEUP,
105
+ triggerAtMillis,
106
+ operation
107
+ )
108
+ } else {
109
+ AlarmManagerCompat.setAndAllowWhileIdle(
110
+ alarmManager,
111
+ AlarmManager.RTC_WAKEUP,
112
+ triggerAtMillis,
113
+ operation
114
+ )
115
+ }
116
+ }
102
117
  }
@@ -24,6 +24,7 @@ public class PushTokenModule extends ExportedModule implements PushTokenListener
24
24
  private final static String NEW_TOKEN_EVENT_TOKEN_KEY = "devicePushToken";
25
25
 
26
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";
27
28
 
28
29
  private PushTokenManager mPushTokenManager;
29
30
  private EventEmitter mEventEmitter;
@@ -81,6 +82,23 @@ public class PushTokenModule extends ExportedModule implements PushTokenListener
81
82
  });
82
83
  }
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
+
84
102
  /**
85
103
  * Callback called when {@link PushTokenManager} gets notified of a new token.
86
104
  * Emits a {@link PushTokenModule#NEW_TOKEN_EVENT_NAME} event.
@@ -1,5 +1,6 @@
1
1
  import { ProxyNativeModule } from 'expo-modules-core';
2
2
  export interface PushTokenManagerModule extends ProxyNativeModule {
3
3
  getDevicePushTokenAsync?: () => Promise<string>;
4
+ unregisterForNotificationsAsync?: () => Promise<void>;
4
5
  }
5
6
  //# sourceMappingURL=PushTokenManager.types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PushTokenManager.types.d.ts","sourceRoot":"","sources":["../src/PushTokenManager.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD"}
1
+ {"version":3,"file":"PushTokenManager.types.d.ts","sourceRoot":"","sources":["../src/PushTokenManager.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,+BAA+B,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"PushTokenManager.types.js","sourceRoot":"","sources":["../src/PushTokenManager.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ProxyNativeModule } from 'expo-modules-core';\n\nexport interface PushTokenManagerModule extends ProxyNativeModule {\n getDevicePushTokenAsync?: () => Promise<string>;\n}\n"]}
1
+ {"version":3,"file":"PushTokenManager.types.js","sourceRoot":"","sources":["../src/PushTokenManager.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ProxyNativeModule } from 'expo-modules-core';\n\nexport interface PushTokenManagerModule extends ProxyNativeModule {\n getDevicePushTokenAsync?: () => Promise<string>;\n unregisterForNotificationsAsync?: () => Promise<void>;\n}\n"]}
package/build/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';
2
+ export { default as unregisterForNotificationsAsync } from './unregisterForNotificationsAsync';
2
3
  export { default as getExpoPushTokenAsync } from './getExpoPushTokenAsync';
3
4
  export { default as getPresentedNotificationsAsync } from './getPresentedNotificationsAsync';
4
5
  export { default as presentNotificationAsync } from './presentNotificationAsync';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AACzG,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AACzG,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
package/build/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';
2
+ export { default as unregisterForNotificationsAsync } from './unregisterForNotificationsAsync';
2
3
  export { default as getExpoPushTokenAsync } from './getExpoPushTokenAsync';
3
4
  export { default as getPresentedNotificationsAsync } from './getPresentedNotificationsAsync';
4
5
  export { default as presentNotificationAsync } from './presentNotificationAsync';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AACzG,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC","sourcesContent":["export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';\nexport { default as getExpoPushTokenAsync } from './getExpoPushTokenAsync';\nexport { default as getPresentedNotificationsAsync } from './getPresentedNotificationsAsync';\nexport { default as presentNotificationAsync } from './presentNotificationAsync';\nexport { default as dismissNotificationAsync } from './dismissNotificationAsync';\nexport { default as dismissAllNotificationsAsync } from './dismissAllNotificationsAsync';\nexport { default as getNotificationChannelsAsync } from './getNotificationChannelsAsync';\nexport { default as getNotificationChannelAsync } from './getNotificationChannelAsync';\nexport { default as setNotificationChannelAsync } from './setNotificationChannelAsync';\nexport { default as deleteNotificationChannelAsync } from './deleteNotificationChannelAsync';\nexport { default as getNotificationChannelGroupsAsync } from './getNotificationChannelGroupsAsync';\nexport { default as getNotificationChannelGroupAsync } from './getNotificationChannelGroupAsync';\nexport { default as setNotificationChannelGroupAsync } from './setNotificationChannelGroupAsync';\nexport { default as deleteNotificationChannelGroupAsync } from './deleteNotificationChannelGroupAsync';\nexport { default as getBadgeCountAsync } from './getBadgeCountAsync';\nexport { default as setBadgeCountAsync } from './setBadgeCountAsync';\nexport { default as getAllScheduledNotificationsAsync } from './getAllScheduledNotificationsAsync';\nexport { default as scheduleNotificationAsync } from './scheduleNotificationAsync';\nexport { default as cancelScheduledNotificationAsync } from './cancelScheduledNotificationAsync';\nexport { default as cancelAllScheduledNotificationsAsync } from './cancelAllScheduledNotificationsAsync';\nexport { default as getNotificationCategoriesAsync } from './getNotificationCategoriesAsync';\nexport { default as setNotificationCategoryAsync } from './setNotificationCategoryAsync';\nexport { default as deleteNotificationCategoryAsync } from './deleteNotificationCategoryAsync';\nexport { default as getNextTriggerDateAsync } from './getNextTriggerDateAsync';\nexport { default as useLastNotificationResponse } from './useLastNotificationResponse';\nexport { setAutoServerRegistrationEnabledAsync } from './DevicePushTokenAutoRegistration.fx';\nexport { default as registerTaskAsync } from './registerTaskAsync';\nexport { default as unregisterTaskAsync } from './unregisterTaskAsync';\nexport * from './TokenEmitter';\nexport * from './NotificationsEmitter';\nexport * from './NotificationsHandler';\nexport * from './NotificationPermissions';\nexport * from './NotificationChannelGroupManager.types';\nexport * from './NotificationChannelManager.types';\nexport * from './NotificationPermissions.types';\nexport * from './Notifications.types';\nexport * from './Tokens.types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACjF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AACvG,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnF,OAAO,EAAE,OAAO,IAAI,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,EAAE,OAAO,IAAI,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AACzG,OAAO,EAAE,OAAO,IAAI,8BAA8B,EAAE,MAAM,kCAAkC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,OAAO,IAAI,+BAA+B,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,OAAO,IAAI,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC","sourcesContent":["export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';\nexport { default as unregisterForNotificationsAsync } from './unregisterForNotificationsAsync';\nexport { default as getExpoPushTokenAsync } from './getExpoPushTokenAsync';\nexport { default as getPresentedNotificationsAsync } from './getPresentedNotificationsAsync';\nexport { default as presentNotificationAsync } from './presentNotificationAsync';\nexport { default as dismissNotificationAsync } from './dismissNotificationAsync';\nexport { default as dismissAllNotificationsAsync } from './dismissAllNotificationsAsync';\nexport { default as getNotificationChannelsAsync } from './getNotificationChannelsAsync';\nexport { default as getNotificationChannelAsync } from './getNotificationChannelAsync';\nexport { default as setNotificationChannelAsync } from './setNotificationChannelAsync';\nexport { default as deleteNotificationChannelAsync } from './deleteNotificationChannelAsync';\nexport { default as getNotificationChannelGroupsAsync } from './getNotificationChannelGroupsAsync';\nexport { default as getNotificationChannelGroupAsync } from './getNotificationChannelGroupAsync';\nexport { default as setNotificationChannelGroupAsync } from './setNotificationChannelGroupAsync';\nexport { default as deleteNotificationChannelGroupAsync } from './deleteNotificationChannelGroupAsync';\nexport { default as getBadgeCountAsync } from './getBadgeCountAsync';\nexport { default as setBadgeCountAsync } from './setBadgeCountAsync';\nexport { default as getAllScheduledNotificationsAsync } from './getAllScheduledNotificationsAsync';\nexport { default as scheduleNotificationAsync } from './scheduleNotificationAsync';\nexport { default as cancelScheduledNotificationAsync } from './cancelScheduledNotificationAsync';\nexport { default as cancelAllScheduledNotificationsAsync } from './cancelAllScheduledNotificationsAsync';\nexport { default as getNotificationCategoriesAsync } from './getNotificationCategoriesAsync';\nexport { default as setNotificationCategoryAsync } from './setNotificationCategoryAsync';\nexport { default as deleteNotificationCategoryAsync } from './deleteNotificationCategoryAsync';\nexport { default as getNextTriggerDateAsync } from './getNextTriggerDateAsync';\nexport { default as useLastNotificationResponse } from './useLastNotificationResponse';\nexport { setAutoServerRegistrationEnabledAsync } from './DevicePushTokenAutoRegistration.fx';\nexport { default as registerTaskAsync } from './registerTaskAsync';\nexport { default as unregisterTaskAsync } from './unregisterTaskAsync';\nexport * from './TokenEmitter';\nexport * from './NotificationsEmitter';\nexport * from './NotificationsHandler';\nexport * from './NotificationPermissions';\nexport * from './NotificationChannelGroupManager.types';\nexport * from './NotificationChannelManager.types';\nexport * from './NotificationPermissions.types';\nexport * from './Notifications.types';\nexport * from './Tokens.types';\n"]}
@@ -0,0 +1,2 @@
1
+ export default function unregisterForNotificationsAsync(): Promise<void>;
2
+ //# sourceMappingURL=unregisterForNotificationsAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unregisterForNotificationsAsync.d.ts","sourceRoot":"","sources":["../src/unregisterForNotificationsAsync.ts"],"names":[],"mappings":"AAIA,wBAA8B,+BAA+B,IAAI,OAAO,CAAC,IAAI,CAAC,CAK7E"}
@@ -0,0 +1,9 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+ import PushTokenManager from './PushTokenManager';
3
+ export default async function unregisterForNotificationsAsync() {
4
+ if (!PushTokenManager.unregisterForNotificationsAsync) {
5
+ throw new UnavailabilityError('ExpoNotifications', 'unregisterForNotificationsAsync');
6
+ }
7
+ return PushTokenManager.unregisterForNotificationsAsync();
8
+ }
9
+ //# sourceMappingURL=unregisterForNotificationsAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unregisterForNotificationsAsync.js","sourceRoot":"","sources":["../src/unregisterForNotificationsAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,gBAAgB,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,+BAA+B;IAC3D,IAAI,CAAC,gBAAgB,CAAC,+BAA+B,EAAE;QACrD,MAAM,IAAI,mBAAmB,CAAC,mBAAmB,EAAE,iCAAiC,CAAC,CAAC;KACvF;IACD,OAAO,gBAAgB,CAAC,+BAA+B,EAAE,CAAC;AAC5D,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\n\nimport PushTokenManager from './PushTokenManager';\n\nexport default async function unregisterForNotificationsAsync(): Promise<void> {\n if (!PushTokenManager.unregisterForNotificationsAsync) {\n throw new UnavailabilityError('ExpoNotifications', 'unregisterForNotificationsAsync');\n }\n return PushTokenManager.unregisterForNotificationsAsync();\n}\n"]}
@@ -45,6 +45,13 @@ EX_EXPORT_METHOD_AS(getDevicePushTokenAsync,
45
45
  });
46
46
  }
47
47
 
48
+ EX_EXPORT_METHOD_AS(unregisterForNotificationsAsync,
49
+ unregisterForNotificationsAsync:(EXPromiseResolveBlock)resolve reject:(EXPromiseRejectBlock)reject)
50
+ {
51
+ [[UIApplication sharedApplication] unregisterForRemoteNotifications];
52
+ resolve(nil);
53
+ }
54
+
48
55
  # pragma mark - EXModuleRegistryConsumer
49
56
 
50
57
  - (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
@@ -6,30 +6,30 @@
6
6
  <array>
7
7
  <dict>
8
8
  <key>LibraryIdentifier</key>
9
- <string>ios-arm64_x86_64-simulator</string>
9
+ <string>ios-arm64</string>
10
10
  <key>LibraryPath</key>
11
11
  <string>EXNotifications.framework</string>
12
12
  <key>SupportedArchitectures</key>
13
13
  <array>
14
14
  <string>arm64</string>
15
- <string>x86_64</string>
16
15
  </array>
17
16
  <key>SupportedPlatform</key>
18
17
  <string>ios</string>
19
- <key>SupportedPlatformVariant</key>
20
- <string>simulator</string>
21
18
  </dict>
22
19
  <dict>
23
20
  <key>LibraryIdentifier</key>
24
- <string>ios-arm64</string>
21
+ <string>ios-arm64_x86_64-simulator</string>
25
22
  <key>LibraryPath</key>
26
23
  <string>EXNotifications.framework</string>
27
24
  <key>SupportedArchitectures</key>
28
25
  <array>
29
26
  <string>arm64</string>
27
+ <string>x86_64</string>
30
28
  </array>
31
29
  <key>SupportedPlatform</key>
32
30
  <string>ios</string>
31
+ <key>SupportedPlatformVariant</key>
32
+ <string>simulator</string>
33
33
  </dict>
34
34
  </array>
35
35
  <key>CFBundlePackageType</key>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-notifications",
3
- "version": "0.15.0",
3
+ "version": "0.15.3",
4
4
  "description": "Notifications module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -58,5 +58,5 @@
58
58
  "peerDependencies": {
59
59
  "expo": "*"
60
60
  },
61
- "gitHead": "22dce752354bb429c84851bc4389abe47a766b1f"
61
+ "gitHead": "aa4163b5cb533fd4b3fc583e3958b36eaa97617c"
62
62
  }
@@ -2,4 +2,5 @@ import { ProxyNativeModule } from 'expo-modules-core';
2
2
 
3
3
  export interface PushTokenManagerModule extends ProxyNativeModule {
4
4
  getDevicePushTokenAsync?: () => Promise<string>;
5
+ unregisterForNotificationsAsync?: () => Promise<void>;
5
6
  }
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as getDevicePushTokenAsync } from './getDevicePushTokenAsync';
2
+ export { default as unregisterForNotificationsAsync } from './unregisterForNotificationsAsync';
2
3
  export { default as getExpoPushTokenAsync } from './getExpoPushTokenAsync';
3
4
  export { default as getPresentedNotificationsAsync } from './getPresentedNotificationsAsync';
4
5
  export { default as presentNotificationAsync } from './presentNotificationAsync';
@@ -0,0 +1,10 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+
3
+ import PushTokenManager from './PushTokenManager';
4
+
5
+ export default async function unregisterForNotificationsAsync(): Promise<void> {
6
+ if (!PushTokenManager.unregisterForNotificationsAsync) {
7
+ throw new UnavailabilityError('ExpoNotifications', 'unregisterForNotificationsAsync');
8
+ }
9
+ return PushTokenManager.unregisterForNotificationsAsync();
10
+ }
@@ -1,56 +0,0 @@
1
- package expo.modules.notifications.badge;
2
-
3
- import android.app.Notification;
4
- import android.content.Context;
5
- import android.util.Log;
6
-
7
- import expo.modules.core.ModuleRegistry;
8
- import expo.modules.core.errors.CodedRuntimeException;
9
-
10
- import androidx.annotation.Nullable;
11
- import expo.modules.notifications.badge.interfaces.BadgeManager;
12
- import expo.modules.notifications.notifications.presentation.builders.BadgeSettingNotificationBuilder;
13
- import expo.modules.notifications.notifications.presentation.effects.BaseNotificationEffect;
14
-
15
- public class SetBadgeCountNotificationEffect extends BaseNotificationEffect {
16
- private static final String EXTRAS_BADGE_KEY = BadgeSettingNotificationBuilder.EXTRAS_BADGE_KEY;
17
-
18
- private BadgeManager mBadgeManager;
19
-
20
- public SetBadgeCountNotificationEffect(Context context) {
21
- super(context);
22
- }
23
-
24
- @Override
25
- public void onCreate(ModuleRegistry moduleRegistry) {
26
- super.onCreate(moduleRegistry);
27
- mBadgeManager = moduleRegistry.getSingletonModule("BadgeManager", BadgeManager.class);
28
- }
29
-
30
- @Override
31
- public boolean onNotificationPresented(@Nullable String tag, int id, Notification notification) {
32
- return applyBadgeFromNotification(notification);
33
- }
34
-
35
- @Override
36
- public boolean onNotificationPresentationFailed(@Nullable String tag, int id, Notification notification) {
37
- // We could also just return false here. Then, notifications that failed to be presented
38
- // wouldn't affect badge count. Applying badge count from failed notifications lets us
39
- // properly handle badge-update-only notifications.
40
- return applyBadgeFromNotification(notification);
41
- }
42
-
43
- private boolean applyBadgeFromNotification(Notification notification) {
44
- try {
45
- if (notification.extras.get(EXTRAS_BADGE_KEY) != null && mBadgeManager != null) {
46
- mBadgeManager.setBadgeCount(notification.extras.getInt(EXTRAS_BADGE_KEY));
47
- return true;
48
- }
49
- } catch (CodedRuntimeException e) {
50
- // We can't do anything but log the error and return false.
51
- Log.e(e.getCode(), e.getMessage());
52
- }
53
-
54
- return false;
55
- }
56
- }
@@ -1,66 +0,0 @@
1
- package expo.modules.notifications.notifications.presentation.builders;
2
-
3
- import android.app.Notification;
4
- import android.content.Context;
5
- import android.os.Bundle;
6
-
7
- import androidx.core.app.NotificationCompat;
8
- import expo.modules.notifications.notifications.model.NotificationContent;
9
- import me.leolin.shortcutbadger.ShortcutBadger;
10
-
11
- public class BadgeSettingNotificationBuilder extends ExpoNotificationBuilder {
12
- public static final String EXTRAS_BADGE_KEY = "badge";
13
-
14
- public BadgeSettingNotificationBuilder(Context context) {
15
- super(context);
16
- }
17
-
18
- @Override
19
- protected NotificationCompat.Builder createBuilder() {
20
- NotificationCompat.Builder builder = super.createBuilder();
21
-
22
- if (shouldSetBadge()) {
23
- // Forward information about badge count to set
24
- // to SetBadgeCountNotificationEffect.
25
- Bundle extras = builder.getExtras();
26
- extras.putInt(EXTRAS_BADGE_KEY, getBadgeCount());
27
- builder.setExtras(extras);
28
- }
29
-
30
- return builder;
31
- }
32
-
33
- @Override
34
- public Notification build() {
35
- Notification notification = super.build();
36
-
37
- if (shouldSetBadge()) {
38
- // Xiaomi devices require this extra notification configuration step
39
- // https://github.com/leolin310148/ShortcutBadger/wiki/Xiaomi-Device-Support
40
- // Badge for other devices is set as an effect in SetBadgeCountNotificationEffect
41
- ShortcutBadger.applyNotification(getContext(), notification, getBadgeCount());
42
- }
43
-
44
- return notification;
45
- }
46
-
47
- private boolean shouldSetBadge() {
48
- boolean behaviorAllowsBadge = getNotificationBehavior() == null || getNotificationBehavior().shouldSetBadge();
49
-
50
- NotificationContent content = getNotificationContent();
51
- boolean contentDefinesBadge = content.getBadgeCount() != null;
52
-
53
- return behaviorAllowsBadge && contentDefinesBadge;
54
- }
55
-
56
- private int getBadgeCount() {
57
- Number badgeCount = getNotificationContent().getBadgeCount();
58
- if (badgeCount == null) {
59
- // We should never end up here, since getBadgeCount is guarded by
60
- // shouldSetBadge, which checks if badgeCount is null, but in case
61
- // this is ever called, let's not crash the application.
62
- return 0;
63
- }
64
- return badgeCount.intValue();
65
- }
66
- }