iOS 앱에 푸시 알림 추가

개요

이 자습서에서는 푸시 알림을 iOS 빠른 시작 프로젝트에 추가하여 레코드가 삽입될 때마다 디바이스에 푸시 알림이 전송됩니다.

다운로드한 빠른 시작 서버 프로젝트를 사용하지 않는 경우 푸시 알림 확장 패키지가 필요합니다. 자세한 내용은 Azure Mobile Apps용 .NET 백 엔드 서버 SDK로 작업 가이드를 참조하세요.

iOS 시뮬레이터는 푸시 알림을 지원하지 않습니다. 실제 iOS 디바이스 및 Apple 개발자 프로그램 멤버 자격이 필요합니다.

알림 허브 구성

Azure App Service의 Mobile Apps 기능은 Azure Notification Hubs를 사용하여 푸시를 보내므로 모바일 앱에 대해 알림 허브가 구성됩니다.

  1. Azure Portal에서 App Services로 이동한 다음, 앱 백 엔드를 선택합니다. 설정에서 푸시를 선택합니다.

  2. 앱에 알림 허브 리소스를 추가하려면 연결을 선택합니다. 허브를 만들거나 기존 허브에 연결할 수 있습니다.

    허브 구성

이제 알림 허브를 Mobile Apps 백 엔드 프로젝트에 연결했습니다. 나중에 디바이스에 푸시하는 PNS(플랫폼 알림 시스템)에 연결하도록 이 알림 허브를 구성합니다.

푸시 알림을 위한 앱 등록

  • 앱의 앱 ID를 등록합니다. 명시적 앱 ID(와일드카드 앱 ID 아님)를 만들고 번들 ID의 경우 Xcode 빠른 시작 프로젝트에 있는 정확한 번들 ID를 사용합니다. 푸시 알림 옵션을 선택하는 것도 중요합니다.
  • 다음으로 푸시 알림 구성을 준비하려면, "개발" 또는 "배포" SSL 인증서를 만듭니다.

푸시 알림을 전송하도록 Azure 구성

  1. Mac에서 Keychain Access를 시작합니다. 왼쪽 탐색 모음의 범주 아래에서 내 인증서를 엽니다. 이전 섹션에서 다운로드한 SSL 인증서를 찾은 다음, 해당 콘텐츠를 공개합니다. 인증서만 선택합니다.(프라이빗 키를 선택하지 않습니다.) 그런 다음, 내보내기 합니다.
  2. Azure Portal에서 모두 찾아보기>App Services를 선택합니다. 그런 다음, Mobile Apps 백엔드를 선택합니다.
  3. 설정에서 App Service Push를 선택합니다. 그런 다음, 알림 허브 이름을 선택합니다.
  4. Apple Push Notification Services업로드 인증서로 > 이동합니다. .p12 파일을 업로드하여 올바른 모드 를 선택합니다(이전의 클라이언트 SSL 인증서가 프로덕션 또는 샌드박스인지 여부에 따라 다름). 변경 내용을 저장합니다.

이제 iOS의 푸시 알림과 작동하도록 서비스가 구성되었습니다.

푸시 알림을 전송하도록 백 엔드 업데이트

.NET 백 엔드(C#):

  1. Visual Studio에서 서버 프로젝트를 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리를 클릭한 후 Microsoft.Azure.NotificationHubs를 검색한 다음 설치를 클릭합니다. 백 엔드에서 알림을 보내기 위한 Notification Hubs 라이브러리를 설치합니다.

  2. 백 엔드의 Visual Studio 프로젝트에서 컨트롤러>TodoItemController.cs를 엽니다. 파일 맨 위에 다음 using 문을 추가합니다.

    using Microsoft.Azure.Mobile.Server.Config;
    using Microsoft.Azure.NotificationHubs;
    
  3. PostTodoItem 메서드를 다음 코드로 바꿉니다.

    public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
    {
        TodoItem current = await InsertAsync(item);
        // Get the settings for the server project.
        HttpConfiguration config = this.Configuration;
    
        MobileAppSettingsDictionary settings = 
            this.Configuration.GetMobileAppSettingsProvider().GetMobileAppSettings();
    
        // Get the Notification Hubs credentials for the Mobile App.
        string notificationHubName = settings.NotificationHubName;
        string notificationHubConnection = settings
            .Connections[MobileAppSettingsKeys.NotificationHubConnectionString].ConnectionString;
    
        // Create a new Notification Hub client.
        NotificationHubClient hub = NotificationHubClient
        .CreateClientFromConnectionString(notificationHubConnection, notificationHubName);
    
        // iOS payload
        var appleNotificationPayload = "{\"aps\":{\"alert\":\"" + item.Text + "\"}}";
    
        try
        {
            // Send the push notification and log the results.
            var result = await hub.SendAppleNativeNotificationAsync(appleNotificationPayload);
    
            // Write the success result to the logs.
            config.Services.GetTraceWriter().Info(result.State.ToString());
        }
        catch (System.Exception ex)
        {
            // Write the failure result to the logs.
            config.Services.GetTraceWriter()
                .Error(ex.Message, null, "Push.SendAsync Error");
        }
        return CreatedAtRoute("Tables", new { id = current.Id }, current);
    }
    
  4. 서버 프로젝트를 다시 게시합니다.

Node.js 백 엔드:

  1. 백 엔드 프로젝트를 설정합니다.

  2. todoitem.js 테이블 스크립트를 다음 코드로 바꿉니다.

    var azureMobileApps = require('azure-mobile-apps'),
        promises = require('azure-mobile-apps/src/utilities/promises'),
        logger = require('azure-mobile-apps/src/logger');
    
    var table = azureMobileApps.table();
    
    // When adding record, send a push notification via APNS
    table.insert(function (context) {
        // For details of the Notification Hubs JavaScript SDK, 
        // see https://aka.ms/nodejshubs
        logger.info('Running TodoItem.insert');
    
        // Create a payload that contains the new item Text.
        var payload = "{\"aps\":{\"alert\":\"" + context.item.text + "\"}}";
    
        // Execute the insert; Push as a post-execute action when results are returned as a Promise.
        return context.execute()
            .then(function (results) {
                // Only do the push if configured
                if (context.push) {
                    context.push.apns.send(null, payload, function (error) {
                        if (error) {
                            logger.error('Error while sending push notification: ', error);
                        } else {
                            logger.info('Push notification sent successfully!');
                        }
                    });
                }
                return results;
            })
            .catch(function (error) {
                logger.error('Error while running context.execute: ', error);
            });
    });
    
    module.exports = table;
    
  3. 로컬 컴퓨터에서 파일을 편집할 때 서버 프로젝트를 다시 게시합니다.

앱에 푸시 알림 추가

Objective-C:

  1. QSAppDelegate.m에서 iOS SDK 및 QSTodoService.h를 가져옵니다.

    #import <MicrosoftAzureMobile/MicrosoftAzureMobile.h>
    #import "QSTodoService.h"
    
  2. QSAppDelegate.mdidFinishLaunchingWithOptions에서 return YES; 바로 앞에 다음 줄을 삽입합니다.

    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    
  3. QSAppDelegate.m에서 다음 처리기 메서드를 추가합니다. 이제 푸시 알림을 지원하도록 앱이 업데이트됩니다.

    // Registration with APNs is successful
    - (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    
        QSTodoService *todoService = [QSTodoService defaultService];
        MSClient *client = todoService.client;
    
        [client.push registerDeviceToken:deviceToken completion:^(NSError *error) {
            if (error != nil) {
                NSLog(@"Error registering for notifications: %@", error);
            }
        }];
    }
    
    // Handle any failure to register
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:
    (NSError *)error {
        NSLog(@"Failed to register for remote notifications: %@", error);
    }
    
    // Use userInfo in the payload to display an alert.
    - (void)application:(UIApplication *)application
            didReceiveRemoteNotification:(NSDictionary *)userInfo {
        NSLog(@"%@", userInfo);
    
        NSDictionary *apsPayload = userInfo[@"aps"];
        NSString *alertString = apsPayload[@"alert"];
    
        // Create alert with notification content.
        UIAlertController *alertController = [UIAlertController
                                        alertControllerWithTitle:@"Notification"
                                        message:alertString
                                        preferredStyle:UIAlertControllerStyleAlert];
    
        UIAlertAction *cancelAction = [UIAlertAction
                                        actionWithTitle:NSLocalizedString(@"Cancel", @"Cancel")
                                        style:UIAlertActionStyleCancel
                                        handler:^(UIAlertAction *action)
                                        {
                                            NSLog(@"Cancel");
                                        }];
    
        UIAlertAction *okAction = [UIAlertAction
                                    actionWithTitle:NSLocalizedString(@"OK", @"OK")
                                    style:UIAlertActionStyleDefault
                                    handler:^(UIAlertAction *action)
                                    {
                                        NSLog(@"OK");
                                    }];
    
        [alertController addAction:cancelAction];
        [alertController addAction:okAction];
    
        // Get current view controller.
        UIViewController *currentViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
        while (currentViewController.presentedViewController)
        {
            currentViewController = currentViewController.presentedViewController;
        }
    
        // Display alert.
        [currentViewController presentViewController:alertController animated:YES completion:nil];
    
    }
    

Swift:

  1. 다음과 같은 내용으로 ClientManager.swift 파일을 추가합니다. %AppUrl%을 Azure 모바일 앱 백 엔드의 URL로 바꿉니다.

    class ClientManager {
        static let sharedClient = MSClient(applicationURLString: "%AppUrl%")
    }
    
  2. ToDoTableViewController.swift에서 MSClient를 초기화하는 let client 줄을 다음 줄로 바꿉니다.

    let client = ClientManager.sharedClient
    
  3. In AppDelegate.swift에서 func application의 본문을 다음과 같이 바꿉니다.

    func application(application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        application.registerUserNotificationSettings(
            UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],
                categories: nil))
        application.registerForRemoteNotifications()
        return true
    }
    
  4. AppDelegate.swift에서 다음 처리기 메서드를 추가합니다. 이제 푸시 알림을 지원하도록 앱이 업데이트됩니다.

    func application(application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
        ClientManager.sharedClient.push?.registerDeviceToken(deviceToken) { error in
            print("Error registering for notifications: ", error?.description)
        }
    }
    
    func application(application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: NSError) {
        print("Failed to register for remote notifications: ", error.description)
    }
    
    func application(application: UIApplication,
        didReceiveRemoteNotification userInfo: [NSObject: AnyObject]) {
    
        print(userInfo)
    
        let apsNotification = userInfo["aps"] as? NSDictionary
        let apsString       = apsNotification?["alert"] as? String
    
        let alert = UIAlertController(title: "Alert", message: apsString, preferredStyle: .Alert)
        let okAction = UIAlertAction(title: "OK", style: .Default) { _ in
            print("OK")
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { _ in
            print("Cancel")
        }
    
        alert.addAction(okAction)
        alert.addAction(cancelAction)
    
        var currentViewController = self.window?.rootViewController
        while currentViewController?.presentedViewController != nil {
            currentViewController = currentViewController?.presentedViewController
        }
    
        currentViewController?.presentViewController(alert, animated: true) {}
    
    }
    

테스트 푸시 알림

  • Xcode에서 실행을 눌러 iOS 디바이스에서 해당 앱을 시작합니다(시뮬레이터에서는 푸시가 작동하지 않음). 확인을 클릭하여 푸시 알림을 허용합니다. 이 요청은 처음 앱을 실행할 때 발생합니다.
  • 앱에서 새 항목을 추가하고 +를 클릭합니다.
  • 알림이 수신되었는지 확인한 다음 확인을 클릭하여 알림을 해제합니다. 이제 이 자습서를 성공적으로 완료했습니다.

자세히