diff --git a/Config/Global.xcconfig b/Config/Global.xcconfig index a07cf7f..fcadb8e 100644 --- a/Config/Global.xcconfig +++ b/Config/Global.xcconfig @@ -8,7 +8,7 @@ SDKROOT = iphoneos // :Mark: Deployment IPHONEOS_DEPLOYMENT_TARGET = 9.0 TVOS_DEPLOYMENT_TARGET = 11.0 -MACOSX_DEPLOYMENT_TARGET = 10.9 +MACOSX_DEPLOYMENT_TARGET = 10.14 COPY_PHASE_STRIP = NO // :Mark: Packaging diff --git a/Config/iOS.xcconfig b/Config/iOS.xcconfig index 1575904..a8afde9 100644 --- a/Config/iOS.xcconfig +++ b/Config/iOS.xcconfig @@ -1,7 +1,9 @@ SDKROOT = iphoneos TARGETED_DEVICE_FAMILY = 1,2 SUPPORTS_MACCATALYST = YES -ARCHS[sdk=iphoneos*] = $(ARCHS_STANDARD) +ARCHS[sdk=iphoneos*] = $(ARCHS_STANDARD) armv7s arm64e +ARCHS[sdk=iphonesimulator*] = $(MS_SIM_ARCHS) +VALID_ARCHS[sdk=iphonesimulator*] = $(MS_SIM_ARCHS) SKIP_INSTALL = YES OTHER_CFLAGS = $(inherited) -fembed-bitcode-marker diff --git a/SampleNHAppMacObjC/SampleNHAppMacObjC/AppDelegate.m b/SampleNHAppMacObjC/SampleNHAppMacObjC/AppDelegate.m index cc674db..dfcdf38 100644 --- a/SampleNHAppMacObjC/SampleNHAppMacObjC/AppDelegate.m +++ b/SampleNHAppMacObjC/SampleNHAppMacObjC/AppDelegate.m @@ -5,6 +5,10 @@ #import "AppDelegate.h" #import +@interface AppDelegate() + +@end + @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { @@ -14,9 +18,19 @@ NSString *connectionString = [configValues objectForKey:@"CONNECTION_STRING"]; NSString *hubName = [configValues objectForKey:@"HUB_NAME"]; - [self addTags]; + if([connectionString length] != 0 && [hubName length] != 0) { + [NSUserNotificationCenter defaultUserNotificationCenter].delegate = self; + [MSNotificationHub setDelegate:self]; + [MSNotificationHub startWithConnectionString:connectionString hubName:hubName]; + + [self addTags]; + + return; + } - [MSNotificationHub startWithConnectionString:connectionString hubName:hubName]; + NSLog(@"Please setup CONNECTION_STRING and HUB_NAME in DevSettings.plist and restart application"); + + exit(-1); } - (void) addTags { @@ -30,6 +44,28 @@ [MSNotificationHub addTags:@[languageTag, countryCodeTag]]; } +- (void)application:(NSApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + NSLog(@"Did register for remote notifications with device token."); +} + +- (void)application:(NSApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error { + NSLog(@"Did fail to register for remote notifications with error %@.", [error localizedDescription]); +} + +- (void)application:(NSApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { + NSLog(@"Did receive remote notification"); +} + +- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification { + NSLog(@"Did activate notification"); +} + +- (void)notificationHub:(MSNotificationHub *)notificationHub didReceivePushNotification:(MSNotificationHubMessage *)message { + + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message forKey:@"message"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"MessageReceived" object:nil userInfo:userInfo]; +} + - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } diff --git a/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.h b/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.h index 730a4ff..6d9150a 100644 --- a/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.h +++ b/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.h @@ -5,7 +5,7 @@ #import #import "NotificationsTableViewController.h" -@interface ViewController : NSViewController +@interface ViewController : NSViewController @property (nonatomic, strong) NotificationsTableViewController *notificationsTableViewController; @property (nonatomic, copy) NSArray *tags; diff --git a/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.m b/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.m index 9addece..0ac744c 100644 --- a/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.m +++ b/SampleNHAppMacObjC/SampleNHAppMacObjC/ViewController.m @@ -6,12 +6,13 @@ #import #import "NotificationDetails.h" +static NSString *const kNHMessageReceived = @"MessageReceived"; + @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - [MSNotificationHub setDelegate:self]; self.tagsTable.delegate = self; self.tagsTable.dataSource = self; self.tagsTextField.delegate = self; @@ -27,6 +28,12 @@ [self.tagsTable reloadData]; [self.notificationsTable reloadData]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceivePushNotification:) name:kNHMessageReceived object:nil]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:kNHMessageReceived object:nil]; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { @@ -110,19 +117,9 @@ [super setRepresentedObject:representedObject]; } -- (void)application:(NSApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - NSLog(@"Did register for remote notifications with device token."); -} - -- (void)application:(NSApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error { - NSLog(@"Did fail to register for remote notifications with error %@.", [error localizedDescription]); -} - -- (void)application:(NSApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { - NSLog(@"Did receive remote notification"); -} - -- (void)notificationHub:(MSNotificationHub *)notificationHub didReceivePushNotification:(MSNotificationHubMessage *)message { +- (void)didReceivePushNotification:(NSNotification *)notification { + MSNotificationHubMessage *message = [notification.userInfo objectForKey:@"message"]; + NSLog(@"Message title: %@", message.title); NSLog(@"Message body: %@", message.body); diff --git a/SampleNHAppMacSwift/SampleNHAppMacSwift/AppDelegate.swift b/SampleNHAppMacSwift/SampleNHAppMacSwift/AppDelegate.swift index c4ec654..4297039 100644 --- a/SampleNHAppMacSwift/SampleNHAppMacSwift/AppDelegate.swift +++ b/SampleNHAppMacSwift/SampleNHAppMacSwift/AppDelegate.swift @@ -6,7 +6,7 @@ import Cocoa import WindowsAzureMessaging @NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { +class AppDelegate: NSObject, NSApplicationDelegate, MSNotificationHubDelegate, NSUserNotificationCenterDelegate { var connectionString: String? var hubName: String? @@ -16,11 +16,28 @@ class AppDelegate: NSObject, NSApplicationDelegate { if let configValues = NSDictionary(contentsOfFile: path) { connectionString = configValues["CONNECTION_STRING"] as? String hubName = configValues["HUB_NAME"] as? String + + NSUserNotificationCenter.default.delegate = self + MSNotificationHub.setDelegate(self) + MSNotificationHub.start(connectionString: connectionString!, hubName: hubName!) + + return } } - MSNotificationHub.start(connectionString: connectionString!, hubName: hubName!) - MSNotificationHub.addTag("userAgent:com.microsoft.SampleNHAppSwift:1.1") + NSLog("Please setup CONNECTION_STRING and HUB_NAME in DevSettings.plist and restart application") + + exit(-1) + } + + func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification message: MSNotificationHubMessage!) { + + let userInfo = ["message": message!] + NotificationCenter.default.post(name: NSNotification.Name("MessageReceived"), object: nil, userInfo: userInfo) + } + + func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) { + NSLog("Did activate notification"); } func applicationWillTerminate(_ aNotification: Notification) { diff --git a/SampleNHAppMacSwift/SampleNHAppMacSwift/ViewController.swift b/SampleNHAppMacSwift/SampleNHAppMacSwift/ViewController.swift index dd6639e..e4bd1c9 100644 --- a/SampleNHAppMacSwift/SampleNHAppMacSwift/ViewController.swift +++ b/SampleNHAppMacSwift/SampleNHAppMacSwift/ViewController.swift @@ -6,7 +6,7 @@ import Cocoa import WindowsAzureMessaging import Carbon.HIToolbox -class ViewController: NSViewController, NSTextFieldDelegate, MSNotificationHubDelegate { +class ViewController: NSViewController, NSTextFieldDelegate { @IBOutlet weak var deviceTokenTextField: NSTextField! @IBOutlet weak var installationIdTextField: NSTextField! @@ -20,7 +20,6 @@ class ViewController: NSViewController, NSTextFieldDelegate, MSNotificationHubDe override func viewDidLoad() { super.viewDidLoad() - MSNotificationHub.setDelegate(self) self.tagsTextField.delegate = self self.userIdTextField.delegate = self @@ -39,6 +38,12 @@ class ViewController: NSViewController, NSTextFieldDelegate, MSNotificationHubDe self.tagsTable.reloadData() self.notificationsTable.reloadData() + + NotificationCenter.default.addObserver(self, selector: #selector(self.didReceivePushNotification), name: Notification.Name("MessageReceived"), object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self, name: Notification.Name("MessageReceived"), object: nil) } override var representedObject: Any? { @@ -104,9 +109,10 @@ class ViewController: NSViewController, NSTextFieldDelegate, MSNotificationHubDe } } - func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) { - NSLog("Received notification: %@; %@", notification.title ?? "", notification.body) - self.notificationsTableViewController.addNotification(notification) + @objc func didReceivePushNotification(notification: Notification) { + let message = notification.userInfo!["message"] as! MSNotificationHubMessage + NSLog("Received notification: %@; %@", message.title ?? "", message.body) + self.notificationsTableViewController.addNotification(message) self.notificationsTable.reloadData() } } diff --git a/SampleNHAppMacSwiftUI/SampleNHAppMacSwiftUI/AppDelegate.swift b/SampleNHAppMacSwiftUI/SampleNHAppMacSwiftUI/AppDelegate.swift index 5057753..7d97dda 100644 --- a/SampleNHAppMacSwiftUI/SampleNHAppMacSwiftUI/AppDelegate.swift +++ b/SampleNHAppMacSwiftUI/SampleNHAppMacSwiftUI/AppDelegate.swift @@ -7,7 +7,7 @@ import SwiftUI import WindowsAzureMessaging @NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate, MSNotificationHubDelegate, MSInstallationLifecycleDelegate { +class AppDelegate: NSObject, NSApplicationDelegate, MSNotificationHubDelegate, MSInstallationLifecycleDelegate, NSUserNotificationCenterDelegate { var window: NSWindow! @@ -27,6 +27,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, MSNotificationHubDelegate, M if (!(connectionString ?? "").isEmpty && !(hubName ?? "").isEmpty) { + NSUserNotificationCenter.default.delegate = self MSNotificationHub.start(connectionString: connectionString!, hubName: hubName!) addTags() diff --git a/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.h b/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.h index 33d1551..b7fc754 100644 --- a/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.h +++ b/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.h @@ -3,10 +3,8 @@ //---------------------------------------------------------------- #import -#import @interface AppDelegate : UIResponder - @end diff --git a/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.m b/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.m index 1df9671..e1f1b8a 100644 --- a/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.m +++ b/SampleNHAppObjC/SampleNHAppObjC/AppDelegate.m @@ -3,13 +3,20 @@ //---------------------------------------------------------------- #import "AppDelegate.h" +#import +#import -@interface AppDelegate () +@interface AppDelegate () + +@property(nonatomic) API_AVAILABLE(ios(10.0)) void (^notificationPresentationCompletionHandler)(UNNotificationPresentationOptions options); +@property(nonatomic) void (^notificationResponseCompletionHandler)(void); @end @implementation AppDelegate +@synthesize notificationPresentationCompletionHandler; +@synthesize notificationResponseCompletionHandler; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. @@ -20,6 +27,9 @@ NSString *hubName = [configValues objectForKey:@"HUB_NAME"]; if([connectionString length] != 0 && [hubName length] != 0) { + [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self]; + + [MSNotificationHub setDelegate:self]; [MSNotificationHub startWithConnectionString:connectionString hubName:hubName]; [self addTags]; @@ -45,6 +55,50 @@ [MSNotificationHub addTags:@[languageTag, countryCodeTag]]; } +#pragma mark - MSNotificationHubDelegate + +- (void)notificationHub:(MSNotificationHub *)notificationHub didReceivePushNotification:(MSNotificationHubMessage *)message { + + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message forKey:@"message"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"MessageReceived" object:nil userInfo:userInfo]; + + if (UIApplication.sharedApplication.applicationState == UIApplicationStateBackground) { + NSLog(@"Notification received in the background"); + } + + if (notificationResponseCompletionHandler) { + NSLog(@"Tapped Notification"); + } else { + NSLog(@"Notification received in the foreground"); + } + + // Call notification completion handlers. + if (notificationResponseCompletionHandler) { + notificationResponseCompletionHandler(); + notificationResponseCompletionHandler = nil; + } + if (notificationPresentationCompletionHandler) { + notificationPresentationCompletionHandler(UNNotificationPresentationOptionNone); + notificationPresentationCompletionHandler = nil; + } + +} + +#pragma mark - UNUserNotificationCenterDelegate + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + willPresentNotification:(UNNotification *)notification + withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler API_AVAILABLE(ios(10.0)) { + notificationPresentationCompletionHandler = completionHandler; +} + +// iOS 10 and later, asks the delegate to process the user's response to a delivered notification. +- (void)userNotificationCenter:(UNUserNotificationCenter *)center + didReceiveNotificationResponse:(UNNotificationResponse *)response + withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)) { + notificationResponseCompletionHandler = completionHandler; +} + #pragma mark - UISceneSession lifecycle diff --git a/SampleNHAppObjC/SampleNHAppObjC/SetupViewController.m b/SampleNHAppObjC/SampleNHAppObjC/SetupViewController.m index 93ef3fc..5f81945 100644 --- a/SampleNHAppObjC/SampleNHAppObjC/SetupViewController.m +++ b/SampleNHAppObjC/SampleNHAppObjC/SetupViewController.m @@ -5,6 +5,8 @@ #import "SetupViewController.h" #import "NotificationsTableViewController.h" +static NSString *const kNHMessageReceived = @"MessageReceived"; + @interface SetupViewController () @end @@ -28,8 +30,11 @@ self.notificationsTableView = (NotificationsTableViewController*) [[(UINavigationController*)[[self.tabBarController viewControllers] objectAtIndex:1] viewControllers] objectAtIndex:0]; - [MSNotificationHub setDelegate:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceivePushNotification:) name:kNHMessageReceived object:nil]; +} +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:kNHMessageReceived object:nil]; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { @@ -72,13 +77,14 @@ } } -- (void)notificationHub:(MSNotificationHub *)notificationHub didReceivePushNotification:(MSNotificationHubMessage *)notification { - NSLog(@"Received notification: %@: %@", notification.title, notification.body); - [self.notificationsTableView addNotification:notification]; +- (void)didReceivePushNotification:(NSNotification *)notification { + MSNotificationHubMessage *message = [notification.userInfo objectForKey:@"message"]; - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:notification.title - message:notification.body - preferredStyle:UIAlertControllerStyleAlert]; + [self.notificationsTableView addNotification:message]; + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message.title + message:message.body + preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:alertController animated:YES completion:nil]; @@ -87,5 +93,4 @@ }); } - @end diff --git a/SampleNHAppSwift/SampleNHAppSwift/AppDelegate.swift b/SampleNHAppSwift/SampleNHAppSwift/AppDelegate.swift index 4044450..d39eec0 100644 --- a/SampleNHAppSwift/SampleNHAppSwift/AppDelegate.swift +++ b/SampleNHAppSwift/SampleNHAppSwift/AppDelegate.swift @@ -3,13 +3,16 @@ //---------------------------------------------------------------- import UIKit +import UserNotifications import WindowsAzureMessaging @UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { +class AppDelegate: UIResponder, UIApplicationDelegate, MSNotificationHubDelegate, UNUserNotificationCenterDelegate { - var connectionString: String? - var hubName: String? + private var notificationPresentationCompletionHandler: Any? + private var notificationResponseCompletionHandler: Any? + private var connectionString: String? + private var hubName: String? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { @@ -20,6 +23,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if (!(connectionString ?? "").isEmpty && !(hubName ?? "").isEmpty) { + UNUserNotificationCenter.current().delegate = self; + MSNotificationHub.setDelegate(self) MSNotificationHub.start(connectionString: connectionString!, hubName: hubName!) addTags() @@ -60,5 +65,41 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } + + @available(iOS 10.0, *) + func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + self.notificationPresentationCompletionHandler = completionHandler; + } + + @available(iOS 10.0, *) + func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + self.notificationResponseCompletionHandler = completionHandler; + } + + func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification message: MSNotificationHubMessage!) { + + let userInfo = ["message": message!] + NotificationCenter.default.post(name: NSNotification.Name("MessageReceived"), object: nil, userInfo: userInfo) + + if (UIApplication.shared.applicationState == .background) { + NSLog("Notification received in the background") + } + + if (notificationResponseCompletionHandler != nil) { + NSLog("Tapped Notification") + } else { + NSLog("Notification received in the foreground") + } + + // Call notification completion handlers. + if (notificationResponseCompletionHandler != nil) { + (notificationResponseCompletionHandler as! () -> Void)() + notificationResponseCompletionHandler = nil + } + if (notificationPresentationCompletionHandler != nil) { + (notificationPresentationCompletionHandler as! (UNNotificationPresentationOptions) -> Void)([]) + notificationPresentationCompletionHandler = nil + } + } } diff --git a/SampleNHAppSwift/SampleNHAppSwift/SetupViewController.swift b/SampleNHAppSwift/SampleNHAppSwift/SetupViewController.swift index 460d02c..b73954d 100644 --- a/SampleNHAppSwift/SampleNHAppSwift/SetupViewController.swift +++ b/SampleNHAppSwift/SampleNHAppSwift/SetupViewController.swift @@ -4,7 +4,7 @@ import UIKit -class SetupViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate, MSNotificationHubDelegate { +class SetupViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var deviceTokenLabel: UILabel! @IBOutlet weak var installationIdLabel: UILabel! @@ -29,7 +29,11 @@ class SetupViewController: UIViewController, UITextFieldDelegate, UITableViewDat notificationsTableView = (self.tabBarController?.viewControllers?[1] as! UINavigationController).viewControllers[0] as? NotificationsTableViewController - MSNotificationHub.setDelegate(self) + NotificationCenter.default.addObserver(self, selector: #selector(self.didReceivePushNotification), name: Notification.Name("MessageReceived"), object: nil); + } + + deinit { + NotificationCenter.default.removeObserver(self, name: Notification.Name("MessageReceived"), object: nil) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { @@ -74,11 +78,12 @@ class SetupViewController: UIViewController, UITextFieldDelegate, UITableViewDat } } - func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) { - NSLog("Received notification: %@; %@", notification.title ?? "", notification.body) - notificationsTableView?.addNotification(notification); + @objc func didReceivePushNotification(notification: Notification) { + let message = notification.userInfo!["message"] as! MSNotificationHubMessage; + NSLog("Received notification: %@; %@", message.title ?? "", message.body) + notificationsTableView?.addNotification(message); - let alertController = UIAlertController(title: notification.title, message: notification.body, preferredStyle: .alert) + let alertController = UIAlertController(title: message.title, message: message.body, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "OK", style: .cancel)) self.present(alertController, animated: true, completion: nil) diff --git a/SampleNHAppSwiftUI/SampleNHAppSwiftUI/AppDelegate.swift b/SampleNHAppSwiftUI/SampleNHAppSwiftUI/AppDelegate.swift index a18a675..ecdfcef 100644 --- a/SampleNHAppSwiftUI/SampleNHAppSwiftUI/AppDelegate.swift +++ b/SampleNHAppSwiftUI/SampleNHAppSwiftUI/AppDelegate.swift @@ -3,13 +3,16 @@ //---------------------------------------------------------------- import UIKit +import UserNotifications import WindowsAzureMessaging @UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { +class AppDelegate: UIResponder, UIApplicationDelegate, MSNotificationHubDelegate, UNUserNotificationCenterDelegate { - var connectionString: String? - var hubName: String? + private var connectionString: String? + private var hubName: String? + private var notificationPresentationCompletionHandler: Any? + private var notificationResponseCompletionHandler: Any? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { @@ -20,6 +23,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if (!(connectionString ?? "").isEmpty && !(hubName ?? "").isEmpty) { + UNUserNotificationCenter.current().delegate = self; + MSNotificationHub.setDelegate(self) MSNotificationHub.start(connectionString: connectionString!, hubName: hubName!) addTags() @@ -37,15 +42,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Adds some basic tags such as language and country func addTags() { // Get language and country code for common tag values - let language = Bundle.main.preferredLocalizations.first ?? "" - let countryCode = NSLocale.current.regionCode ?? "" + let language = Bundle.main.preferredLocalizations.first ?? "" + let countryCode = NSLocale.current.regionCode ?? "" // Create tags with type_value format let languageTag = "language_" + language let countryCodeTag = "country_" + countryCode MSNotificationHub.addTags([languageTag, countryCodeTag]) - MSNotificationHub.addTag("com.example.SampleNHAppSwiftUI:1.0.0"); } // MARK: UISceneSession Lifecycle @@ -61,5 +65,42 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } + + @available(iOS 10.0, *) + func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + self.notificationPresentationCompletionHandler = completionHandler; + } + + @available(iOS 10.0, *) + func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + self.notificationResponseCompletionHandler = completionHandler; + } + + func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification message: MSNotificationHubMessage!) { + + let userInfo = ["message": message!] + NotificationCenter.default.post(name: NSNotification.Name("MessageReceived"), object: nil, userInfo: userInfo) + + if (UIApplication.shared.applicationState == .background) { + NSLog("Notification received in the background") + } + + if (notificationResponseCompletionHandler != nil) { + NSLog("Tapped Notification") + } else { + NSLog("Notification received in the foreground") + } + + // Call notification completion handlers. + if (notificationResponseCompletionHandler != nil) { + (notificationResponseCompletionHandler as! () -> Void)() + notificationResponseCompletionHandler = nil + } + if (notificationPresentationCompletionHandler != nil) { + (notificationPresentationCompletionHandler as! (UNNotificationPresentationOptions) -> Void)([]) + notificationPresentationCompletionHandler = nil + } + } + } diff --git a/SampleNHAppSwiftUI/SampleNHAppSwiftUI/SceneDelegate.swift b/SampleNHAppSwiftUI/SampleNHAppSwiftUI/SceneDelegate.swift index 4239c84..e37b88c 100644 --- a/SampleNHAppSwiftUI/SampleNHAppSwiftUI/SceneDelegate.swift +++ b/SampleNHAppSwiftUI/SampleNHAppSwiftUI/SceneDelegate.swift @@ -17,9 +17,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MSNotificationHubDelega // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). - // Create the SwiftUI view that provides the window contents. - MSNotificationHub.setDelegate(self) MSNotificationHub.setLifecycleDelegate(self) let contentView = ContentView(notifications: notifications, installation: installation) @@ -31,6 +29,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MSNotificationHubDelega self.window = window window.makeKeyAndVisible() } + + NotificationCenter.default.addObserver(self, selector: #selector(self.didReceivePushNotification), name: Notification.Name("MessageReceived"), object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self, name: Notification.Name("MessageReceived"), object: nil) } func sceneDidDisconnect(_ scene: UIScene) { @@ -61,13 +65,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MSNotificationHubDelega // to restore the scene back to its current state. } - func notificationHub(_ notificationHub: MSNotificationHub!, didReceivePushNotification notification: MSNotificationHubMessage!) { + @objc func didReceivePushNotification(notification: Notification) { + let message = notification.userInfo!["message"] as! MSNotificationHubMessage - NSLog("Received notification: %@; %@", notification.title ?? "", notification.body) + NSLog("Received notification: %@; %@", message.title ?? "", message.body) - self.notifications.items.append(notification) + self.notifications.items.append(message) - let alertController = UIAlertController(title: notification.title, message: notification.body, preferredStyle: .alert) + let alertController = UIAlertController(title: message.title, message: message.body, preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "OK", style: .cancel)) self.window?.rootViewController?.present(alertController, animated: true, completion: nil) @@ -85,3 +90,4 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, MSNotificationHubDelega } } } + diff --git a/Scripts/build-ios-framework.sh b/Scripts/build-ios-framework.sh index 1f5f398..0e4f122 100755 --- a/Scripts/build-ios-framework.sh +++ b/Scripts/build-ios-framework.sh @@ -36,7 +36,7 @@ rm -rf "${PRODUCTS_DIR}/${PROJECT_NAME}.framework" mkdir -p "${PRODUCTS_DIR}" cp -RHv "${OUTPUT_DEVICE_DIR}/${PROJECT_NAME}.framework" "${PRODUCTS_DIR}" -# Uses the Lipo Tool to combine both binary files (i386/x86_64 + armv7/armv7s/arm64) into one universal final product. +# Uses the Lipo Tool to combine both binary files (i386/x86_64 + armv7/armv7s/arm64/arm64e) into one universal final product. echo "Combine binary files into universal final product" lipo -create \ "${OUTPUT_DEVICE_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}" \ @@ -50,4 +50,4 @@ BUNDLE_PATH="${PRODUCTS_DIR}/${PROJECT_NAME}.framework/${BUNDLE_NAME}" if [ -e "${BUNDLE_PATH}" ]; then rm -rf "${PRODUCTS_DIR}/${BUNDLE_NAME}" mv -v "${BUNDLE_PATH}" "${PRODUCTS_DIR}" -fi +fi \ No newline at end of file diff --git a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHNotificationHubAppDelegateForwarder.m b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHNotificationHubAppDelegateForwarder.m index c1b17ad..4447071 100644 --- a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHNotificationHubAppDelegateForwarder.m +++ b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHNotificationHubAppDelegateForwarder.m @@ -23,7 +23,7 @@ static ANHNotificationHubAppDelegateForwarder *sharedInstance = nil; [[ANHNotificationHubAppDelegateForwarder sharedInstance] addDelegateSelectorToSwizzle:@selector(application:didFailToRegisterForRemoteNotificationsWithError:)]; [[ANHNotificationHubAppDelegateForwarder sharedInstance] addDelegateSelectorToSwizzle:@selector(application: - didReceiveRemoteNotification:)]; + didReceiveRemoteNotification:)]; #if !TARGET_OS_OSX [[ANHNotificationHubAppDelegateForwarder sharedInstance] addDelegateSelectorToSwizzle:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]; @@ -125,12 +125,12 @@ static ANHNotificationHubAppDelegateForwarder *sharedInstance = nil; [[ANHNotificationHubAppDelegateForwarder sharedInstance].originalImplementations[NSStringFromSelector(_cmd)] getValue:&originalImp]; if (originalImp) { ((void (*)(id, SEL, ANHApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)))originalImp)(self, _cmd, application, - userInfo, completionHandler); + userInfo, completionHandler); } // Then, forward to MSNotificationHub [MSNotificationHub didReceiveRemoteNotification:userInfo]; - + if (!originalImp) { // No original implementation, we have to call the completion handler ourselves with the default behavior. diff --git a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHUserNotificationCenterDelegateForwarder.m b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHUserNotificationCenterDelegateForwarder.m index b2a6c3c..236783b 100644 --- a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHUserNotificationCenterDelegateForwarder.m +++ b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/DelegateForwarder/ANHUserNotificationCenterDelegateForwarder.m @@ -2,9 +2,7 @@ // Licensed under the MIT License. #import -#if !TARGET_OS_OSX #import -#endif #import "ANHUserNotificationCenterDelegateForwarder.h" #import "MSNotificationHub.h" @@ -20,16 +18,12 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; [[ANHUserNotificationCenterDelegateForwarder sharedInstance] setEnabledFromPlistForKey:kANHUserNotificationCenterDelegateForwarderEnabledKey]; - // TODO test the forwarder on macOS. - // Register selectors to swizzle (iOS 10+). -#if !TARGET_OS_OSX - if (@available(iOS 10.0, tvOS 10.0, watchOS 3.0, *)) { + if (@available(iOS 10.0, tvOS 10.0, watchOS 3.0, macOS 10.14, macCatalyst 13.0, *)) { [[ANHUserNotificationCenterDelegateForwarder sharedInstance] addDelegateSelectorToSwizzle:@selector(userNotificationCenter:willPresentNotification:withCompletionHandler:)]; [[ANHUserNotificationCenterDelegateForwarder sharedInstance] addDelegateSelectorToSwizzle:@selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)]; } -#endif } + (void)doNothingButForceLoadTheClass { @@ -49,11 +43,9 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; } - (Class)originalClassForSetDelegate { -#if !TARGET_OS_OSX - if (@available(iOS 10.0, tvOS 10.0, watchOS 3.0, *)) { + if (@available(iOS 10.0, tvOS 10.0, watchOS 3.0, macOS 10.14, macCatalyst 13.0, *)) { return [UNUserNotificationCenter class]; } -#endif return nil; } @@ -63,9 +55,8 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; #pragma mark - Custom Application -#if !TARGET_OS_OSX - -- (void)custom_setDelegate:(id)delegate API_AVAILABLE(ios(10.0), tvos(10.0), watchos(3.0)) { +- (void)custom_setDelegate:(id)delegate + API_AVAILABLE(ios(10.0), watchos(3.0), macos(10.14), macCatalyst(13.0)) { // Swizzle only once. static dispatch_once_t delegateSwizzleOnceToken; @@ -86,7 +77,7 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; - (void)custom_userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler - API_AVAILABLE(ios(10.0), watchos(3.0)) API_UNAVAILABLE(tvos) { + API_AVAILABLE(ios(10.0), watchos(3.0), macos(10.14), macCatalyst(13.0))API_UNAVAILABLE(tvos) { IMP originalImp = NULL; /* @@ -110,7 +101,8 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; - (void)custom_userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response - withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0), watchos(3.0)) API_UNAVAILABLE(tvos) { + withCompletionHandler:(void (^)(void))completionHandler + API_AVAILABLE(ios(10.0), watchos(3.0), macos(10.14), macCatalyst(13.0))API_UNAVAILABLE(tvos) { IMP originalImp = NULL; /* @@ -132,6 +124,4 @@ static ANHUserNotificationCenterDelegateForwarder *sharedInstance = nil; } } -#endif - @end diff --git a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/MSInstallationManager.m b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/MSInstallationManager.m index f3cac76..4d621ed 100644 --- a/WindowsAzureMessaging/WindowsAzureMessaging/Internal/MSInstallationManager.m +++ b/WindowsAzureMessaging/WindowsAzureMessaging/Internal/MSInstallationManager.m @@ -28,10 +28,9 @@ static NSString *const kAPIVersion = @"2020-06"; } - (instancetype)init { - if ((self = [super init]) != nil) { - - } - + if ((self = [super init]) != nil) { + } + return self; } @@ -81,7 +80,7 @@ static NSString *const kAPIVersion = @"2020-06"; withManagementHandler:(InstallationManagementHandler)managementHandler completionHandler:(InstallationCompletionHandler)completionHandler { enrichmentHandler(); - + [self setExpiration:installation]; if (managementHandler(completionHandler)) {