Azure Notification Hubs 다양한 푸시Azure Notification Hubs Rich Push

개요Overview

사용자에게 즉각적인 풍부한 콘텐츠를 제공하기 위해 애플리케이션은 일반 텍스트 이상을 푸시할 수 있습니다.In order to engage users with instant rich contents, an application might want to push beyond plain text. 이러한 알림은 사용자 상호 작용을 촉진 하 고 Url, 소리, 이미지/쿠폰 등의 콘텐츠를 제공 합니다.These notifications promote user interactions and present content such as URLs, sounds, images/coupons, and more. 이 자습서는 사용자에 게 알림 자습서를 기반으로 하며, 페이로드 (예: 이미지)를 통합 하는 푸시 알림을 보내는 방법을 보여 줍니다.This tutorial builds on the Notify Users tutorial, and shows how to send push notifications that incorporate payloads (for example, images).

이 자습서는 iOS 7 및 8과 호환 됩니다.This tutorial is compatible with iOS 7 and 8.

3 개의 스크린샷: 푸시 단추가 있는 앱 화면, 장치의 시작 화면 및 뒤로 단추가 있는 Windows 로고

개요:At a high level:

  1. 앱 백 엔드:The app backend:
    • 백 엔드 데이터베이스/로컬 저장소에 리치 페이로드 (이 경우 이미지)를 저장 합니다.Stores the rich payload (in this case, image) in the backend database/local storage.
    • 이 풍부한 알림의 ID를 장치에 보냅니다.Sends ID of this rich notification to the device.
  2. 디바이스의 앱:App on the device:
    • 받은 ID를 사용 하 여 리치 페이로드를 요청 하는 백 엔드에 연결 합니다.Contacts the backend requesting the rich payload with the ID it receives.
    • 데이터 검색이 완료 되 면 장치에 사용자 알림을 보내고 사용자가 더 자세히 알아보려면 사용자가 탭 할 때 페이로드를 즉시 표시 합니다.Sends users notifications on the device when data retrieval is complete, and shows the payload immediately when users tap to learn more.

WebAPI 프로젝트WebAPI project

  1. Visual Studio에서 사용자에게 알림 자습서에서 만든 AppBackend 프로젝트를 엽니다.In Visual Studio, open the AppBackend project that you created in the Notify Users tutorial.

  2. 사용자에게 알릴 이미지를 얻어 프로젝트 디렉터리의 img 폴더에 배치합니다.Obtain an image you would like to notify users with, and put it in an img folder in your project directory.

  3. 솔루션 탐색기에서 모든 파일 표시를 클릭하고 프로젝트에 포함할 폴더를 마우스 오른쪽 단추로 클릭합니다.Click Show All Files in the Solution Explorer, and right-click the folder to Include In Project.

  4. 이미지를 선택한 상태에서 속성 창의 빌드 작업포함 리소스로 변경 합니다.With the image selected, change its Build Action in the Properties window to Embedded Resource.

    솔루션 탐색기의 스크린샷

  5. 에서 Notifications.cs 다음 문을 추가 합니다 using .In Notifications.cs, add the following using statement:

    using System.Reflection;
    
  6. Notifications 클래스를 다음 코드로 바꿉니다.Replace the Notifications class with the following code. 자리 표시자를 알림 허브 자격 증명 및 이미지 파일 이름으로 바꾸어야 합니다.Be sure to replace the placeholders with your notification hub credentials and image file name:

    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}");
        }
    }
    
  7. 에서 NotificationsController.cs NotificationsController 다음 코드를 사용 하 여를 재정의 합니다.In NotificationsController.cs, redefine NotificationsController with the following code. 그러면 장치에 초기 자동 서식 알림 ID를 보내고 이미지를 클라이언트 쪽에서 검색할 수 있습니다.This sends an initial silent rich notification ID to the device and allows client-side retrieval of the image:

    // 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);
    }
    
  8. 이제 모든 장치에서 액세스할 수 있도록 Azure 웹 사이트에이 앱을 다시 배포 합니다.Now, re-deploy this app to an Azure Website in order to make it accessible from all devices. AppBackend 프로젝트를 마우스 오른쪽 단추로 클릭하고 게시를 선택합니다.Right-click on the AppBackend project and select Publish.

  9. 게시 대상으로 Azure 웹 사이트 를 선택 합니다.Select Azure Website as your publish target. Azure 계정으로 로그인 하 고 기존 또는 새 웹 사이트를 선택 하 고 연결 탭에서 대상 URL 속성을 기록 합니다. 이 자습서의 뒷부분에서이 URL을 백 엔드 끝점 으로 참조 합니다.Sign in with your Azure account and select an existing or new Website, and make a note of the destination URL property in the Connection tab. We refer to this URL as your backend endpoint later in this tutorial. 게시를 선택합니다.Select Publish.

iOS 프로젝트 수정Modify the iOS project

알림의 id 만 보내도록 앱 백 엔드를 수정 했으므로 해당 id를 처리 하도록 iOS 앱을 변경 하 고 백 엔드에서 다양 한 메시지를 검색 합니다.Now that you've modified your app backend to send just the ID of a notification, change your iOS app to handle that ID, and retrieve the rich message from your backend:

  1. iOS 프로젝트를 열고 대상 섹션에서 기본 앱 대상으로 이동하여 원격 알림을 사용하도록 설정합니다.Open your iOS project, and enable remote notifications by going to your main app target in the Targets section.

  2. 기능을 선택 하 고, 백그라운드 모드를 사용 하도록 설정 하 고, 원격 알림 확인란을 선택 합니다.Select Capabilities, enable Background Modes, and check the Remote Notifications checkbox.

    기능 화면을 표시 하는 iOS 프로젝트의 스크린샷

  3. Main.storyboard을 열고 사용자 알림 자습서에서 보기 컨트롤러 (이 자습서에서는 홈 보기 컨트롤러 라고 함)가 있는지 확인 합니다.Open Main.storyboard, and make sure you have a View Controller (referred to as Home View Controller in this tutorial) from the Notify User tutorial.

  4. 탐색 컨트롤러 를 스토리 보드에 추가 하 고 홈 보기 컨트롤러를 컨트롤을 끌어 탐색의 루트 뷰로 만듭니다.Add a Navigation Controller to your storyboard, and control-drag the Home View Controller to make it the root view of navigation. 탐색 컨트롤러에 대해서만 특성 검사자의 초기 뷰 컨트롤러 가 선택 되어 있는지 확인 합니다.Make sure the Is Initial View Controller in the Attributes inspector is selected for the Navigation Controller only.

  5. 뷰 컨트롤러 를 스토리 보드에 추가 하 고 이미지 뷰를 추가 합니다.Add a View Controller to the storyboard and add an Image View. 이 페이지는 사용자가 자세한 내용을 보기 위해 알림을 클릭하면 표시되는 페이지입니다.This is the page users will see once they choose to learn more by clicking on the notification. 스토리보드는 다음과 같이 표시됩니다.Your storyboard should look as follows:

    스토리 보드의 스크린샷

  6. 스토리 보드에서 홈 보기 컨트롤러 를 클릭 하 고 id 검사기 아래에 해당 사용자 지정 클래스스토리 보드 IDhomeViewController 있는지 확인 합니다.Click on the Home View Controller in the storyboard, and make sure it has homeViewController as its Custom Class and Storyboard ID under the Identity inspector.

  7. 이미지 뷰 컨트롤러에 대해 Imageviewcontroller와 동일한 작업을 수행 합니다.Do the same for the Image View Controller, as imageViewController.

  8. 그런 다음, 방금 만든 UI를 처리 하기 위해 Imageviewcontroller 라는 새 뷰 컨트롤러 클래스를 만듭니다.Then, create a new View Controller class called imageViewController to handle the UI you just created.

  9. Imageviewcontroller .h에서 컨트롤러의 인터페이스 선언에 다음 코드를 추가 합니다.In imageViewController.h, add the following code to the controller's interface declarations. 스토리보드 이미지 보기에서 Ctrl 키를 누른 상태에서 이러한 속성으로 끌어 다음 두 항목을 연결해야 합니다.Make sure to control-drag from the storyboard image view to these properties to link the two:

    @property (weak, nonatomic) IBOutlet UIImageView *myImage;
    @property (strong) UIImage* imagePayload;
    
  10. imageViewController.m에서 다음을 viewDidload 마지막에 추가합니다.In imageViewController.m, add the following at the end of viewDidload:

    // Display the UI Image in UI Image View
    [self.myImage setImage:self.imagePayload];
    
  11. AppDelegate.m에서 사용자가 만든 이미지 컨트롤러를 가져옵니다.In AppDelegate.m, import the image controller you created:

    #import "imageViewController.h"
    
  12. 다음 선언을 포함하여 인터페이스 섹션을 추가합니다.Add an interface section with the following declaration:

    @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
    
  13. AppDelegate에서 앱이 application: didFinishLaunchingWithOptions에서 자동 알림을 등록하는지 확인합니다.In AppDelegate, make sure your app registers for silent notifications in application: 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;
    
  14. 에 대 한 다음 구현을 대체 application:didRegisterForRemoteNotificationsWithDeviceToken 하 여 스토리 보드 UI 변경 내용을 고려 합니다.Substitute the following implementation for application:didRegisterForRemoteNotificationsWithDeviceToken to take the storyboard UI changes into account:

    // 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;
    
  15. 그런 다음, AppDelegate.m에 다음 메서드를 추가하여 엔드포인트에서 이미지를 검색하고 검색이 완료되면 로컬 알림을 보냅니다.Then, add the following methods to AppDelegate.m to retrieve the image from your endpoint and send a local notification when retrieval is complete. 자리 표시자 {backend endpoint} 를 해당 백 엔드 엔드포인트로 대체해야 합니다.Make sure to substitute the placeholder {backend endpoint} with your backend endpoint:

    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.
    }
    
  16. 에서 다음 메서드를 사용 하 여 이미지 뷰 컨트롤러를 열어 이전 로컬 알림을 처리 합니다 AppDelegate.m .Handle the previous local notification by opening the image view controller in AppDelegate.m with the following methods:

    // 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();
    }
    

애플리케이션 실행Run the Application

  1. XCode에서는 실제 iOS 디바이스에서 앱을 실행합니다(푸시 알림은 시뮬레이터에서 작동하지 않음).In XCode, run the app on a physical iOS device (push notifications will not work in the simulator).
  2. iOS 앱 UI에서 인증에 대해 동일한 값의 사용자 이름과 암호를 입력하고 로그인을 클릭합니다.In the iOS app UI, enter a username and password of the same value for authentication and click Log In.
  3. 푸시 보내기 를 클릭하면 앱 내 경고가 표시됩니다.Click Send push and you should see an in-app alert. 더 보기를 클릭하면 앱 백 엔드에 포함되도록 선택한 이미지가 표시됩니다.If you click on More, you will be brought to the image you chose to include in your app backend.
  4. 푸시 보내기를 클릭하고 즉시 디바이스의 홈 단추를 누를 수도 있습니다.You can also click Send push and immediately press the home button of your device. 곧 푸시 알림을 받게 됩니다.In a few moments, you will receive a push notification. 푸시 알림을 탭하거나 More를 클릭하면 앱과 풍부한 이미지 콘텐츠가 표시됩니다.If you tap on it or click More, you will be brought to your app and the rich image content.