애플 아이폰 푸시알림 서비스 (APNS, Apple Push Notification Service)
출처 : http://artyst.egloos.com/2652130
1. 내 아이폰에서 개발어플 실행하기 (푸시 서비스를 하기 위해 필수)







- (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();
}
}
혹시 푸시알림을 제대로 받지 못했다면 아이폰의 설정을 살펴보자.

~ 끝 ~