IPhone

애플 아이폰 푸시알림 서비스 (APNS, Apple Push Notification Service)

Sunny's 2011. 5. 18. 21:08

출처 :  http://artyst.egloos.com/2652130

1. 내 아이폰에서 개발어플 실행하기 (푸시 서비스를 하기 위해 필수)

http://artyst.egloos.com/2650529

------------------------------------------------------------------------------------------

2. 푸시 서비스등록 및 인증서 다운로드

https://developer.apple.com/iphone/ 에 접속하여 로그인한다.


화면 우측에 iPhone Provisioning Portal 클릭.

App IDs 메뉴에서 등록했던 어플목록을 보자.

Apple Push Notification service 항목에 노란불이 켜져있다. 활성화되지 않은 상태이다.

Action 항목의 Configure 를 클릭.


Development Push SSL Certificate 는 개발 어플용이다.
Production 을 선택하면 테스트는 불가능할 것이다. (배포용 제품어플은 실제 배포했을때만 동작됨)

Development Push SSL Certificate의 Configure 버튼을 누른다.

아래와 같은 화면에서 파일선택을 눌러
#내 아이폰에서 개발어플 실행하기 ( http://artyst.egloos.com/2650529 )의 "1. 인증키 생성" 에서 생성한 인증서 파일을 선택한다.

등록 성공!!!


Continue 버튼을 눌러 다음 화면으로 이동하면 푸시관련 인증서를 다운로드 받을 수 있다.

다운로드 받은 인증서를 더블클릭하여 실행하면 "키체인 접근" 프로그램이 실행되면서 해당 인증서가 추가된다.


예전에 Provisioning Profile 을 다운로드 받아 적용했다면, 위의 과정 이후에 아마도 다시 다운로드 받아서 적용해야할 것이다.


Provisioning 메뉴에서 등록했던 profile 의 Edit 버튼을 눌러 다시 한번 Submit하고 (App IDs 를 잘 확인할것),
Provisioning Profile 을 다운로드 받아 적용하자.
#내 아이폰에서 개발어플 실행하기 ( http://artyst.egloos.com/2650529 )의 과정과 동일함.

@ 추후 푸시 기능이 제대로 작동하지 않는다면 Certificates 메뉴에서 인증서를 다운로드 받아 적용해보자.

------------------------------------------------------------------------------------------

3. 어플(클라이언트) 소스코드
지금부터 소개되는 함수들은 UIApplicationDelegate 에 정의된 함수들이다.
예) @interface 프로젝트명AppDelegate : NSObject <UIApplicationDelegate>
푸시 기능을 사용하기 위해 아래의 상속된 함수들을 overriding 하겠다.

(1)  어플 실행시
푸시알림 서비스를 허용하겠는지 묻고, 해당 장치(아이폰)를 APNS 에 등록

아래의 함수는 [ 프로젝트이름AppDelegate.m ] 파일에 있다.
어플이 시작할때 실행되는 함수인데 //APNS에 장치등록 부분과 //Badge개수설정 을 추가했다.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

[window makeKeyAndVisible];

//APNS  장치 등록

[application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

//Badge 개수 설정

application.applicationIconBadgeNumber = 0;

return YES;

}


최초에 어플이 실행될때만 "푸시알림을 허용할것인지" 묻고, 그 이후에 어플이 실행되어도 다시 묻지 않는다.

위의 함수처럼 코드를 작성했을 경우, 최초에 "허용"을 했다면 매번 APNS 에 장치를 등록하게 된다.

그러므로 따로 함수를 만들어 사용자가 (내 서버에) 로그인할때만 APNS에 등록되도록 코드를 작성하는 편이 좋을 것이다.


UIRemoteNotificationTypeBadge 는 앱스토어 아이콘에 업데이트할 어플의 갯수를 표시하거나

문자가 몇개 왔는지 아이콘에 나타낼때 처럼, 우리가 만든 어플의 아이콘에도 푸시가 올때 표시하겠다는 것.

UIRemoteNotificationTypeSound 는 푸시알림이 왔을때 어떤 소리를 낼지 결정하겠다는 것.

UIRemoteNotificationTypeAlert 은 알림 메시지를 보내겠다는 것.


Badge 갯수 = 0 은 사용자가 어플 아이콘을 눌러 실행할때, 아이콘에 표시되었던 Badge갯수를 초기화 하려고 한다.


(2) APNS 에 장치 등록시

APNS에 장치를 등록하는 코드가 실행되면 APNS 에 등록요청하며 성공/실패 여부를 알려준다.

성공/실패 여부에 따라 아래의 2가지 함수가 자동호출된다.


//push : APNS  장치 등록 성공시 자동실행

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

NSLog(@"deviceToken : %@", deviceToken);


/*

 여기에 당신의 서버와 통신하는 부분을 만들것.

 푸시를 누구에게 보낼지를 결정하는 것이 바로 deviceToken 값이다.

 내가 운영할 서버에 deviceToken  보내서 보관하자.

 */

}


//push : APNS  장치 등록 오류시 자동실행

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

NSLog(@"deviceToken error : %@", error);

}


성공시 deviceToken를 문자열로 보내준다.

NSLog 를 이용해 출력해보면 아이폰(장치)의 식별토큰을 알수있다.

테스트 해봐야하니 복사해서 보관해놓자.


아래와 같은 xcode 화면에서 "Build and Run" 을 눌러 아이폰에서 실행시키고

필자가 분홍색 동그라미로 강조해놓은 부분을 눌러 출력되는 로그를 보자.

녹색 네모로 강조해놓은 부분에 출력된 것을 볼 수 있다. 복사해놓자.



만약 code 3000 에러가 발생하면 인증서 문제이므로,

애플-개발자-사이트에서 프로젝트 관련 모든 인증서를 새로 다운로드 받아 적용해보자.


(3) 어플 실행중일때 알림 도착

이때는 알림 확인창이 뜬다거나 소리가 나지 않을것이다. 대신 아래의 함수가 실행되므로 알맞게 처리하면 되겠다.


//push : 어플 실행중에 알림도착

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

NSDictionary *aps = [userInfo valueForKey:@"aps"];

NSLog(@"userInfo Alert : %@", [aps valueForKey:@"alert"]);

}


------------------------------------------------------------------------------------------


4. 운영서버 설정하기


(1) APNS 와 보안통신 할때 사용할 인증서 추출


응용프로그램 > 유틸리티 > 키체인접근 을 실행.


아래의 화면과 같이 "Apple Development Push Services"와 거기에 포함되어 있는

"개인키"까지 2개를 한꺼번에 선택하고 "2개 항복 보내기"(Export 2 items...)를 한다. 

(인증서와 개인키를 하나의 p12 파일로 만든다)

화면 왼쪽의 키체인항목에서 "로그인" 선택. 카테고리항목에서 "인증서" 선택해야 포함된 개인키가 보인다.




파일포멧은 p12 로 선택하고, 디스크에 저장한다.


디스크에 저장할 인증서의 암호를 설정한다. 암호를 지정하고 기억해두자.


맥OS 로그인 암호를 입력하여 내보내기를 허용한다.



(2) 서버 소스코드


개발환경 : 자바(JAVA)

@ PHP 나 Objective C 는 다루는 곳이 많으므로 자바(JAVA) 로만 작성하도록 하겠다.


APNS 와 통신하려면 먼저 java에서 편리하게 이용할 수 있는 라이브러리를 다운로드 받자. http://code.google.com/p/javapns/ 에서 jar 파일을 다운로드 받을 수 있다.



그런데 이 API를 사용하기 위해서 필요한 라이브러리가 있다.


commons-lang-x.x.jar 가 없다면 org.apache.commons.lang.StringUtils 를 찾을 수 없다며 에러가 발생한다.

bcprov-ext-jdk16-xxx.jar 가 없다면 암호화관련 에러가 발생한다.


http://commons.apache.org/lang/ => apache

http://www.bouncycastle.org/ => 암호화 모듈


위의 사이트에서 각각 다운로드 받을 수 있다.


이제 서버에서 APNS로 메시지를 발송하는 JAVA 서버 프로바이저를 작성해보자.

deviceToken 에는 아이폰 클라이언트 어플에서 APNS 에 등록하고 나서 받은 토큰값을 넣어주자.

certificatePath 에는 인증서 경로와 파일명을 넣어주고, password에는 인증서를 추출할때 입력한 암호를 넣자.


import javapns.back.PushNotificationManager;

import javapns.back.SSLConnectionHelper;

import javapns.data.Device;

import javapns.data.PayLoad;


public class ApnsManager {

  public void provider() throws Exception {

    try {

      String deviceToken = "6a4aa1981062d0b8bxxbbaa3b6b0fdc275exyyx0f5dcac1ce101d314acca1a35";


      PayLoad payLoad = new PayLoad();

      payLoad.addAlert("알림 메시지 테스트");

      payLoad.addBadge(1);

      payLoad.addSound("default");

      PushNotificationManager pushManager = PushNotificationManager.getInstance();

      pushManager.addDevice("iPhone", deviceToken);

      //Connect to APNs

      String host = "gateway.sandbox.push.apple.com";

      int port = 2195;

      String certificatePath = "/work/project/apple-apns-key.p12";

      String certificatePassword = "인증서암호";

      pushManager.initializeConnection(host, port, certificatePath, certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);

      //Send Push

      Device client = pushManager.getDevice("iPhone");

      pushManager.sendNotification(client, payLoad);

      pushManager.stopConnection();


      pushManager.removeDevice("iPhone");

    }

    catch (Exception e) {

      e.printStackTrace(); 

    }

}



혹시 푸시알림을 제대로 받지 못했다면 아이폰의 설정을 살펴보자.



~ 끝 ~