Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Översikt
För att engagera användare med omedelbart omfattande innehåll kanske ett program vill skicka mer än oformaterad text. Dessa meddelanden främjar användarinteraktioner och presenterar innehåll som URL:er, ljud, bilder/kuponger med mera. Den här självstudien bygger på självstudien Meddela användare och visar hur du skickar push-meddelanden som innehåller nyttolaster (till exempel bilder).
Den här självstudien är kompatibel med iOS 7 och 8.
På hög nivå:
- Appens serverdel:
- Lagrar den omfattande nyttolasten (i det här fallet avbildningen) i serverdelsdatabasen/den lokala lagringen.
- Skickar ID för det här omfattande meddelandet till enheten.
- App på enheten:
- Kontaktar serverdelen och begär den omfattande nyttolasten med det ID som den tar emot.
- Skickar meddelanden till användarna på enheten när datahämtningen är klar och visar nyttolasten direkt när användarna trycker för att lära sig mer.
WebAPI-projekt
I Visual Studio öppnar du det AppBackend-projekt som du skapade i självstudien Meddela användare .
Hämta en avbildning som du vill meddela användarna med och placera den i en img-mapp i projektkatalogen.
Klicka på Visa alla filer i Solution Explorer och högerklicka på mappen som ska inkluderas i projektet.
När avbildningen är markerad ändrar du dess byggåtgärd i fönstret Egenskaper till Inbäddad resurs.
I
Notifications.cs
lägger du till följandeusing
instruktion:using System.Reflection;
Notifications
Ersätt klassen med följande kod. Se till att ersätta platshållarna med dina autentiseringsuppgifter för meddelandehubben och bildfilens namn: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}"); } }
I
NotificationsController.cs
omdefinierar duNotificationsController
med följande kod. Detta skickar ett första tyst rikt notifikations-ID till enheten och tillåter hämtning av bilden på klientsidan.// 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); }
Distribuera nu om den här appen till en Azure-webbplats för att göra den tillgänglig från alla enheter. Högerklicka på AppBackend-projektet och välj Publicera.
Välj Azure-webbplats som publiceringsmål. Logga in med ditt Azure-konto och välj en befintlig eller ny webbplats och anteckna mål-URL-egenskapen på fliken Anslutning . Vi refererar till den här URL:en som din serverdelsslutpunkt senare i den här självstudien. Välj Publicera.
Ändra iOS-projektet
Nu när du har ändrat appens serverdel så att den bara skickar ID :t för ett meddelande ändrar du iOS-appen för att hantera det ID:t och hämtar det omfattande meddelandet från serverdelen:
Öppna ditt iOS-projekt och aktivera fjärrmeddelanden genom att gå till huvudappens mål i avsnittet Mål .
Välj Funktioner, aktivera bakgrundslägen och markera kryssrutan Fjärrmeddelanden .
Öppna
Main.storyboard
, och se till att du har en View Controller (kallas Home View Controller i den här handledningen) från handledningen Meddela användare.Lägg till en navigeringsstyrenhet i din storyboard och styr-dra startvisningsstyrenheten för att göra den till rotvyn för navigering. Kontrollera att Är initial vykontrollant i attributinspektören är markerad för endast navigeringskontrollanten.
Lägg till en vykontrollant i storyboarden och lägg till en bildvy. Det här är sidan som användarna ser när de väljer att lära sig mer genom att klicka på meddelandet. Din storyboard bör se ut så här:
Klicka på Styrenheten för hemvy i storyboarden och se till att den har homeViewController som anpassat klass - och Storyboard-ID under identitetskontrollen.
Gör samma sak för bildvisningsstyrenheten som imageViewController.
Skapa sedan en ny View Controller-klass med namnet imageViewController för att hantera användargränssnittet som du nyss skapade.
Lägg till följande kod i kontrollantens gränssnittsdeklarationer i imageViewController.h. Se till att dra från storyboardens bildvy till dessa egenskaper för att länka de två.
@property (weak, nonatomic) IBOutlet UIImageView *myImage; @property (strong) UIImage* imagePayload;
I
imageViewController.m
lägger du till följande i slutet avviewDidload
:// Display the UI Image in UI Image View [self.myImage setImage:self.imagePayload];
I
AppDelegate.m
importerar du den avbildningskontrollant som du skapade:#import "imageViewController.h"
Lägg till ett gränssnittsavsnitt med följande deklaration:
@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
I
AppDelegate
kontrollerar du att appen registrerar sig för tysta meddelanden iapplication: 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;
Ersätt följande implementering för
application:didRegisterForRemoteNotificationsWithDeviceToken
att ta hänsyn till ändringar i användargränssnittet för storyboard:// 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;
Lägg sedan till följande metoder för att
AppDelegate.m
hämta avbildningen från slutpunkten och skicka ett lokalt meddelande när hämtningen är klar. Se till att ersätta platshållaren{backend endpoint}
med din serverdelsslutpunkt: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. }
Hantera det föregående lokala meddelandet genom att öppna bildvisningskontrollern i
AppDelegate.m
med följande metoder:// 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(); }
Kör programmet
- I XCode kör du appen på en fysisk iOS-enhet (push-meddelanden fungerar inte i simulatorn).
- I användargränssnittet för iOS-appen anger du ett användarnamn och lösenord med samma värde för autentisering och klickar på Logga in.
- Klicka på Skicka push så bör du se en avisering i appen. Om du klickar på Mer kommer du till den bild som du valde att inkludera i din app-serverdel.
- Du kan också klicka på Skicka push-överföring och omedelbart trycka på hemknappen på enheten. Om en liten stund får du ett push-meddelande. Om du trycker på den eller klickar på Mer kommer du till din app och det omfattande bildinnehållet.