aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Example/Messaging/App/iOS/AppDelegate.swift21
-rw-r--r--Firebase/Messaging/FIRMMessageCode.h1
-rw-r--r--Firebase/Messaging/FIRMessaging.m76
-rw-r--r--Firebase/Messaging/Public/FIRMessaging.h40
4 files changed, 99 insertions, 39 deletions
diff --git a/Example/Messaging/App/iOS/AppDelegate.swift b/Example/Messaging/App/iOS/AppDelegate.swift
index aafd844..32b55ed 100644
--- a/Example/Messaging/App/iOS/AppDelegate.swift
+++ b/Example/Messaging/App/iOS/AppDelegate.swift
@@ -66,19 +66,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// register for remote notifications
NotificationsController.shared.registerForUserFacingNotificationsFor(application)
}
-
- printFCMToken()
return true
}
- func printFCMToken() {
- if let token = Messaging.messaging().fcmToken {
- print("FCM Token: \(token)")
- } else {
- print("FCM Token: nil")
- }
- }
-
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("APNS Token: \(deviceToken.hexByteString)")
@@ -116,8 +106,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
extension AppDelegate: MessagingDelegate {
- func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
- printFCMToken()
+ // FCM tokens are always provided here. It is called generally during app start, but may be called
+ // more than once, if the token is invalidated or updated. This is the right spot to upload this
+ // token to your application server, or to subscribe to any topics.
+ func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
+ if let token = Messaging.messaging().fcmToken {
+ print("FCM Token: \(token)")
+ } else {
+ print("FCM Token: nil")
+ }
}
// Direct channel data messages are delivered here, on iOS 10.0+.
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.