@react-native-firebase/messaging 16.7.0 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,24 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [17.1.0](https://github.com/invertase/react-native-firebase/compare/v17.0.0...v17.1.0) (2023-02-09)
7
+
8
+ **Note:** Version bump only for package @react-native-firebase/messaging
9
+
10
+ ## [17.0.0](https://github.com/invertase/react-native-firebase/compare/v16.7.0...v17.0.0) (2023-02-02)
11
+
12
+ ### ⚠ BREAKING CHANGES
13
+
14
+ - **app, ios:** You must have an APNS token before calling getToken to
15
+ get an FCM token on iOS. Previously it was not required. See documentation
16
+ for setAPNSToken if you are using getToken in testing or have disabled
17
+ FCM Swizzling, and use setAPNSToken to set a token before using getToken
18
+
19
+ ### Features
20
+
21
+ - **app, ios:** adopt firebase-ios-sdk 10.4.0 ([1b8df4c](https://github.com/invertase/react-native-firebase/commit/1b8df4c8e55d474c09e301f9c7b58b6128ae6485))
22
+ - **messaging, ios:** new setAPNSToken API / getToken works on M1 Simulator ([8d75b36](https://github.com/invertase/react-native-firebase/commit/8d75b36f485af07ecfa653192ca56f761d0cc5b7))
23
+
6
24
  ## [16.7.0](https://github.com/invertase/react-native-firebase/compare/v16.6.0...v16.7.0) (2023-01-28)
7
25
 
8
26
  **Note:** Version bump only for package @react-native-firebase/messaging
@@ -87,12 +87,12 @@
87
87
  (RCTRootView *)[UIApplication sharedApplication].delegate.window.rootViewController.view;
88
88
  }
89
89
 
90
- #if !(TARGET_IPHONE_SIMULATOR)
90
+ // #if !(TARGET_IPHONE_SIMULATOR)
91
91
  if ([[RNFBJSON shared] getBooleanValue:@"messaging_ios_auto_register_for_remote_messages"
92
92
  defaultValue:YES]) {
93
93
  [[UIApplication sharedApplication] registerForRemoteNotifications];
94
94
  }
95
- #endif
95
+ // #endif
96
96
 
97
97
  if (notification.userInfo[UIApplicationLaunchOptionsRemoteNotificationKey]) {
98
98
  if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
@@ -108,7 +108,7 @@
108
108
  }
109
109
  }
110
110
 
111
- #if !(TARGET_IPHONE_SIMULATOR)
111
+ // #if !(TARGET_IPHONE_SIMULATOR)
112
112
  // When an app launches in the background (BG mode) and is launched with the notification
113
113
  // launch option the app delegate method
114
114
  // application:didReceiveRemoteNotification:fetchCompletionHandler: will not get called unless
@@ -118,7 +118,7 @@
118
118
  // `messaging_ios_auto_register_for_remote_messages` as this is most likely an app launching
119
119
  // as a result of a remote notification - so has been registered previously
120
120
  [[UIApplication sharedApplication] registerForRemoteNotifications];
121
- #endif
121
+ // #endif
122
122
  } else {
123
123
  if (rctRootView != nil) {
124
124
  isHeadless = NO;
@@ -114,7 +114,6 @@ RCT_EXPORT_METHOD(getToken
114
114
  : (NSString *)senderId
115
115
  : (RCTPromiseResolveBlock)resolve
116
116
  : (RCTPromiseRejectBlock)reject) {
117
- #if !(TARGET_IPHONE_SIMULATOR)
118
117
  if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
119
118
  [RNFBSharedUtils
120
119
  rejectPromiseWithUserInfo:reject
@@ -126,7 +125,14 @@ RCT_EXPORT_METHOD(getToken
126
125
  }];
127
126
  return;
128
127
  }
129
- #endif
128
+
129
+ // As of firebase-ios-sdk 10.4.0, an APNS token is strictly required for getToken to work
130
+ NSData *apnsToken = [FIRMessaging messaging].APNSToken;
131
+ if (apnsToken == nil) {
132
+ DLog(@"RNFBMessaging getToken - no APNS token is available. Firebase requires an APNS token to "
133
+ @"vend an FCM token in firebase-ios-sdk 10.4.0 and higher. See documentation on "
134
+ @"setAPNSToken and getAPNSToken.")
135
+ }
130
136
 
131
137
  [[FIRMessaging messaging]
132
138
  retrieveFCMTokenForSenderID:senderId
@@ -160,7 +166,17 @@ RCT_EXPORT_METHOD(getAPNSToken : (RCTPromiseResolveBlock)resolve : (RCTPromiseRe
160
166
  if (apnsToken) {
161
167
  resolve([RNFBMessagingSerializer APNSTokenFromNSData:apnsToken]);
162
168
  } else {
163
- #if !(TARGET_IPHONE_SIMULATOR)
169
+ #if TARGET_IPHONE_SIMULATOR
170
+ #if !TARGET_CPU_ARM64
171
+ DLog(@"RNFBMessaging getAPNSToken - Simulator without APNS support detected, with no token "
172
+ @"set. Use setAPNSToken with an arbitrary string if needed for testing.")
173
+ resolve([NSNull null]);
174
+ return;
175
+ #endif
176
+ DLog(@"RNFBMessaging getAPNSToken - ARM64 Simulator detected, but no APNS token set. Assuming "
177
+ @"APNS token is possible. macOS13+ / iOS16+ / M1 mac required for assumption to be valid. "
178
+ @"Use setAPNSToken in testing if needed.");
179
+ #endif
164
180
  if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == NO) {
165
181
  [RNFBSharedUtils
166
182
  rejectPromiseWithUserInfo:reject
@@ -172,11 +188,28 @@ RCT_EXPORT_METHOD(getAPNSToken : (RCTPromiseResolveBlock)resolve : (RCTPromiseRe
172
188
  }];
173
189
  return;
174
190
  }
175
- #endif
176
- resolve([NSNull null]);
177
191
  }
178
192
  }
179
193
 
194
+ RCT_EXPORT_METHOD(setAPNSToken
195
+ : (NSString *)token
196
+ : (NSString *)type
197
+ : (RCTPromiseResolveBlock)resolve
198
+ : (RCTPromiseRejectBlock)reject) {
199
+ // Default to unknown (determined by provisioning profile) type, but user may have passed type as
200
+ // param
201
+ FIRMessagingAPNSTokenType tokenType = FIRMessagingAPNSTokenTypeUnknown;
202
+ if (type != nil && [@"prod" isEqualToString:type]) {
203
+ tokenType = FIRMessagingAPNSTokenTypeProd;
204
+ } else if (type != nil && [@"sandbox" isEqualToString:type]) {
205
+ tokenType = FIRMessagingAPNSTokenTypeSandbox;
206
+ }
207
+
208
+ [[FIRMessaging messaging] setAPNSToken:[RNFBMessagingSerializer APNSTokenDataFromNSString:token]
209
+ type:tokenType];
210
+ resolve([NSNull null]);
211
+ }
212
+
180
213
  RCT_EXPORT_METHOD(getIsHeadless : (RCTPromiseResolveBlock)resolve : (RCTPromiseRejectBlock)reject) {
181
214
  RNFBMessagingNSNotificationCenter *notifCenter =
182
215
  [RNFBMessagingNSNotificationCenter sharedInstance];
@@ -267,12 +300,19 @@ RCT_EXPORT_METHOD(registerForRemoteNotifications
267
300
  : (RCTPromiseResolveBlock)resolve
268
301
  : (RCTPromiseRejectBlock)reject) {
269
302
  #if TARGET_IPHONE_SIMULATOR
303
+ #if !TARGET_CPU_ARM64
304
+ // Do the registration on this unsupported simulator, but don't set up to wait for a token that
305
+ // won't arrive
306
+ [[UIApplication sharedApplication] registerForRemoteNotifications];
270
307
  resolve(@([RCTConvert BOOL:@(YES)]));
271
308
  return;
309
+ #endif
310
+ DLog(@"RNFBMessaging registerForRemoteNotifications ARM64 Simulator detected, attempting real "
311
+ @"registration. macOS13+ / iOS16+ / M1 mac required or will timeout.")
272
312
  #endif
273
313
  #pragma clang diagnostic push
274
314
  #pragma clang diagnostic ignored "-Wunreachable-code"
275
- if (@available(iOS 10.0, *)) {
315
+ if (@available(iOS 10.0, *)) {
276
316
  #pragma pop
277
317
  if ([UIApplication sharedApplication].isRegisteredForRemoteNotifications == YES) {
278
318
  resolve(@([RCTConvert BOOL:@(YES)]));
@@ -286,7 +326,8 @@ RCT_EXPORT_METHOD(registerForRemoteNotifications
286
326
  dispatch_async(dispatch_get_main_queue(), ^{
287
327
  [[UIApplication sharedApplication] registerForRemoteNotifications];
288
328
  });
289
- } else {
329
+ }
330
+ else {
290
331
  [RNFBSharedUtils
291
332
  rejectPromiseWithUserInfo:reject
292
333
  userInfo:[@{
@@ -21,6 +21,8 @@
21
21
 
22
22
  @interface RNFBMessagingSerializer : NSObject
23
23
 
24
+ + (NSData *)APNSTokenDataFromNSString:(NSString *)token;
25
+
24
26
  + (NSString *)APNSTokenFromNSData:(NSData *)tokenData;
25
27
 
26
28
  + (NSDictionary *)notificationToDict:(UNNotification *)notification;
@@ -20,6 +20,24 @@
20
20
 
21
21
  @implementation RNFBMessagingSerializer
22
22
 
23
+ + (NSData *)APNSTokenDataFromNSString:(NSString *)token {
24
+ NSString *string = [token lowercaseString];
25
+ NSMutableData *data = [NSMutableData new];
26
+ unsigned char whole_byte;
27
+ char byte_chars[3] = {'\0', '\0', '\0'};
28
+ NSUInteger i = 0;
29
+ NSUInteger length = string.length;
30
+ while (i < length - 1) {
31
+ char c = [string characterAtIndex:i++];
32
+ if (c < '0' || (c > '9' && c < 'a') || c > 'f') continue;
33
+ byte_chars[0] = c;
34
+ byte_chars[1] = [string characterAtIndex:i++];
35
+ whole_byte = strtol(byte_chars, NULL, 16);
36
+ [data appendBytes:&whole_byte length:1];
37
+ }
38
+ return data;
39
+ }
40
+
23
41
  + (NSString *)APNSTokenFromNSData:(NSData *)tokenData {
24
42
  const char *data = [tokenData bytes];
25
43
 
package/lib/index.d.ts CHANGED
@@ -881,10 +881,43 @@ export namespace FirebaseMessagingTypes {
881
881
  * }
882
882
  * ```
883
883
  *
884
- * @ios
884
+ * @platform ios
885
885
  */
886
886
  getAPNSToken(): Promise<string | null>;
887
887
 
888
+ /**
889
+ * On iOS, This method is used to set the APNs Token received by the application delegate.
890
+ * Note that the token is expected to be a hexadecimal string, as it is an NSData type in
891
+ * the underlying native firebase SDK, and raw data may only be passed as a string if it is
892
+ * hex encoded. Calling code is responsible for correct encoding, you should verify by comparing
893
+ * the results of `getAPNSToken()` with your token parameter to make sure they are equivalent
894
+ *
895
+ * Messaging uses method swizzling to ensure that the APNs token is set automatically.
896
+ * However, if you have disabled swizzling by setting FirebaseAppDelegateProxyEnabled to NO
897
+ * in your app’s Info.plist, you should manually set the APNs token in your application
898
+ * delegate’s application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method.
899
+ *
900
+ * If you would like to set the type of the APNs token, rather than relying on automatic
901
+ * detection, provide a type of either 'prod', 'sandbox'. Omitting the type parameter
902
+ * or specifying 'unknown' will rely on automatic type detection based on provisioning profile.
903
+ *
904
+ * At a native level you may also call objective-c `[FIRMessaging setAPNSToken];` as needed
905
+ *
906
+ * > You can safely call this method on Android without platform checks. It's a no-op on Android and will promise resolve `null`.
907
+ *
908
+ * #### Example
909
+ *
910
+ * ```js
911
+ * let myAPNSToken = someOthermodule.someWayToGetAPNSToken();
912
+ * await firebase.messaging().setAPNSToken(myAPNSToken);
913
+ * ```
914
+ *
915
+ * @param token a hexadecimal string representing your APNS token
916
+ * @param type optional string specifying 'prod', 'sandbox' or 'unknown' token type
917
+ * @platform ios
918
+ */
919
+ setAPNSToken(token: string, type?: string): Promise<void>;
920
+
888
921
  /**
889
922
  * Returns a `AuthorizationStatus` as to whether the user has messaging permission for this app.
890
923
  *
package/lib/index.js CHANGED
@@ -51,6 +51,7 @@ export {
51
51
  isDeviceRegisteredForRemoteMessages,
52
52
  unregisterDeviceForRemoteMessages,
53
53
  getAPNSToken,
54
+ setAPNSToken,
54
55
  hasPermission,
55
56
  onDeletedMessages,
56
57
  onMessageSent,
@@ -340,6 +341,27 @@ class FirebaseMessagingModule extends FirebaseModule {
340
341
  return this.native.getAPNSToken();
341
342
  }
342
343
 
344
+ /**
345
+ * @platform ios
346
+ */
347
+ setAPNSToken(token, type) {
348
+ if (isUndefined(token) || !isString(token)) {
349
+ throw new Error("firebase.messaging().setAPNSToken(*) 'token' expected a string value.");
350
+ }
351
+
352
+ if (!isUndefined(type) && (!isString(type) || !['prod', 'sandbox', 'unknown'].includes(type))) {
353
+ throw new Error(
354
+ "firebase.messaging().setAPNSToken(*) 'type' expected one of 'prod', 'sandbox', or 'unknown'.",
355
+ );
356
+ }
357
+
358
+ if (isAndroid) {
359
+ return Promise.resolve(null);
360
+ }
361
+
362
+ return this.native.setAPNSToken(token, type);
363
+ }
364
+
343
365
  hasPermission() {
344
366
  return this.native.hasPermission();
345
367
  }
package/lib/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- module.exports = '16.7.0';
2
+ module.exports = '17.1.0';
package/modular/index.js CHANGED
@@ -176,6 +176,33 @@ export function getAPNSToken(messaging) {
176
176
  return messaging.getAPNSToken();
177
177
  }
178
178
 
179
+ /**
180
+ * On iOS, This method is used to set the APNs Token received by the application delegate.
181
+ * Note that the token is expected to be a hexadecimal string, as it is an NSData type in
182
+ * the underlying native firebase SDK, and raw data may only be passed as a string if it is
183
+ * hex encoded. Calling code is responsible for correct encoding, you should verify by comparing
184
+ * the results of `getAPNSToken()` with your token parameter to make sure they are equivalent
185
+ *
186
+ * Messaging uses method swizzling to ensure that the APNs token is set automatically.
187
+ * However, if you have disabled swizzling by setting FirebaseAppDelegateProxyEnabled to NO
188
+ * in your app’s Info.plist, you should manually set the APNs token in your application
189
+ * delegate’s application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method.
190
+ *
191
+ * If you would like to set the type of the APNs token, rather than relying on automatic
192
+ * detection, provide a type of either 'prod', 'sandbox'. Omitting the type parameter
193
+ * or specifying 'unknown' will rely on automatic type detection based on provisioning profile.
194
+ *
195
+ * At a native level you may also call objective-c `[FIRMessaging setAPNSToken];` as needed
196
+ *
197
+ * @param messaging Messaging instance.
198
+ * @param {string} token a hexadecimal string representing your APNS token
199
+ * @param {string?} type specifying 'prod', 'sandbox' or 'unknown' token type
200
+ * @returns {Promise<void>}
201
+ */
202
+ export function setAPNSToken(messaging, token, type) {
203
+ return messaging.setAPNSToken(token, type);
204
+ }
205
+
179
206
  /**
180
207
  * Returns a `AuthorizationStatus` as to whether the user has messaging permission for this app.
181
208
  * @param messaging Messaging instance.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-firebase/messaging",
3
- "version": "16.7.0",
3
+ "version": "17.1.0",
4
4
  "author": "Invertase <oss@invertase.io> (http://invertase.io)",
5
5
  "description": "React Native Firebase - React Native Firebase provides native integration of Firebase Cloud Messaging (FCM) for both Android & iOS. FCM is a cost free service, allowing for server-device and device-device communication. The React Native Firebase Messaging module provides a simple JavaScript API to interact with FCM.",
6
6
  "main": "lib/index.js",
@@ -22,10 +22,10 @@
22
22
  "messaging"
23
23
  ],
24
24
  "peerDependencies": {
25
- "@react-native-firebase/app": "16.7.0"
25
+ "@react-native-firebase/app": "17.1.0"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
- "gitHead": "a94f371da16f9bf873c18b09541cbeb19960978d"
30
+ "gitHead": "635d595389bfb224fc530681627fb2180fea6e26"
31
31
  }