Register the current user for push notifications by using ASP.NET
Overview
This topic shows you how to request push notification registration with Azure Notification Hubs when registration is performed by ASP.NET Web API. This topic extends the tutorial Notify users with Notification Hubs. You must have already completed the required steps in that tutorial to create the authenticated mobile service. For more information on the notify users scenario, see Notify users with Notification Hubs.
Update your app
In your MainStoryboard_iPhone.storyboard, add the following components from the object library:
Label: "Push to User with Notification Hubs"
Label: "InstallationId"
Label: "User"
Text Field: "User"
Label: "Password"
Text Field: "Password"
Button: "Login"
At this point, your storyboard looks like the following:
In the assistant editor, create outlets for all the switched controls and call them, connect the text fields with the View Controller (delegate), and create an Action for the login button.
Your BreakingNewsViewController.h file should now contain the following code:
@property (weak, nonatomic) IBOutlet UILabel *installationId; @property (weak, nonatomic) IBOutlet UITextField *User; @property (weak, nonatomic) IBOutlet UITextField *Password; - (IBAction)login:(id)sender;
Create a class named
DeviceInfo
, and copy the following code into the interface section of the file DeviceInfo.h:@property (readonly, nonatomic) NSString* installationId; @property (nonatomic) NSData* deviceToken;
Copy the following code in the implementation section of the DeviceInfo.m file:
@synthesize installationId = _installationId; - (id)init { if (!(self = [super init])) return nil; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; _installationId = [defaults stringForKey:@"PushToUserInstallationId"]; if(!_installationId) { CFUUIDRef newUUID = CFUUIDCreate(kCFAllocatorDefault); _installationId = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, newUUID); CFRelease(newUUID); //store the install ID so we don't generate a new one next time [defaults setObject:_installationId forKey:@"PushToUserInstallationId"]; [defaults synchronize]; } return self; } - (NSString*)getDeviceTokenInHex { const unsigned *tokenBytes = [[self deviceToken] bytes]; NSString *hexToken = [NSString stringWithFormat:@"%08X%08X%08X%08X%08X%08X%08X%08X", ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]), ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]), ntohl(tokenBytes[6]), ntohl(tokenBytes[7])]; return hexToken; }
In PushToUserAppDelegate.h, add the following property singleton:
@property (strong, nonatomic) DeviceInfo* deviceInfo;
In the
didFinishLaunchingWithOptions
method in PushToUserAppDelegate.m, add the following code:self.deviceInfo = [[DeviceInfo alloc] init]; [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
The first line initializes the
DeviceInfo
singleton. The second line starts the registration for push notifications, which is already present if you have already completed the Get Started with Notification Hubs tutorial.In PushToUserAppDelegate.m, implement the method
didRegisterForRemoteNotificationsWithDeviceToken
in your AppDelegate and add the following code:self.deviceInfo.deviceToken = deviceToken;
This sets the device token for the request.
Note
At this point, there should not be any other code in this method. If you already have a call to the
registerNativeWithDeviceToken
method that was added when you completed the Send push notifications to iOS apps using Azure Notification Hubs tutorial, you must comment-out or remove that call.In the
PushToUserAppDelegate.m
file, add the following handler method:* (void) application:(UIApplication *) application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"%@", userInfo); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Notification" message: [userInfo objectForKey:@"inAppMessage"] delegate:nil cancelButtonTitle: @"OK" otherButtonTitles:nil, nil]; [alert show]; }
This method displays an alert in the UI when your app receives notifications while it is running.
Open the
PushToUserViewController.m
file, and return the keyboard in the following implementation:- (BOOL)textFieldShouldReturn:(UITextField *)theTextField { if (theTextField == self.User || theTextField == self.Password) { [theTextField resignFirstResponder]; } return YES; }
In the
viewDidLoad
method in thePushToUserViewController.m
file, initialize theinstallationId
label as follows:DeviceInfo* deviceInfo = [(PushToUserAppDelegate*)[[UIApplication sharedApplication]delegate] deviceInfo]; Self.installationId.text = deviceInfo.installationId;
Add the following properties in interface in
PushToUserViewController.m
:@property (readonly) NSOperationQueue* downloadQueue; - (NSString*)base64forData:(NSData*)theData;
Then, add the following implementation:
- (NSOperationQueue *)downloadQueue { if (!_downloadQueue) { _downloadQueue = [[NSOperationQueue alloc] init]; _downloadQueue.name = @"Download Queue"; _downloadQueue.maxConcurrentOperationCount = 1; } return _downloadQueue; } // base64 encoding - (NSString*)base64forData:(NSData*)theData { const uint8_t* input = (const uint8_t*)[theData bytes]; NSInteger length = [theData length]; static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; uint8_t* output = (uint8_t*)data.mutableBytes; NSInteger i; for (i=0; i < length; i += 3) { NSInteger value = 0; NSInteger j; for (j = i; j < (i + 3); j++) { value <<= 8; if (j < length) { value |= (0xFF & input[j]); } } NSInteger theIndex = (i / 3) * 4; output[theIndex + 0] = table[(value >> 18) & 0x3F]; output[theIndex + 1] = table[(value >> 12) & 0x3F]; output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; } return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; }
Copy the following code into the
login
handler method created by XCode:DeviceInfo* deviceInfo = [(PushToUserAppDelegate*)[[UIApplication sharedApplication]delegate] deviceInfo]; // build JSON NSString* json = [NSString stringWithFormat:@"{\"platform\":\"ios\", \"instId\":\"%@\", \"deviceToken\":\"%@\"}", deviceInfo.installationId, [deviceInfo getDeviceTokenInHex]]; // build auth string NSString* authString = [NSString stringWithFormat:@"%@:%@", self.User.text, self.Password.text]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://nhnotifyuser.azurewebsites.net/api/register"]]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]]; [request addValue:[@([json lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) description] forHTTPHeaderField:@"Content-Length"]; [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request addValue:[NSString stringWithFormat:@"Basic %@",[self base64forData:[authString dataUsingEncoding:NSUTF8StringEncoding]]] forHTTPHeaderField:@"Authorization"]; // connect with POST [NSURLConnection sendAsynchronousRequest:request queue:[self downloadQueue] completionHandler:^(NSURLResponse* response, NSData* data, NSError* error) { // add UIAlert depending on response. if (error != nil) { NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; if ([httpResponse statusCode] == 200) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Back-end registration" message:@"Registration successful" delegate:nil cancelButtonTitle: @"OK" otherButtonTitles:nil, nil]; [alert show]; } else { NSLog(@"status: %ld", (long)[httpResponse statusCode]); } } else { NSLog(@"error: %@", error); } }];
This method gets both an installation ID and channel for push notifications and sends it, along with the device type, to the authenticated Web API method that creates a registration in Notification Hubs. This Web API was defined in Notify users with Notification Hubs.
Now that the client app has been updated, return to the Notify users with Notification Hubs and update the mobile service to send notifications by using Notification Hubs.