aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Messaging
diff options
context:
space:
mode:
authorGravatar Riz <rsattar@gmail.com>2017-10-12 16:09:07 -0700
committerGravatar GitHub <noreply@github.com>2017-10-12 16:09:07 -0700
commit2b40693be4c9aa2c94b668fb144c6993f557b8d6 (patch)
treecb1462b6df4132e67a665331def8f4fc9cd78edc /Firebase/Messaging
parent230c78b5ed7ea80f7ff9aa67c6b12a2794c08718 (diff)
Add simpler delegate method for FCM tokens (#375)
This new delegate method will be called generally once per app start, to always provide a current token. This token may change over time. This simpler method makes integration much simpler, as: * Developers no longer have to check for a current token using the `.fcmToken` property, and also check for token changes using the `-messaging:didRefreshRegistrationToken:` delegate method. * There is a single code path for when a token is available, making operations that depend on a token being available easier to implement. For example, this is the right method to always upload your FCM token to your application server, or to subscribe to topics, etc.
Diffstat (limited to 'Firebase/Messaging')
-rw-r--r--Firebase/Messaging/FIRMMessageCode.h1
-rw-r--r--Firebase/Messaging/FIRMessaging.m76
-rw-r--r--Firebase/Messaging/Public/FIRMessaging.h40
3 files changed, 90 insertions, 27 deletions
diff --git a/Firebase/Messaging/FIRMMessageCode.h b/Firebase/Messaging/FIRMMessageCode.h
index 46505ec..2b6ddad 100644
--- a/Firebase/Messaging/FIRMMessageCode.h
+++ b/Firebase/Messaging/FIRMMessageCode.h
@@ -44,6 +44,7 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenFetch = 2020, // I-FCM002020
kFIRMessagingMessageCodeSenderIDNotSuppliedForTokenDelete = 2021, // I-FCM002021
kFIRMessagingMessageCodeAPNSTokenNotAvailableDuringTokenFetch = 2022, // I-FCM002022
+ kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented = 2023, // I-FCM002023
// FIRMessagingClient.m
kFIRMessagingMessageCodeClient000 = 4000, // I-FCM004000
kFIRMessagingMessageCodeClient001 = 4001, // I-FCM004001
diff --git a/Firebase/Messaging/FIRMessaging.m b/Firebase/Messaging/FIRMessaging.m
index 9d10741..1c31961 100644
--- a/Firebase/Messaging/FIRMessaging.m
+++ b/Firebase/Messaging/FIRMessaging.m
@@ -507,6 +507,42 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
handler:completion];
}
+#pragma mark - FIRMessagingDelegate helper methods
+- (void)setDelegate:(id<FIRMessagingDelegate>)delegate {
+ _delegate = delegate;
+ [self validateDelegateConformsToTokenAvailabilityMethods];
+}
+
+// Check if the delegate conforms to either |didReceiveRegistrationToken:| or
+// |didRefreshRegistrationToken:|, and display a warning to the developer if not.
+// NOTE: Once |didReceiveRegistrationToken:| can be made a required method, this
+// check can be removed.
+- (void)validateDelegateConformsToTokenAvailabilityMethods {
+ if (self.delegate &&
+ ![self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)] &&
+ ![self.delegate respondsToSelector:@selector(messaging:didRefreshRegistrationToken:)]) {
+ FIRMessagingLoggerWarn(kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented,
+ @"The object %@ does not respond to "
+ @"-messaging:didReceiveRegistrationToken:, nor "
+ @"-messaging:didRefreshRegistrationToken:. Please implement "
+ @"-messaging:didReceiveRegistrationToken: to be provided with an FCM "
+ @"token.", self.delegate.description);
+ }
+}
+
+- (void)notifyDelegateOfFCMTokenAvailability {
+ __weak FIRMessaging *weakSelf = self;
+ if (![NSThread isMainThread]) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [weakSelf notifyDelegateOfFCMTokenAvailability];
+ });
+ return;
+ }
+ if ([self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) {
+ [self.delegate messaging:self didReceiveRegistrationToken:self.defaultFcmToken];
+ }
+}
+
#pragma mark - Application State Changes
- (void)applicationStateChanged {
@@ -719,6 +755,17 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
#pragma mark - Network
+- (void)onNetworkStatusChanged {
+ if (![self.client isConnected] && [self isNetworkAvailable]) {
+ if (self.client.shouldStayConnected) {
+ FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging014,
+ @"Attempting to establish direct channel.");
+ [self.client retryConnectionImmediately:YES];
+ }
+ [self.pubsub scheduleSync:YES];
+ }
+}
+
- (BOOL)isNetworkAvailable {
FIRReachabilityStatus status = self.reachability.reachabilityStatus;
return (status == kFIRReachabilityViaCellular || status == kFIRReachabilityViaWifi);
@@ -737,19 +784,6 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
#pragma mark - Notifications
-- (void)onNetworkStatusChanged {
- if (![self.client isConnected] && [self isNetworkAvailable]) {
- if (self.client.shouldStayConnected) {
- FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging014,
- @"Attempting to establish direct channel.");
- [self.client retryConnectionImmediately:YES];
- }
- [self.pubsub scheduleSync:YES];
- }
-}
-
-#pragma mark - Notifications
-
- (void)didReceiveDefaultInstanceIDToken:(NSNotification *)notification {
if (![notification.object isKindOfClass:[NSString class]]) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging015,
@@ -757,7 +791,11 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
NSStringFromClass([notification.object class]));
return;
}
+ NSString *oldToken = self.defaultFcmToken;
self.defaultFcmToken = [(NSString *)notification.object copy];
+ if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) {
+ [self notifyDelegateOfFCMTokenAvailability];
+ }
[self.pubsub scheduleSync:YES];
if (self.shouldEstablishDirectChannel) {
[self updateAutomaticClientConnection];
@@ -771,8 +809,18 @@ NSString * const FIRMessagingRegistrationTokenRefreshedNotification =
// token is fetched, and then notify. This ensures that this token should not
// be nil when the developer accesses it.
if (token != nil) {
+ NSString *oldToken = self.defaultFcmToken;
self.defaultFcmToken = [token copy];
- [self.delegate messaging:self didRefreshRegistrationToken:token];
+ if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) {
+ [self notifyDelegateOfFCMTokenAvailability];
+ }
+ // Call deprecated refresh method, because it should still work (until it is removed).
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ if ([self.delegate respondsToSelector:@selector(messaging:didRefreshRegistrationToken:)]) {
+ [self.delegate messaging:self didRefreshRegistrationToken:token];
+ }
+#pragma clang diagnostic pop
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification object:nil];
}
diff --git a/Firebase/Messaging/Public/FIRMessaging.h b/Firebase/Messaging/Public/FIRMessaging.h
index 7313f23..65a9d06 100644
--- a/Firebase/Messaging/Public/FIRMessaging.h
+++ b/Firebase/Messaging/Public/FIRMessaging.h
@@ -111,9 +111,9 @@ FOUNDATION_EXPORT const NSNotificationName __nonnull FIRMessagingConnectionState
FIR_SWIFT_NAME(MessagingConnectionStateChanged);
/**
- * Notification sent when the FCM registration token has been refreshed. You can also
- * receive the FCM token via the FIRMessagingDelegate method
- * `-messaging:didRefreshRegistrationToken:`
+ * Notification sent when the FCM registration token has been refreshed. Please use the
+ * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and
+ * updated tokens.
*/
FOUNDATION_EXPORT const NSNotificationName __nonnull
FIRMessagingRegistrationTokenRefreshedNotification
@@ -156,9 +156,9 @@ FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingConnectionStateChangedN
FIR_SWIFT_NAME(MessagingConnectionStateChangedNotification);
/**
- * Notification sent when the FCM registration token has been refreshed. You can also
- * receive the FCM token via the FIRMessagingDelegate method
- * `-messaging:didRefreshRegistrationToken:`
+ * Notification sent when the FCM registration token has been refreshed. Please use the
+ * FIRMessaging delegate method `messaging:didReceiveRegistrationToken:` to receive current and
+ * updated tokens.
*/
FOUNDATION_EXPORT NSString * __nonnull const FIRMessagingRegistrationTokenRefreshedNotification
FIR_SWIFT_NAME(MessagingRegistrationTokenRefreshedNotification);
@@ -246,14 +246,27 @@ FIR_SWIFT_NAME(MessagingRemoteMessage)
FIR_SWIFT_NAME(MessagingDelegate)
@protocol FIRMessagingDelegate <NSObject>
+@optional
+/// This method will be called once a token is available, or has been refreshed. Typically it
+/// will be called once per app start, but may be called more often, if token is invalidated or
+/// updated. In this method, you should perform operations such as:
+///
+/// * Uploading the FCM token to your application server, so targeted notifications can be sent.
+///
+/// * Subscribing to any topics.
+- (void)messaging:(nonnull FIRMessaging *)messaging
+ didReceiveRegistrationToken:(nonnull NSString *)fcmToken
+ FIR_SWIFT_NAME(messaging(_:didReceiveRegistrationToken:));
+
/// This method will be called whenever FCM receives a new, default FCM token for your
-/// Firebase project's Sender ID.
-/// You can send this token to your application server to send notifications to this device.
+/// Firebase project's Sender ID. This method is deprecated. Please use
+/// `messaging:didReceiveRegistrationToken:`.
- (void)messaging:(nonnull FIRMessaging *)messaging
didRefreshRegistrationToken:(nonnull NSString *)fcmToken
- FIR_SWIFT_NAME(messaging(_:didRefreshRegistrationToken:));
+ FIR_SWIFT_NAME(messaging(_:didRefreshRegistrationToken:))
+ __deprecated_msg("Please use messaging:didReceiveRegistrationToken:, which is called for both \
+ current and refreshed tokens.");
-@optional
/// This method is called on iOS 10 devices to handle data messages received via FCM through its
/// direct channel (not via APNS). For iOS 9 and below, the FCM data message is delivered via the
/// UIApplicationDelegate's -application:didReceiveRemoteNotification: method.
@@ -356,9 +369,10 @@ FIR_SWIFT_NAME(Messaging)
* It is associated with your APNS token when the APNS token is supplied, so that sending
* messages to the FCM token will be delivered over APNS.
*
- * The FCM token is sometimes refreshed automatically. You can be notified of these changes
- * via the FIRMessagingDelegate method `-message:didRefreshRegistrationToken:`, or by
- * listening for the `FIRMessagingRegistrationTokenRefreshedNotification` notification.
+ * The FCM token is sometimes refreshed automatically. In your FIRMessaging delegate, the
+ * delegate method `messaging:didReceiveRegistrationToken:` will be called once a token is
+ * available, or has been refreshed. Typically it should be called once per app start, but
+ * may be called more often, if token is invalidated or updated.
*
* Once you have an FCM token, you should send it to your application server, so it can use
* the FCM token to send notifications to your device.