Azure Notification Hubs – Részletes leküldés
Áttekintés
Ha azonnali tartalommal szeretné bevonni a felhasználókat, előfordulhat, hogy egy alkalmazás egyszerű szövegen túl szeretne leküldni. Ezek az értesítések elősegítik a felhasználói interakciókat, és olyan tartalmakat mutatnak be, mint az URL-címek, a hangok, a képek/kuponok stb. Ez az oktatóanyag a Felhasználók értesítése oktatóanyagra épül, és bemutatja, hogyan küldhet leküldéses értesítéseket hasznos adatokat (például képeket) tartalmazó leküldéses értesítéseket.
Ez az oktatóanyag kompatibilis az iOS 7 és 8 rendszerrel.
Magas szinten:
- Az alkalmazás háttérrendszere:
- A gazdag hasznos adatokat (ebben az esetben a rendszerképet) a háttéradatbázisban/helyi tárolóban tárolja.
- A részletes értesítés azonosítóját küldi el az eszköznek.
- Alkalmazás az eszközön:
- Kapcsolatba lép a háttérrendszerrel, és kéri a gazdag hasznos adatokat a kapott azonosítóval.
- Értesítéseket küld a felhasználóknak az eszközön, amikor az adatlekérés befejeződött, és azonnal megjeleníti a hasznos adatokat, amikor a felhasználók koppintással többet is megtudhatnak.
WebAPI-projekt
A Visual Studióban nyissa meg a Felhasználók értesítése oktatóanyagban létrehozott AppBackend projektet.
Szerezzen be egy képet, amellyel értesíteni szeretné a felhasználókat, és helyezze egy img mappába a projektkönyvtárban.
Kattintson az Összes fájl megjelenítése elemre a Megoldáskezelő, majd kattintson a jobb gombbal a mappára a Belefoglalás a Projectbe parancshoz.
Ha a kép ki van jelölve, módosítsa a Létrehozási műveletet a Tulajdonságok ablakban beágyazott erőforrásra.
A fájlban
Notifications.cs
adja hozzá a következőusing
utasítást:using System.Reflection;
Cserélje le az osztályt
Notifications
a következő kódra. Mindenképpen cserélje le a helyőrzőket az értesítési központ hitelesítő adataira és a képfájl nevére:public class Notification { public int Id { get; set; } // Initial notification message to display to users public string Message { get; set; } // Type of rich payload (developer-defined) public string RichType { get; set; } public string Payload { get; set; } public bool Read { get; set; } } public class Notifications { public static Notifications Instance = new Notifications(); private List<Notification> notifications = new List<Notification>(); public NotificationHubClient Hub { get; set; } private Notifications() { // Placeholders: replace with the connection string (with full access) for your notification hub and the hub name from the Azure Classics Portal Hub = NotificationHubClient.CreateClientFromConnectionString("{conn string with full access}", "{hub name}"); } public Notification CreateNotification(string message, string richType, string payload) { var notification = new Notification() { Id = notifications.Count, Message = message, RichType = richType, Payload = payload, Read = false }; notifications.Add(notification); return notification; } public Stream ReadImage(int id) { var assembly = Assembly.GetExecutingAssembly(); // Placeholder: image file name (for example, logo.png). return assembly.GetManifestResourceStream("AppBackend.img.{logo.png}"); } }
A fájlban
NotificationsController.cs
adjaNotificationsController
meg újra a következő kódot. Ez egy kezdeti csendes, részletes értesítési azonosítót küld az eszköznek, és lehetővé teszi a rendszerkép ügyféloldali lekérését:// Return http response with image binary public HttpResponseMessage Get(int id) { var stream = Notifications.Instance.ReadImage(id); var result = new HttpResponseMessage(HttpStatusCode.OK); result.Content = new StreamContent(stream); // Switch in your image extension for "png" result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/{png}"); return result; } // Create rich notification and send initial silent notification (containing id) to client public async Task<HttpResponseMessage> Post() { // Replace the placeholder with image file name var richNotificationInTheBackend = Notifications.Instance.CreateNotification("Check this image out!", "img", "{logo.png}"); var usernameTag = "username:" + HttpContext.Current.User.Identity.Name; // Silent notification with content available var aboutUser = "{\"aps\": {\"content-available\": 1, \"sound\":\"\"}, \"richId\": \"" + richNotificationInTheBackend.Id.ToString() + "\", \"richMessage\": \"" + richNotificationInTheBackend.Message + "\", \"richType\": \"" + richNotificationInTheBackend.RichType + "\"}"; // Send notification to apns await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(aboutUser, usernameTag); return Request.CreateResponse(HttpStatusCode.OK); }
Most helyezze újra üzembe ezt az alkalmazást egy Azure-webhelyen, hogy minden eszközről elérhető legyen. Kattintson jobb gombbal az AppBackend projektre, és válassza a Publish (Közzététel) lehetőséget.
Válassza ki az Azure-webhelyet közzétételi célként. Jelentkezzen be az Azure-fiókjával, válasszon ki egy meglévő vagy új webhelyet, és jegyezze fel a Cél URL-cím tulajdonságát a Kapcsolat lapon. Az oktatóanyag későbbi részében ezt az URL-címet tekintjük a háttérbeli végpontnak . Válassza a Közzététel lehetőséget.
Az iOS-projekt módosítása
Most, hogy módosította az alkalmazás háttérrendszerét úgy, hogy csak egy értesítés azonosítóját küldje el, módosítsa az iOS-alkalmazást az azonosító kezelésére, és kérje le a gazdag üzenetet a háttérrendszerből:
Nyissa meg az iOS-projektet, és engedélyezze a távoli értesítéseket a Célok szakaszban található fő alkalmazáscélra lépve.
Válassza a Képességek lehetőséget, engedélyezze a Háttér módokat, és jelölje be a Távoli értesítések jelölőnégyzetet .
Nyissa meg
Main.storyboard
a elemet, és győződjön meg arról, hogy rendelkezik nézetvezérlővel (ebben az oktatóanyagban Home View Controller néven) a Felhasználó értesítése oktatóanyagból.Vegyen fel egy navigációs vezérlőt a vágólapra, és húzza a vezérlőt a Kezdőlapnézet-vezérlőre, hogy az legyen a navigáció gyökérnézete . Győződjön meg arról, hogy az Attribútumok felügyelő kezdeti nézetvezérlője csak a navigációs vezérlőhöz van kiválasztva.
Adjon hozzá egy Nézetvezérlőt a storyboardhoz, és adjon hozzá egy Képnézetet. Ezt az oldalt fogják látni a felhasználók, ha úgy döntenek, hogy többet szeretnének megtudni az értesítésre kattintva. A történetnek a következőképpen kell kinéznie:
Kattintson a Kezdőlapnézet-vezérlőre a vágólapon, és győződjön meg arról, hogy a homeViewController egyéni osztály- és storyboard-azonosítóval rendelkezik az Identitásfelügyelő alatt.
Tegye ugyanezt a Képnézet-vezérlő esetében is, mint az imageViewController esetében.
Ezután hozzon létre egy imageViewController nevű új Nézetvezérlő osztályt az imént létrehozott felhasználói felület kezeléséhez.
Az imageViewController.h fájlban adja hozzá a következő kódot a vezérlő felületi deklarációihoz. A két tulajdonság összekapcsolásához mindenképpen húzza a vezérlőt a vágólap képnézetéből az alábbi tulajdonságokra:
@property (weak, nonatomic) IBOutlet UIImageView *myImage; @property (strong) UIImage* imagePayload;
A
imageViewController.m
fájlban adja hozzá a következőt a végéhezviewDidload
:// Display the UI Image in UI Image View [self.myImage setImage:self.imagePayload];
A fájlban
AppDelegate.m
importálja a létrehozott képvezérlőt:#import "imageViewController.h"
Adjon hozzá egy felületszakaszt a következő deklarációval:
@interface AppDelegate () @property UIImage* imagePayload; @property NSDictionary* userInfo; @property BOOL iOS8; // Obtain content from backend with notification id - (void)retrieveRichImageWithId:(int)richId completion: (void(^)(NSError*)) completion; // Redirect to Image View Controller after notification interaction - (void)redirectToImageViewWithImage: (UIImage *)img; @end
A fájlban
AppDelegate
győződjön meg arról, hogy az alkalmazás regisztrál a csendes értesítésekre a következő helyenapplication: didFinishLaunchingWithOptions
:// Software version self.iOS8 = [[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)] && [[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]; // Register for remote notifications for iOS8 and previous versions if (self.iOS8) { NSLog(@"This device is running with iOS8."); // Action UIMutableUserNotificationAction *richPushAction = [[UIMutableUserNotificationAction alloc] init]; richPushAction.identifier = @"richPushMore"; richPushAction.activationMode = UIUserNotificationActivationModeForeground; richPushAction.authenticationRequired = NO; richPushAction.title = @"More"; // Notification category UIMutableUserNotificationCategory* richPushCategory = [[UIMutableUserNotificationCategory alloc] init]; richPushCategory.identifier = @"richPush"; [richPushCategory setActions:@[richPushAction] forContext:UIUserNotificationActionContextDefault]; // Notification categories NSSet* richPushCategories = [NSSet setWithObjects:richPushCategory, nil]; UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:richPushCategories]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerForRemoteNotifications]; } else { // Previous iOS versions NSLog(@"This device is running with iOS7 or earlier versions."); [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeNewsstandContentAvailability]; } return YES;
Helyettesítse be a következő implementációt
application:didRegisterForRemoteNotificationsWithDeviceToken
, hogy figyelembe vegye a storyboard felhasználói felületének módosításait:// Access navigation controller which is at the root of window UINavigationController *nc = (UINavigationController *)self.window.rootViewController; // Get home view controller from stack on navigation controller homeViewController *hvc = (homeViewController *)[nc.viewControllers objectAtIndex:0]; hvc.deviceToken = deviceToken;
Ezután adja hozzá a következő módszereket
AppDelegate.m
a kép végpontról való lekéréséhez, és küldjön egy helyi értesítést, amikor a lekérés befejeződött. Ügyeljen arra, hogy a helyőrzőt{backend endpoint}
helyettesítse a háttérvégponttal:NSString *const GetNotificationEndpoint = @"{backend endpoint}/api/notifications"; // Helper: retrieve notification content from backend with rich notification id - (void)retrieveRichImageWithId:(int)richId completion: (void(^)(NSError*)) completion { UINavigationController *nc = (UINavigationController *)self.window.rootViewController; homeViewController *hvc = (homeViewController *)[nc.viewControllers objectAtIndex:0]; NSString* authenticationHeader = hvc.registerClient.authenticationHeader; // Check if authenticated if (!authenticationHeader) return; NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:nil delegateQueue:nil]; NSURL* requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%d", GetNotificationEndpoint, richId]]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:requestURL]; [request setHTTPMethod:@"GET"]; NSString* authorizationHeaderValue = [NSString stringWithFormat:@"Basic %@", authenticationHeader]; [request setValue:authorizationHeaderValue forHTTPHeaderField:@"Authorization"]; NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response; if (!error && httpResponse.statusCode == 200) { // From NSData to UIImage self.imagePayload = [UIImage imageWithData:data]; completion(nil); } else { NSLog(@"Error status: %ld, request: %@", (long)httpResponse.statusCode, error); if (error) completion(error); else { completion([NSError errorWithDomain:@"APICall" code:httpResponse.statusCode userInfo:nil]); } } }]; [dataTask resume]; } // Handle silent push notifications when id is sent from backend - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler { self.userInfo = userInfo; int richId = [[self.userInfo objectForKey:@"richId"] intValue]; NSString* richType = [self.userInfo objectForKey:@"richType"]; // Retrieve image data if ([richType isEqualToString:@"img"]) { [self retrieveRichImageWithId:richId completion:^(NSError* error) { if (!error){ // Send local notification UILocalNotification* localNotification = [[UILocalNotification alloc] init]; // "5" is arbitrary here to give you enough time to quit out of the app and receive push notifications localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:5]; localNotification.userInfo = self.userInfo; localNotification.alertBody = [self.userInfo objectForKey:@"richMessage"]; localNotification.timeZone = [NSTimeZone defaultTimeZone]; // iOS8 categories if (self.iOS8) { localNotification.category = @"richPush"; } [[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; handler(UIBackgroundFetchResultNewData); } else{ handler(UIBackgroundFetchResultFailed); } }]; } // Add "else if" here to handle more types of rich content such as url, sound files, etc. }
Az előző helyi értesítés kezeléséhez nyissa meg a képnézet vezérlőt
AppDelegate.m
a következő módszerekkel:// Helper: redirect users to image view controller - (void)redirectToImageViewWithImage: (UIImage *)img { UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController; UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil]; imageViewController *imgViewController = [mainStoryboard instantiateViewControllerWithIdentifier: @"imageViewController"]; // Pass data/image to image view controller imgViewController.imagePayload = img; // Redirect [navigationController pushViewController:imgViewController animated:YES]; } // Handle local notification sent above in didReceiveRemoteNotification - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { if (application.applicationState == UIApplicationStateActive) { // Show in-app alert with an extra "more" button UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Notification" message:notification.alertBody delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"More", nil]; [alert show]; } // App becomes active from user's tap on notification else { [self redirectToImageViewWithImage:self.imagePayload]; } } // Handle buttons in in-app alerts and redirect with data/image - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { // Handle "more" button if (buttonIndex == 1) { [self redirectToImageViewWithImage:self.imagePayload]; } // Add "else if" here to handle more buttons } // Handle notification setting actions in iOS8 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { // Handle richPush related buttons if ([identifier isEqualToString:@"richPushMore"]) { [self redirectToImageViewWithImage:self.imagePayload]; } completionHandler(); }
Az alkalmazás futtatása
- Az XCode-ban futtassa az alkalmazást egy fizikai iOS-eszközön (a leküldéses értesítések nem fognak működni a szimulátorban).
- Az iOS alkalmazás felhasználói felületén adjon meg egy azonos értékű felhasználónevet és jelszót a hitelesítéshez, majd kattintson a Bejelentkezés gombra.
- Kattintson a Leküldés küldése gombra, és meg kell jelennie egy alkalmazáson belüli riasztásnak. Ha az Egyebek gombra kattint, a rendszer arra a képre viszi, amelyet az alkalmazás háttérrendszerében szerepeltetni szeretne.
- A Leküldés küldése gombra kattintva azonnal lenyomhatja az eszköz kezdőlapját. Néhány pillanat múlva leküldéses értesítést kap. Ha rákoppint, vagy az Egyebek gombra kattint, a rendszer megjeleníti az alkalmazást és a gazdag képtartalmat.