Skip to content

Commit 2e02813

Browse files
Fix topic in watchOS (#6209)
1 parent e131a19 commit 2e02813

13 files changed

Lines changed: 93 additions & 282 deletions

Example/watchOSSample/SampleWatchAppWatchKitExtension/ExtensionDelegate.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,19 @@ class ExtensionDelegate: NSObject, WKExtensionDelegate, MessagingDelegate {
3434
/// MessagingDelegate
3535
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
3636
print("token:\n" + fcmToken)
37+
Messaging.messaging().subscribe(toTopic: "watch") { error in
38+
if error != nil {
39+
print("error:" + error.debugDescription)
40+
} else {
41+
print("Successfully subscribed to topic")
42+
}
43+
}
3744
}
3845

3946
/// WKExtensionDelegate
4047
func didRegisterForRemoteNotifications(withDeviceToken deviceToken: Data) {
4148
/// Swizzling should be disabled in Messaging for watchOS, set APNS token manually.
49+
print("Set APNS Token\n")
4250
Messaging.messaging().apnsToken = deviceToken
4351
}
4452
}

FirebaseMessaging/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# unreleased
2+
- [fixed] Fixed an issue that topic doesn't work in watchOS. (#6160)
3+
14
# 2020-07 -- v4.6.1
25
- [changed] Remove logic that is executed for iOS 7 and below. (#5835)
36

FirebaseMessaging/Sources/FIRMMessageCode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ typedef NS_ENUM(NSInteger, FIRMessagingMessageCode) {
4747
kFIRMessagingMessageCodeTokenDelegateMethodsNotImplemented = 2023, // I-FCM002023
4848
kFIRMessagingMessageCodeTopicFormatIsDeprecated = 2024,
4949
kFIRMessagingMessageCodeDirectChannelConnectionFailed = 2025,
50-
kFIRMessagingMessageCodeInvalidClient = 2026,
50+
kFIRMessagingMessageCodeInvalidClient = 2026, // no longer used
5151
// FIRMessagingClient.m
5252
kFIRMessagingMessageCodeClient000 = 4000, // I-FCM004000
5353
kFIRMessagingMessageCodeClient001 = 4001, // I-FCM004001

FirebaseMessaging/Sources/FIRMessaging.m

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ - (void)configureNotificationSwizzlingIfEnabled {
269269
- (void)start {
270270
[self setupFileManagerSubDirectory];
271271
[self setupNotificationListeners];
272+
[self setupTopics];
272273

273274
#if !TARGET_OS_WATCH
274275
// Print the library version for logging.
@@ -288,7 +289,6 @@ - (void)start {
288289
[self setupClient];
289290
[self setupSyncMessageManager];
290291
[self setupDataMessageManager];
291-
[self setupTopics];
292292

293293
#endif
294294
}
@@ -347,11 +347,7 @@ - (void)setupRmqManager {
347347
}
348348

349349
- (void)setupTopics {
350-
if (!self.client) {
351-
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeInvalidClient,
352-
@"Invalid nil client before init pubsub.");
353-
}
354-
self.pubsub = [[FIRMessagingPubSub alloc] initWithClient:self.client];
350+
self.pubsub = [[FIRMessagingPubSub alloc] init];
355351
}
356352

357353
- (void)setupSyncMessageManager {

FirebaseMessaging/Sources/FIRMessagingClient.h

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -53,39 +53,6 @@ typedef void (^FIRMessagingConnectCompletionHandler)(NSError *error);
5353

5454
- (void)teardown;
5555

56-
- (void)cancelAllRequests;
57-
58-
#pragma mark - FIRMessaging subscribe
59-
60-
/**
61-
* Update the subscription associated with the given token and topic.
62-
*
63-
* For a to-be-created subscription we check if the client is already
64-
* subscribed to the topic or not. If subscribed we should have the
65-
* subscriptionID in the cache and we return from there itself, else we call
66-
* the FIRMessaging backend to create a new subscription for the topic for this client.
67-
*
68-
* For delete subscription requests we delete the stored subscription in the
69-
* client and then invoke the FIRMessaging backend to delete the existing subscription
70-
* completely.
71-
*
72-
* @param token The token associated with the device.
73-
* @param topic The topic for which the subscription should be updated.
74-
* @param options The options to be passed in to the subscription request.
75-
* @param shouldDelete If YES this would delete the subscription from the cache
76-
* and also let the FIRMessaging backend know that we need to delete
77-
* the subscriptionID associated with this topic.
78-
* If NO we try to create a new subscription for the given
79-
* token and topic.
80-
* @param handler The handler to invoke once the subscription request
81-
* finishes.
82-
*/
83-
- (void)updateSubscriptionWithToken:(NSString *)token
84-
topic:(NSString *)topic
85-
options:(NSDictionary *)options
86-
shouldDelete:(BOOL)shouldDelete
87-
handler:(FIRMessagingTopicOperationCompletion)handler;
88-
8956
#pragma mark - MCS Connection
9057

9158
/**

FirebaseMessaging/Sources/FIRMessagingClient.m

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#import "FirebaseMessaging/Sources/FIRMessagingDataMessageManager.h"
2828
#import "FirebaseMessaging/Sources/FIRMessagingDefines.h"
2929
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
30-
#import "FirebaseMessaging/Sources/FIRMessagingPubSubRegistrar.h"
3130
#import "FirebaseMessaging/Sources/FIRMessagingRmqManager.h"
3231
#import "FirebaseMessaging/Sources/FIRMessagingTopicsCommon.h"
3332
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
@@ -79,7 +78,6 @@ @interface FIRMessagingClient () <FIRMessagingConnectionDelegate>
7978

8079
@property(nonatomic, readwrite, weak) id<FIRMessagingClientDelegate> clientDelegate;
8180
@property(nonatomic, readwrite, strong) FIRMessagingConnection *connection;
82-
@property(nonatomic, readonly, strong) FIRMessagingPubSubRegistrar *registrar;
8381
@property(nonatomic, readwrite, strong) NSString *senderId;
8482

8583
// FIRMessagingService owns these instances
@@ -120,7 +118,6 @@ - (instancetype)initWithDelegate:(id<FIRMessagingClientDelegate>)delegate
120118
_reachability = reachability;
121119
_clientDelegate = delegate;
122120
_rmq2Manager = rmq2Manager;
123-
_registrar = [[FIRMessagingPubSubRegistrar alloc] init];
124121
_connectionTimeoutInterval = kConnectTimeoutInterval;
125122
// Listen for checkin fetch notifications, as connecting to MCS may have failed due to
126123
// missing checkin info (while it was being fetched).
@@ -144,66 +141,11 @@ - (void)teardown {
144141

145142
[self.connection teardown];
146143

147-
// Stop all subscription requests
148-
[self.registrar stopAllSubscriptionRequests];
149-
150144
[NSObject cancelPreviousPerformRequestsWithTarget:self];
151145

152146
[[NSNotificationCenter defaultCenter] removeObserver:self];
153147
}
154148

155-
- (void)cancelAllRequests {
156-
// Stop any checkin requests or any subscription requests
157-
[self.registrar stopAllSubscriptionRequests];
158-
159-
// Stop any future connection requests to MCS
160-
if (self.stayConnected && self.isConnected && !self.isConnectionActive) {
161-
self.stayConnected = NO;
162-
[NSObject cancelPreviousPerformRequestsWithTarget:self];
163-
}
164-
}
165-
166-
#pragma mark - FIRMessaging subscribe
167-
168-
- (void)updateSubscriptionWithToken:(NSString *)token
169-
topic:(NSString *)topic
170-
options:(NSDictionary *)options
171-
shouldDelete:(BOOL)shouldDelete
172-
handler:(FIRMessagingTopicOperationCompletion)handler {
173-
FIRMessagingTopicOperationCompletion completion = ^void(NSError *error) {
174-
if (error) {
175-
FIRMessagingLoggerError(kFIRMessagingMessageCodeClient001, @"Failed to subscribe to topic %@",
176-
error);
177-
} else {
178-
if (shouldDelete) {
179-
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient002,
180-
@"Successfully unsubscribed from topic %@", topic);
181-
} else {
182-
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient003,
183-
@"Successfully subscribed to topic %@", topic);
184-
}
185-
}
186-
if (handler) {
187-
handler(error);
188-
}
189-
};
190-
191-
if ([[FIRInstanceID instanceID] tryToLoadValidCheckinInfo]) {
192-
[self.registrar updateSubscriptionToTopic:topic
193-
withToken:token
194-
options:options
195-
shouldDelete:shouldDelete
196-
handler:completion];
197-
} else {
198-
NSString *failureReason = @"Device ID and checkin info is not found. Will not proceed with "
199-
@"subscription/unsubscription.";
200-
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRegistrar000, @"%@", failureReason);
201-
NSError *error = [NSError messagingErrorWithCode:kFIRMessagingErrorCodeMissingDeviceID
202-
failureReason:failureReason];
203-
handler(error);
204-
}
205-
}
206-
207149
#pragma mark - MCS Connection
208150

209151
- (BOOL)isConnected {

FirebaseMessaging/Sources/FIRMessagingPubSub.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
NS_ASSUME_NONNULL_BEGIN
2020

21-
@class FIRMessagingClient;
2221
@class FIRMessagingPubSubCache;
2322

2423
/**
@@ -39,14 +38,6 @@ NS_ASSUME_NONNULL_BEGIN
3938
@interface FIRMessagingPubSub : NSObject
4039

4140
@property(nonatomic, readonly, strong) FIRMessagingPubSubCache *cache;
42-
@property(nonatomic, readonly, strong) FIRMessagingClient *client;
43-
44-
/**
45-
* Initializes an instance of FIRMessagingPubSub.
46-
*
47-
* @return An instance of FIRMessagingPubSub.
48-
*/
49-
- (instancetype)initWithClient:(FIRMessagingClient *)client NS_DESIGNATED_INITIALIZER;
5041

5142
/**
5243
* Subscribes an app instance to a topic, enabling it to receive messages

FirebaseMessaging/Sources/FIRMessagingPubSub.m

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#import "FirebaseMessaging/Sources/FIRMessagingPubSub.h"
1818

19+
#import <FirebaseInstanceID/FIRInstanceID_Private.h>
1920
#import <FirebaseMessaging/FIRMessaging.h>
2021
#import "GoogleUtilities/Environment/Private/GULSecureCoding.h"
2122
#import "GoogleUtilities/UserDefaults/Private/GULUserDefaults.h"
@@ -24,6 +25,8 @@
2425
#import "FirebaseMessaging/Sources/FIRMessagingDefines.h"
2526
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
2627
#import "FirebaseMessaging/Sources/FIRMessagingPendingTopicsList.h"
28+
#import "FirebaseMessaging/Sources/FIRMessagingTopicOperation.h"
29+
#import "FirebaseMessaging/Sources/FIRMessagingTopicsCommon.h"
2730
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
2831
#import "FirebaseMessaging/Sources/FIRMessaging_Private.h"
2932
#import "FirebaseMessaging/Sources/NSDictionary+FIRMessaging.h"
@@ -35,22 +38,21 @@
3538
@interface FIRMessagingPubSub () <FIRMessagingPendingTopicsListDelegate>
3639

3740
@property(nonatomic, readwrite, strong) FIRMessagingPendingTopicsList *pendingTopicUpdates;
38-
@property(nonatomic, readwrite, strong) FIRMessagingClient *client;
41+
@property(nonatomic, readonly, strong) NSOperationQueue *topicOperations;
42+
// Common errors, instantiated, to avoid generating multiple copies
43+
@property(nonatomic, readwrite, strong) NSError *operationInProgressError;
3944

4045
@end
4146

4247
@implementation FIRMessagingPubSub
4348

4449
- (instancetype)init {
45-
FIRMessagingInvalidateInitializer();
46-
// Need this to disable an Xcode warning.
47-
return [self initWithClient:nil];
48-
}
49-
50-
- (instancetype)initWithClient:(FIRMessagingClient *)client {
5150
self = [super init];
5251
if (self) {
53-
_client = client;
52+
_topicOperations = [[NSOperationQueue alloc] init];
53+
// Do 10 topic operations at a time; it's enough to keep the TCP connection to the host alive,
54+
// saving hundreds of milliseconds on each request (compared to a serial queue).
55+
_topicOperations.maxConcurrentOperationCount = 10;
5456
[self restorePendingTopicsList];
5557
}
5658
return self;
@@ -60,14 +62,6 @@ - (void)subscribeWithToken:(NSString *)token
6062
topic:(NSString *)topic
6163
options:(NSDictionary *)options
6264
handler:(FIRMessagingTopicOperationCompletion)handler {
63-
if (!self.client) {
64-
handler([NSError
65-
messagingErrorWithCode:kFIRMessagingErrorCodePubSubClientNotSetup
66-
failureReason:@"Firebase Messaging Client does not exist. Firebase Messaging was "
67-
@"not setup property and subscription failed."]);
68-
return;
69-
}
70-
7165
token = [token copy];
7266
topic = [topic copy];
7367

@@ -93,26 +87,64 @@ - (void)subscribeWithToken:(NSString *)token
9387
// copy the dictionary would trim non-string keys or values if any.
9488
options = [options fcm_trimNonStringValues];
9589

96-
[self.client updateSubscriptionWithToken:token
97-
topic:topic
98-
options:options
99-
shouldDelete:NO
100-
handler:^void(NSError *error) {
101-
handler(error);
102-
}];
90+
[self updateSubscriptionWithToken:token
91+
topic:topic
92+
options:options
93+
shouldDelete:NO
94+
handler:handler];
95+
}
96+
97+
- (void)dealloc {
98+
[self.topicOperations cancelAllOperations];
99+
}
100+
101+
#pragma mark - FIRMessaging subscribe
102+
103+
- (void)updateSubscriptionWithToken:(NSString *)token
104+
topic:(NSString *)topic
105+
options:(NSDictionary *)options
106+
shouldDelete:(BOOL)shouldDelete
107+
handler:(FIRMessagingTopicOperationCompletion)handler {
108+
if ([[FIRInstanceID instanceID] tryToLoadValidCheckinInfo]) {
109+
FIRMessagingTopicAction action =
110+
shouldDelete ? FIRMessagingTopicActionUnsubscribe : FIRMessagingTopicActionSubscribe;
111+
FIRMessagingTopicOperation *operation = [[FIRMessagingTopicOperation alloc]
112+
initWithTopic:topic
113+
action:action
114+
token:token
115+
options:options
116+
completion:^(NSError *_Nullable error) {
117+
if (error) {
118+
FIRMessagingLoggerError(kFIRMessagingMessageCodeClient001,
119+
@"Failed to subscribe to topic %@", error);
120+
} else {
121+
if (shouldDelete) {
122+
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient002,
123+
@"Successfully unsubscribed from topic %@", topic);
124+
} else {
125+
FIRMessagingLoggerInfo(kFIRMessagingMessageCodeClient003,
126+
@"Successfully subscribed to topic %@", topic);
127+
}
128+
}
129+
if (handler) {
130+
handler(error);
131+
}
132+
}];
133+
[self.topicOperations addOperation:operation];
134+
} else {
135+
NSString *failureReason = @"Device ID and checkin info is not found. Will not proceed with "
136+
@"subscription/unsubscription.";
137+
FIRMessagingLoggerDebug(kFIRMessagingMessageCodeRegistrar000, @"%@", failureReason);
138+
NSError *error = [NSError messagingErrorWithCode:kFIRMessagingErrorCodeMissingDeviceID
139+
failureReason:failureReason];
140+
handler(error);
141+
}
103142
}
104143

105144
- (void)unsubscribeWithToken:(NSString *)token
106145
topic:(NSString *)topic
107146
options:(NSDictionary *)options
108147
handler:(FIRMessagingTopicOperationCompletion)handler {
109-
if (!self.client) {
110-
handler([NSError
111-
messagingErrorWithCode:kFIRMessagingErrorCodePubSubClientNotSetup
112-
failureReason:@"Firebase Messaging Client does not exist. Firebase Messaging was "
113-
@"not setup property and subscription failed."]);
114-
return;
115-
}
116148
token = [token copy];
117149
topic = [topic copy];
118150
if (![options count]) {
@@ -136,13 +168,13 @@ - (void)unsubscribeWithToken:(NSString *)token
136168
// copy the dictionary would trim non-string keys or values if any.
137169
options = [options fcm_trimNonStringValues];
138170

139-
[self.client updateSubscriptionWithToken:token
140-
topic:topic
141-
options:options
142-
shouldDelete:YES
143-
handler:^void(NSError *error) {
144-
handler(error);
145-
}];
171+
[self updateSubscriptionWithToken:token
172+
topic:topic
173+
options:options
174+
shouldDelete:YES
175+
handler:^void(NSError *error) {
176+
handler(error);
177+
}];
146178
}
147179

148180
- (void)subscribeToTopic:(NSString *)topic

0 commit comments

Comments
 (0)