فهرست منبع

Ensure sound is assigned with right type (#8203)

Chen Liang 4 سال پیش
والد
کامیت
62538d7f99

+ 3 - 0
FirebaseMessaging/CHANGELOG.md

@@ -1,3 +1,6 @@
+# 2021-06 -- v8.2.0
+- [fixed] Fixed an issue that local scheduled notification is not set correctly due to sound type. (#8172)
+
 # 2021-05 -- v8.1.0
 - [fixed] Fixed an issue that notification open is not logged to Analytics correctly when app is completely shut off. (#7707, #8128).
 

+ 62 - 49
FirebaseMessaging/Sources/FIRMessagingContextManagerService.m

@@ -136,62 +136,75 @@ typedef NS_ENUM(NSUInteger, FIRMessagingContextManagerMessageType) {
   return YES;
 }
 
-+ (void)scheduleiOS10LocalNotificationForMessage:(NSDictionary *)message atDate:(NSDate *)date {
++ (void)scheduleiOS10LocalNotificationForMessage:(NSDictionary *)message
+                                          atDate:(NSDate *)date
+    API_AVAILABLE(macosx(10.14), ios(10.0), watchos(3.0), tvos(10.0)) {
   NSCalendar *calendar = [NSCalendar currentCalendar];
-  if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
-    NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |
-                          NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
-    NSDateComponents *dateComponents = [calendar components:(NSCalendarUnit)unit fromDate:date];
-    UNCalendarNotificationTrigger *trigger =
-        [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
-
-    UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
-    NSDictionary *apsDictionary = message;
-
-    // Badge is universal
-    if (apsDictionary[kFIRMessagingContextManagerBadgeKey]) {
-      content.badge = apsDictionary[kFIRMessagingContextManagerBadgeKey];
-    }
+  NSCalendarUnit unit = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |
+                        NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
+  NSDateComponents *dateComponents = [calendar components:(NSCalendarUnit)unit fromDate:date];
+  UNCalendarNotificationTrigger *trigger =
+      [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
+
+  UNMutableNotificationContent *content = [self contentFromContextualMessage:message];
+  NSString *identifier = message[kFIRMessagingID];
+  if (!identifier) {
+    identifier = [NSUUID UUID].UUIDString;
+  }
+
+  UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
+                                                                        content:content
+                                                                        trigger:trigger];
+  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
+  [center
+      addNotificationRequest:request
+       withCompletionHandler:^(NSError *_Nullable error) {
+         if (error) {
+           FIRMessagingLoggerError(kFIRMessagingMessageCodeContextManagerServiceFailedLocalSchedule,
+                                   @"Failed scheduling local timezone notification: %@.", error);
+         }
+       }];
+}
+
++ (UNMutableNotificationContent *)contentFromContextualMessage:(NSDictionary *)message
+    API_AVAILABLE(macosx(10.14), ios(10.0), watchos(3.0), tvos(10.0)) {
+  UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
+  NSDictionary *apsDictionary = message;
+
+  // Badge is universal
+  if (apsDictionary[kFIRMessagingContextManagerBadgeKey]) {
+    content.badge = apsDictionary[kFIRMessagingContextManagerBadgeKey];
+  }
 #if TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
-    // The following fields are not available on tvOS
-    if ([apsDictionary[kFIRMessagingContextManagerBodyKey] length]) {
-      content.body = apsDictionary[kFIRMessagingContextManagerBodyKey];
-    }
-    if ([apsDictionary[kFIRMessagingContextManagerTitleKey] length]) {
-      content.title = apsDictionary[kFIRMessagingContextManagerTitleKey];
-    }
+  // The following fields are not available on tvOS
+  if ([apsDictionary[kFIRMessagingContextManagerBodyKey] length]) {
+    content.body = apsDictionary[kFIRMessagingContextManagerBodyKey];
+  }
 
-    if (apsDictionary[kFIRMessagingContextManagerSoundKey]) {
-      content.sound = apsDictionary[kFIRMessagingContextManagerSoundKey];
-    }
+  if ([apsDictionary[kFIRMessagingContextManagerTitleKey] length]) {
+    content.title = apsDictionary[kFIRMessagingContextManagerTitleKey];
+  }
 
-    if (apsDictionary[kFIRMessagingContextManagerCategoryKey]) {
-      content.categoryIdentifier = apsDictionary[kFIRMessagingContextManagerCategoryKey];
-    }
+  if (apsDictionary[kFIRMessagingContextManagerSoundKey]) {
+#if !TARGET_OS_WATCH
+    // UNNotificationSound soundNamded: is not available in watchOS
+    content.sound =
+        [UNNotificationSound soundNamed:apsDictionary[kFIRMessagingContextManagerSoundKey]];
+#else   // !TARGET_OS_WATCH
+    content.sound = [UNNotificationSound defaultSound];
+#endif  // !TARGET_OS_WATCH
+  }
 
-    NSDictionary *userInfo = [self parseDataFromMessage:message];
-    if (userInfo.count) {
-      content.userInfo = userInfo;
-    }
-#endif
-    NSString *identifier = apsDictionary[kFIRMessagingID];
-    if (!identifier) {
-      identifier = [NSUUID UUID].UUIDString;
-    }
+  if (apsDictionary[kFIRMessagingContextManagerCategoryKey]) {
+    content.categoryIdentifier = apsDictionary[kFIRMessagingContextManagerCategoryKey];
+  }
 
-    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
-                                                                          content:content
-                                                                          trigger:trigger];
-    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
-    [center addNotificationRequest:request
-             withCompletionHandler:^(NSError *_Nullable error) {
-               if (error) {
-                 FIRMessagingLoggerError(
-                     kFIRMessagingMessageCodeContextManagerServiceFailedLocalSchedule,
-                     @"Failed scheduling local timezone notification: %@.", error);
-               }
-             }];
+  NSDictionary *userInfo = [self parseDataFromMessage:message];
+  if (userInfo.count) {
+    content.userInfo = userInfo;
   }
+#endif  // TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
+  return content;
 }
 
 + (void)scheduleLocalNotificationForMessage:(NSDictionary *)message atDate:(NSDate *)date {

+ 89 - 0
FirebaseMessaging/Tests/UnitTests/FIRMessagingContextManagerServiceTest.m

@@ -24,6 +24,9 @@
 #import "FirebaseMessaging/Sources/FIRMessagingContextManagerService.h"
 
 static NSString *const kBody = @"Save 20% off!";
+static NSString *const kTitle = @"Sparky WFH";
+static NSString *const kSoundName = @"default";
+static NSString *const kAction = @"open";
 static NSString *const kUserInfoKey1 = @"level";
 static NSString *const kUserInfoKey2 = @"isPayUser";
 static NSString *const kUserInfoValue1 = @"5";
@@ -31,6 +34,11 @@ static NSString *const kUserInfoValue2 = @"Yes";
 static NSString *const kMessageIdentifierKey = @"gcm.message_id";
 static NSString *const kMessageIdentifierValue = @"1584748495200141";
 
+@interface FIRMessagingContextManagerService (ExposedForTest)
++ (void)scheduleiOS10LocalNotificationForMessage:(NSDictionary *)message atDate:(NSDate *)date;
++ (UNMutableNotificationContent *)contentFromContextualMessage:(NSDictionary *)message;
+@end
+
 API_AVAILABLE(macos(10.14))
 @interface FIRMessagingContextManagerServiceTest : XCTestCase
 
@@ -269,4 +277,85 @@ API_AVAILABLE(macos(10.14))
 #endif
 }
 
+- (void)testScheduleiOS10LocalNotification {
+  if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
+    id mockContextManagerService = OCMClassMock([FIRMessagingContextManagerService class]);
+    NSDictionary *message = @{};
+
+    [FIRMessagingContextManagerService scheduleiOS10LocalNotificationForMessage:message
+                                                                         atDate:[NSDate date]];
+    OCMVerify([mockContextManagerService contentFromContextualMessage:message]);
+    [mockContextManagerService stopMocking];
+  }
+}
+
+- (void)testContentFromConetxtualMessage {
+  if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
+    NSDictionary *message = @{
+      @"aps" : @{@"content-available" : @1},
+      @"gcm.message_id" : @1623702615599207,
+      @"gcm.n.e" : @1,
+      @"gcm.notification.badge" : @1,
+      @"gcm.notification.body" : kBody,
+      @"gcm.notification.image" :
+          @"https://firebasestorage.googleapis.com/v0/b/fir-ios-app-extensions.appspot.com/o/"
+          @"sparkyWFH.png?alt=media&token=f4dc1533-4d80-4ed6-9870-8df528593157",
+      @"gcm.notification.mutable_content" : @1,
+      @"gcm.notification.sound" : kSoundName,
+      @"gcm.notification.sound2" : kSoundName,
+      @"gcm.notification.title" : kTitle,
+      // This field is not popped out from console
+      // Manual add here to test unit test
+      @"gcm.notification.click_action" : kAction,
+      @"gcms" : @"gcm.gmsproc.cm",
+      @"google.c.a.c_id" : @2159728303499680621,
+      @"google.c.a.c_l" : @"test local send with sound",
+      @"google.c.a.e" : @1,
+      @"google.c.a.ts" : @1623753000,
+      @"google.c.a.udt" : @1,
+      @"google.c.cm.lt_end" : @"2021-07-13 10:30:00",
+      @"google.c.cm.lt_start" : @"2021-06-15 10:30:00",
+      @"google.c.sender.id" : @449451107265,
+    };
+    UNMutableNotificationContent *content =
+        [FIRMessagingContextManagerService contentFromContextualMessage:message];
+    XCTAssertEqualObjects(content.badge, @1);
+
+#if TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
+    XCTAssertEqualObjects(content.body, kBody);
+    XCTAssertEqualObjects(content.title, kTitle);
+#if !TARGET_OS_WATCH
+    XCTAssertEqualObjects(content.sound, [UNNotificationSound soundNamed:kSoundName]);
+#else   // !TARGET_OS_WATCH
+    XCTAssertEqualObjects(content.sound, [UNNotificationSound defaultSound]);
+#endif  // !TARGET_OS_WATCH
+    XCTAssertEqualObjects(content.categoryIdentifier, kAction);
+    NSDictionary *userInfo = @{
+      @"gcm.message_id" : @1623702615599207,
+      @"gcm.n.e" : @1,
+      @"gcm.notification.badge" : @1,
+      @"gcm.notification.body" : kBody,
+      @"gcm.notification.image" :
+          @"https://firebasestorage.googleapis.com/v0/b/fir-ios-app-extensions.appspot.com/o/"
+          @"sparkyWFH.png?alt=media&token=f4dc1533-4d80-4ed6-9870-8df528593157",
+      @"gcm.notification.mutable_content" : @1,
+      @"gcm.notification.sound" : kSoundName,
+      @"gcm.notification.sound2" : kSoundName,
+      @"gcm.notification.title" : kTitle,
+      // This field is not popped out from console
+      // Manual add here to test unit test
+      @"gcm.notification.click_action" : kAction,
+      @"gcms" : @"gcm.gmsproc.cm",
+      @"google.c.a.c_id" : @2159728303499680621,
+      @"google.c.a.c_l" : @"test local send with sound",
+      @"google.c.a.e" : @1,
+      @"google.c.a.ts" : @1623753000,
+      @"google.c.a.udt" : @1,
+      @"google.c.sender.id" : @449451107265
+    };
+    XCTAssertEqualObjects(content.userInfo, userInfo);
+#endif  // TARGET_OS_IOS || TARGET_OS_OSX || TARGET_OS_WATCH
+  }
+}
+
 @end

+ 12 - 1
FirebaseMessaging/Tests/UnitTests/FIRMessagingUtilitiesTest.m

@@ -68,10 +68,21 @@
 }
 
 - (void)testAppIdentifierReturnsExpectedValue {
+#if TARGET_OS_WATCH
+  NSString *bundleIdentifier = @"com.me.myapp.watchkit.watchkitextensions";
+  NSString *expectedIdentifier = @"com.me.myapp.watchkit";
+#else
+  NSString *bundleIdentifier = @"com.me.myapp";
   NSString *expectedIdentifier = @"com.me.myapp";
-  [[[_mainBundleMock stub] andReturn:expectedIdentifier] bundleIdentifier];
+#endif
+
+  [[[_mainBundleMock stub] andReturn:bundleIdentifier] bundleIdentifier];
   NSString *appIdentifier = FIRMessagingAppIdentifier();
+#if TARGET_OS_WATCH
+  XCTAssertEqualObjects(appIdentifier, expectedIdentifier);
+#else
   XCTAssertEqualObjects(appIdentifier, expectedIdentifier);
+#endif
 }
 
 - (void)testAppIdentifierReturnsEmptyStringWhenNotFound {