Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5125CC982437F471006CA5D0"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5125CC982437F471006CA5D0"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-FIRDebugEnabled"
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5125CC982437F471006CA5D0"
BuildableName = "Sample.app"
BlueprintName = "Sample"
ReferencedContainer = "container:Sample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
2 changes: 0 additions & 2 deletions Example/Messaging/Sample/Sample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
// limitations under the License.

import UIKit
import CoreData
import FirebaseCore
import FirebaseMessaging

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
Expand Down
7 changes: 1 addition & 6 deletions Example/Messaging/Sample/Sample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import Combine
import SwiftUI
import FirebaseCore
import FirebaseMessaging
Expand Down Expand Up @@ -109,7 +110,6 @@ struct ContentView: View {
print("Failed delete token: ", error)
return
}
self.identity.token = nil
}
}

Expand All @@ -119,8 +119,6 @@ struct ContentView: View {
print("Failed delete ID: ", error)
return
}
self.identity.instanceID = nil
self.identity.token = nil
}
}

Expand All @@ -130,7 +128,6 @@ struct ContentView: View {
print("Failed delete FID: ", error)
return
}
self.identity.instanceID = nil
}
}
}
Expand Down Expand Up @@ -162,8 +159,6 @@ struct ContentView_Previews: PreviewProvider {

static var previews: some View {
Group {
ContentView().environmentObject(Identity())

ContentView().environmentObject(filledIdentity)
}
}
Expand Down
12 changes: 12 additions & 0 deletions Example/Messaging/Sample/Sample/Identity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,22 @@
// limitations under the License.

import SwiftUI
import FirebaseMessaging
import FirebaseInstallations

public final class Identity: ObservableObject {
// Identity that is unique per app.
@Published public var instanceID: String? = nil
// The token that Firebase Messaging use to send notifications.
@Published public var token: String? = nil

init() {
Installations.installations().installationID(completion: { fid, error in
if let error = error as NSError? {
print("Failed to get FID: ", error)
return
}
self.instanceID = fid ?? "None"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be nil if it doesn't exist, right? Otherwise consumers of this could think that an instanceID is available but the String is actually "None" which isn't valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Good catch!

})
}
}
28 changes: 21 additions & 7 deletions Example/Messaging/Sample/Sample/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MessagingDelegate {
options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView()
// Use a UIHostingController as window root view controller.
Messaging.messaging().delegate = self
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window
Expand All @@ -35,12 +34,27 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MessagingDelegate {
self.window = window
window.makeKeyAndVisible()
}
}

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
identity.token = fcmToken
InstanceID.instanceID().instanceID { result, error in
self.identity.instanceID = result?.instanceID
}
// Subscribe to token refresh
_ = NotificationCenter.default
.publisher(for: Notification.Name.MessagingRegistrationTokenRefreshed)
.map { $0.object as? String }
.receive(on: RunLoop.main)
.assign(to: \Identity.token, on: identity)
Comment on lines +39 to +43
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you'll need to store these AnyCancellable values returned somewhere, likely in a Set<AnyCancellable> otherwise the subscription will only last the lifetime of this code block.


// Subscribe to fid changes
_ = NotificationCenter.default
.publisher(for: Notification.Name.FIRInstallationIDDidChange)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh - looks like we need to change the API name here as well (shouldn't have a FIR prefix).

.map { _ in }
.receive(on: RunLoop.main)
.sink(receiveValue: {
Installations.installations().installationID(completion: { fid, error in
if let error = error as NSError? {
print("Failed to get FID: ", error)
return
}
self.identity.instanceID = fid ?? "None"
})
})
Comment on lines +51 to +58
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the notification not include information about the FID? If not we should look at adding it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}
33 changes: 13 additions & 20 deletions Firebase/InstanceID/FIRInstanceID.m
Original file line number Diff line number Diff line change
Expand Up @@ -245,19 +245,20 @@ - (NSString *)cachedTokenIfAvailable {
}

- (void)setDefaultFCMToken:(NSString *)defaultFCMToken {
if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) {
return;
// Sending this notification out will ensure that FIRMessaging and FIRInstanceID has the updated
// default FCM token.
// Only notify of token refresh if we have a new valid token that's different than before
if ((defaultFCMToken.length && _defaultFCMToken.length &&
![defaultFCMToken isEqualToString:_defaultFCMToken]) ||
defaultFCMToken.length != _defaultFCMToken.length) {
NSNotification *tokenRefreshNotification =
[NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification
object:[defaultFCMToken copy]];
[[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification
postingStyle:NSPostASAP];
}

_defaultFCMToken = defaultFCMToken;

// Sending this notification out will ensure that FIRMessaging has the updated
// default FCM token.
NSNotification *internalDefaultTokenNotification =
[NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification
object:_defaultFCMToken];
[[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification
postingStyle:NSPostASAP];
}

- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity
Expand Down Expand Up @@ -837,18 +838,10 @@ - (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHa
// Post the required notifications if somebody is waiting.
FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@",
token);
NSString *previousFCMToken = self.defaultFCMToken;
// Update default FCM token, this method also triggers sending notification if token has
// changed.
self.defaultFCMToken = token;

// Only notify of token refresh if we have a new valid token that's different than before
if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) {
NSNotification *tokenRefreshNotification =
[NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification
object:[self.defaultFCMToken copy]];
[[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification
postingStyle:NSPostASAP];
}

[self performDefaultTokenHandlerWithToken:token error:nil];
}
};
Expand Down
1 change: 0 additions & 1 deletion Firebase/InstanceID/FIRInstanceIDConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST;
/// Notification used to deliver GCM messages for InstanceID.
FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification;
FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification;
FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification;
FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification;

FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification;
Expand Down
1 change: 0 additions & 1 deletion Firebase/InstanceID/FIRInstanceIDConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
// NOTIFICATIONS
NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched";
NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token";
NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token";
NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification =
@"com.firebase.iid.notif.fcm-token-fail";

Expand Down
45 changes: 16 additions & 29 deletions Firebase/Messaging/FIRMessaging.m
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,6 @@ - (void)setupNotificationListeners {
// To prevent multiple notifications remove self as observer for all events.
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self];

[center addObserver:self
selector:@selector(didReceiveDefaultInstanceIDToken:)
name:kFIRMessagingFCMTokenNotification
object:nil];
[center addObserver:self
selector:@selector(defaultInstanceIDTokenWasRefreshed:)
name:kFIRMessagingRegistrationTokenRefreshNotification
Expand Down Expand Up @@ -664,6 +659,10 @@ - (void)notifyDelegateOfFCMTokenAvailability {
if ([self.delegate respondsToSelector:@selector(messaging:didReceiveRegistrationToken:)]) {
[self.delegate messaging:self didReceiveRegistrationToken:self.defaultFcmToken];
}
// Should always trigger the token refresh notification when the delegate method is called
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification
object:self.defaultFcmToken];
}

#pragma mark - Application State Changes
Expand Down Expand Up @@ -931,41 +930,29 @@ - (FIRMessagingNetworkStatus)networkType {

#pragma mark - Notifications

- (void)didReceiveDefaultInstanceIDToken:(NSNotification *)notification {
- (void)defaultInstanceIDTokenWasRefreshed:(NSNotification *)notification {
if (notification.object && ![notification.object isKindOfClass:[NSString class]]) {
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeMessaging015,
@"Invalid default FCM token type %@",
NSStringFromClass([notification.object class]));
return;
}
// Retrieve the Instance ID default token, and should notify delegate and
// trigger notification as long as the token is different from previous state.
NSString *oldToken = self.defaultFcmToken;
self.defaultFcmToken = [(NSString *)notification.object copy];
if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) {
NSString *token = [(NSString *)notification.object copy];
self.defaultFcmToken = [token copy];
if ((self.defaultFcmToken.length && oldToken.length &&
![self.defaultFcmToken isEqualToString:oldToken]) ||
self.defaultFcmToken.length != oldToken.length) {
[self notifyDelegateOfFCMTokenAvailability];
}
[self.pubsub scheduleSync:YES];
[self.pubsub scheduleSync:YES];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
if (self.shouldEstablishDirectChannel) {
[self updateAutomaticClientConnection];
}
#pragma clang diagnostic pop
}

- (void)defaultInstanceIDTokenWasRefreshed:(NSNotification *)notification {
// Retrieve the Instance ID default token, and if it is non-nil, post it
NSString *token = self.instanceID.token;
// Sometimes Instance ID doesn't yet have a token, so wait until the default
// 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];
if (self.defaultFcmToken && ![self.defaultFcmToken isEqualToString:oldToken]) {
[self notifyDelegateOfFCMTokenAvailability];
if (self.shouldEstablishDirectChannel) {
[self updateAutomaticClientConnection];
}
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center postNotificationName:FIRMessagingRegistrationTokenRefreshedNotification object:nil];
#pragma clang diagnostic pop
}
}

Expand Down
3 changes: 0 additions & 3 deletions Firebase/Messaging/FIRMessagingConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ FOUNDATION_EXPORT NSString *const kFIRMessagingSubDirectoryName;
// Notifications
FOUNDATION_EXPORT NSString *const kFIRMessagingCheckinFetchedNotification;
FOUNDATION_EXPORT NSString *const kFIRMessagingAPNSTokenNotification;
FOUNDATION_EXPORT NSString *const kFIRMessagingFCMTokenNotification;
FOUNDATION_EXPORT NSString *const kFIRMessagingInstanceIDTokenRefreshNotification
__deprecated_msg("Use kFIRMessagingRegistrationTokenRefreshNotification instead");
FOUNDATION_EXPORT NSString *const kFIRMessagingRegistrationTokenRefreshNotification;

FOUNDATION_EXPORT const int kFIRMessagingSendTtlDefault; // 24 hours
Expand Down
3 changes: 0 additions & 3 deletions Firebase/Messaging/FIRMessagingConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@
// Notifications
NSString *const kFIRMessagingCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched";
NSString *const kFIRMessagingAPNSTokenNotification = @"com.firebase.iid.notif.apns-token";
NSString *const kFIRMessagingFCMTokenNotification = @"com.firebase.iid.notif.fcm-token";
NSString *const kFIRMessagingInstanceIDTokenRefreshNotification =
@"com.firebase.iid.notif.refresh-token";
NSString *const kFIRMessagingRegistrationTokenRefreshNotification =
@"com.firebase.iid.notif.refresh-token";

Expand Down