Note
최신 샘플 및 라이브러리는 아래 링크를 통해, 다운로드 받을 수 있습니다.
Morpheus Push 는 스마트폰 OS에서 지원하는 PNS(Push Notification Server)를 기반으로 한 메세지 전송 플랫폼이다.
iOS Client 에서는 UPMC WAS 에서 제공하는 Push API 를 각각 버전 규격에 맞춰 연동하여 원할하게 Push Service 를 운영하기 위한 라이브러리를 제공한다.
– Group Sequence Number 의 준말로 User Group의 고유한 Sequence Number
– Push Service ID 의 줄임말
UPMC 3.5 이하 버전
UPMC 3.6 이상 버전
UPMC 4.0 이상 버전
iOS 용 SDK 파일
MPushLibrary.framework
MPushLibrary.bundle
SDK 적용 방법
XCode Project 에 Library 와 설정 파일에 추가
적용시 Project 내 파일이 없는 경우 Copy items if needed 선택
관련 Frameworks 추가
MPush 플러그인 파일
MPush.framework
MPush.bundle
플러그인 적용 방법
mcore.mobile.lic
#Tue Feb 17 09:53:27 KST 2015
application_id=xxx.xxx.xxxx.xxxx
expiration_date=xxxx-xx-xx
mpsn=hZK................X
sn=AhA....E....
New in version 3.8.1 Library
Manifest.xml
<manifest useDirectView="false">
...
<settings>
<push>
<receiver>
<log>y</log>
<version>x.x</version>
<server>http://pushxx.morpheus.co.kr:8080/upmc</server>
</receiver>
</push>
</settings>
...
</manifest>
Key | Type | Description |
---|---|---|
log | String | Push Service 에 대한 Debugging 로그 출력 여부 ( y / n ) |
version | String | UPMC Version ( 3.0, 3.5, 3.6, 3.7, 3.8, 4.0 ) |
server | String | UPMC WAS 서버 URL |
Case #1. Push Notification 관련 UIApplicationDelegate 를 직접 연동
#import <MPushLibrary/PushManager.h>
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[[PushManager defaultManager] application:application
didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[PushManager defaultManager] application:application
didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[[PushManager defaultManager] application:application
didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
[[PushManager defaultManager] application:application
didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[PushManager defaultManager] application:application
didReceiveRemoteNotification:userInfo];
}
/*
// Background 모드에서 호출하는 경우에 사용
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[PushManager defaultManager] application:application
didReceiveRemoteNotification:userInfo
fetchCompletionHandler:completionHandler];
}
*/
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[[PushManager defaultManager] application:application
didRegisterUserNotificationSettings:notificationSettings];
}
Case #2. <MPushLibrary/AppDelegate+PushManager.h> 로 바로 연동
#import <MPushLibrary/PushManager.h>
#import <MPushLibrary/AppDelegate+PushManager.h>
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[[PushManager defaultManager] application:application
didFinishLaunchingWithOptions:launchOptions];
return YES;
}
Case #1 - Push Notification 관련 UIApplicationDelegate 를 직접 연동
#import <MPush/PushManager.h>
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[[PushManager defaultManager] application:application
didFinishLaunchingWithOptions:launchOptions];
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[[PushManager defaultManager] application:application
didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[[PushManager defaultManager] application:application
didFailToRegisterForRemoteNotificationsWithError:error];
}
- (void)application:(UIApplication *)application
didReceiveLocalNotification:(UILocalNotification *)notification {
[[PushManager defaultManager] application:application
didReceiveLocalNotification:notification];
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[PushManager defaultManager] application:application
didReceiveRemoteNotification:userInfo];
}
/*
// Background 모드에서 호출하는 경우에 사용
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[PushManager defaultManager] application:application
didReceiveRemoteNotification:userInfo
fetchCompletionHandler:completionHandler];
}
*/
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[[PushManager defaultManager] application:application
didRegisterUserNotificationSettings:notificationSettings];
}
Case #2 - <MPush/AppDelegate+PushManager.h> 로 바로 연동
#import <MPush/PushManager.h>
#import <MPush/AppDelegate+PushManager.h>
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[[PushManager defaultManager] application:application
didFinishLaunchingWithOptions:launchOptions];
return YES;
}
Changed in version 3.6.4
Arguments
Changed in version 3.6.4
Arguments
Changed in version 3.6.4
Arguments
[[PushManager defaultManager] registerService:(id)activity completionHandler:^(BOOL success) {}];
Changed in version 3.6.4
Arguments
Changed in version 4.0.0
Arguments
Changed in version 3.6.4
Arguments
Changed in version 3.6.4
Arguments
Changed in version 3.6.4
Arguments
Changed in version 3.6.4
Arguments
3.6 Receiver
Arguments
New in version 3.6 UPMC
Arguments
Constant | Description |
---|---|
PushManagerBadgeOptionKeep | 서버에서 관리되는 counting 하나 줄여 count 를 유지시킴 |
PushManagerBadgeOptionReset | 서버에서 관리되는 counting 을 0으로 reset |
PushManagerBadgeOptionUpdate | 서버에서 관리되는 counting 을 특정 count 로 업데이트 |
PushManagerBadgeOptionForce | 서버에서 관리되는 counting 을 Update API 를 통해 특정 count 로 업데이트 |
New in version 4.0EE UPMC
Arguments
Example:
[[PushManager defaultManager]
read:activity notification:userInfo
badgeOption:PushManagerBadgeOptionKeep
completionHandler:^(BOOL success) {
}];
or
[[PushManager defaultManager]
read:activity notification:userInfo
badgeOption:PushManagerBadgeOptionReset
completionHandler:^(BOOL success) {
}];
New in version 4.0EE UPMC
Arguments
Example:
[[PushManager defaultManager]
read:activity
notification:userInfo
badgeOption:PushManagerBadgeOptionUpdate
badge:@(10)
completionHandler:^(BOOL success) {
}];
New in version 4.0EE UPMC
Arguments
Example:
[[PushManager defaultManager]
update:self
badge:@(3)
completionHandler:^(BOOL success) {
}];
Push Message 가 발송된 상태값
Constant | Description |
---|---|
START | Push Message 로 앱을 시작한 경우 |
ACTIVE | Application Forground Status 에서 Push Message 를 받은 경우 |
BACKGROUND | Application Background Status 에서 Push Message 가 전달된 경우 |
Push Message 수신을 대행하는 대리자를 등록
Arguments
Example:
[[PushManager defaultManager] initializeWithDelegate:self];
3.7.4 Library
Arguments
status:(NSString )status messageUID:(NSString)messageUID {}
New in version 3.7.4 Library
Arguments
Example:
- (void)manager:(PushManager *)manager didReceiveUserNotification:(NSDictionary *)userInfo status:(NSString *)status messageUID:(NSString *)messageUID {
PushManager *manager = [PushManager defaultManager];
NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
if ( [apsInfo objectForKey:@"badge"] ) {
NSNumber *badge = [apsInfo objectForKey:@"badge"];
// 뱃지 숫자 변경
manager.notificationCenter.badgeNumber = badge;
// 뱃지 숫자 초기화
manager.notificationCenter.badgeNumber = [NSNumber numberWithInteger:0];
}
// 읽음 확인
[manager read:self notification:notification.userInfo completionHandler:^(BOOL success) {
NSString *message = ( ! success ) ? @"Confirming Read-Message is FAIL !!" : @"Confirming Read-Message is SUCCESS !!";
NSLog( @"%@", message );
}];
// 알림 메세지
NSString *title = [NSString stringWithFormat:@"PUSH (%@)", status];
NSString *message = [apsInfo objectForKey:@"alert"];
if ( NSClassFromString(@"UIAlertController") ) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"취소" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"확인" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
UIViewController *viewController = [[UIApplication sharedApplication] keyWindow].rootViewController;
if ( viewController.presentedViewController ) {
viewController = viewController.presentedViewController;
}
[viewController presentViewController:alert animated:YES completion:^{
}];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"취소" otherButtonTitles:@"확인", nil];
[alert show];
}
}
UPMC 에서 APNS 로 발송되는 Payload JSON 형태
APNS 로 보내지는 JSON dictionary object 에 기본적으로 정의되는 aps 대한 키값 정의
Key | Value Type | Description |
---|---|---|
alert | String | Push Message 내용 |
badge | Number | 앱 아이콘에 Badge 표시, 값이 정의되지 않으면 변경되지 않음 |
sound | String | Library/Sounds 폴더에 있는 파일명을 정의하면 알림시 Sound 와 함께 알림. 값이 정의되지 않으면 default 로 처리 |
APNS 로 보내지는 JSON dictionary object 에 UPMC에서 추가정의되는 mps 대한 키값 정의
Key | Value Type | Description |
---|---|---|
appid | String | 발송 타겟의 Application ID 값 |
sender | String | 발송 주체 ( admin, device-android, device-ios ) |
seqno | Number | DB 처리되고 있는 |
ext | String | 확장 데이타, 보통 JSON String 형태로 전달. 만약 데이타가 대용량(Rich)인 경우 서버에서 데이타를 HTML형태로 생성하여 해당 URL을 전달 |
senddate | String | 발송된 시간 |
messageuniquekey | String | 발송된 메세지의 고유키 |
db_in | String | DB Insert 여부 ("Y" or "N") |
pushkey | String | 발송 대상에 대한 고유 키, 4.0EE 버전에서 출력 |
History:
Example:
{
"aps": {
"alert": "",
"badge": 1,
"sound": "alert.aif"
},
"mps": {
"appid": "com.uracle.push.test",
"seqno": "104",
"sender": "admin",
"senddate": "2016041417",
"db_in": "N",
"ext": "",
"pushkey": "2b9256f6f959240f4dc5ea2f7ed4095ca693884d"
}
}
{
"aps": {
"alert": "",
"badge": 1,
"sound": "alert.aif"
},
"mps": {
"appid": "com.uracle.push.test",
"seqno": "387",
"sender": "admin",
"senddate": "2016041417",
"db_in": "N",
"ext": "http://domain.com:8080/resources/totalInfo/0414172200_msp.html",
"pushkey": "2b9256f6f959240f4dc5ea2f7ed4095ca693884d"
}
}
"1. 인증서가 만료(폐기)되었거나 발급받는 도중에 오류가 있으면, 처음부터 다시 발급받아볼 것"
"2. java apns 라이브러리와 맞는 jdk를 사용 할 것(서버 실행시 java7을 사용하지말고 java6을 사용해볼 것)"
"3. p12 파일을 생성할 때 인증서 1개만 내보내기로 생성할 것"
File -> New -> Target 선택
Notification Service Extention 선택
Product Name을 자유롭게 설정
Activate를 선택하면 Notification Service Extention Target 항목이 추가
추가된 NotificationService.m 파일에 Push 관련 처리
Example:
// NotificationService 쪽에서 메시지 수신시 들어오는 이벤트
//5.1.3 getImageURLFromMPush 추가
//5.0.8 버전부터 사용가능한 PushNotificationServiceExtension에서의 feedback, image Push Sample
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
//Push 메시지 Payload ext영역에서 이미지 url을 가져오는 처리가 필요함
NSString *imageUrl = @"";
if ([self respondsToSelector:@selector(getImageURLFromMPush:)]) {
imageUrl = [self getImageURLFromMPush:self.bestAttemptContent.userInfo];
}
else
{
//MPush 이미지 푸쉬 파싱 샘플, 모피어스 푸쉬가 아니거나 ext 규격이 커스텀 개발될 경우 변경필요
if([self.bestAttemptContent.userInfo objectForKey:@"mps"])
{
NSDictionary *mps = [self.bestAttemptContent.userInfo objectForKey:@"mps"];
NSString *ext = [mps objectForKey:@"ext"];
if(ext && [ext length] > 0)
{
NSArray *arrayExt = [ext componentsSeparatedByString:@"|"];
NSString *flag = [arrayExt objectAtIndex:0];
if([flag isEqualToString:@"0"] || [flag isEqualToString:@"4"] || [flag isEqualToString:@"6"])
{
PushDebug(@"[notificationService] defaultMessageType (0,4,6)");
}
else if([arrayExt count] > 2)
{
imageUrl = [arrayExt objectAtIndex:2];
imageUrl = [[[imageUrl stringByReplacingOccurrencesOfString:@"\n\r" withString:@""] stringByReplacingOccurrencesOfString:@"\n" withString:@""] stringByReplacingOccurrencesOfString:@"\r" withString:@""];
imageUrl = [imageUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}
}
}
}
if([imageUrl length] > 0)
{
//https 이미지 url에서 attachment를 가져오는 API
[self requestAttachmentImage:imageUrl withAttachmentHandler:^(NSError *error, UNNotificationAttachment *attachment) {
if(error)
{
NSLog(@"requestAttachmentImage error %@", [error localizedDescription]);
}
else
{
NSLog(@"requestAttachmentImage %@", attachment);
self.bestAttemptContent.attachments = @[attachment];
}
//PushNotificationServiceExtension 쪽에 수신 확인 (feedback : rcv_register_sent_ack.ctl) 처리
[super didReceiveNotificationRequest:request withContentHandler:contentHandler];
}];
}
else
{
//PushNotificationServiceExtension 쪽에 수신 확인 (feedback : rcv_register_sent_ack.ctl) 처리
[super didReceiveNotificationRequest:request withContentHandler:contentHandler];
}
}
//feedbackEx 관련 샘플
//5.0.8버전부터 PushNotificationServiceExtension 을 상속받아 대체 가능
/*
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
//PushManager 초기화
PushManager *manager = [PushManager defaultManager];
//manager.info 를 변경하기 전에 강제 initialize
[manager initialize];
//수신 받은 메시지
NSMutableDictionary *userInfo = [self.bestAttemptContent.userInfo mutableCopy];
NSDictionary *mps = [userInfo objectForKey:@"mps"];
NSString *psid = [mps objectForKey:@"psid"];
//psid는 feedback API의 필수값
//서버 버전에 따라 psid가 메시지에 담겨오지 않을 경우 키체인 공유등을 사용하여 psid를 가져와서 설정한다.
//https://docs.morpheus.co.kr/client/push/ios.html#mutable-content-ios10
if(psid)
{
//feedback API 호출
//push메시지 객체와 cuid, psid값이 필요 ( cuid는 옵션값으로 필요시 @"" 공백으로 처리 )
[manager feedbackEx:userInfo clientUID:@"" psID:psid completionHandler:^(BOOL success) {
if(success)
{
//앱에서 중복으로 feedback처리를 하지 않도록 메시지 객체에 feedback 정보에 대한 값을 셋팅후 전달
[userInfo setObject:@"true" forKey:@"feedback"];
self.bestAttemptContent.userInfo = userInfo;
self.contentHandler(self.bestAttemptContent);
}
else
{
self.contentHandler(self.bestAttemptContent);
}
}];
}
else
{
self.contentHandler(self.bestAttemptContent);
}
}
*/
- (void)serviceExtensionTimeWillExpire {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
self.contentHandler(self.bestAttemptContent);
}
Manifest.xml
<manifest useDirectView="false">
...
<settings>
<push>
<umpc>
<!-- umpc 서버 정보 -->
<server></server>
<!-- 타임아웃 정보 -->
<timeout>30000</timeout>
</umpc>
</push>
</settings>
...
</manifest>
Arguments
Example:
[[PushManager defaultManager]
updateSession:activity
cuid:[PushManager defaultManager].info.clientUID
completionHandler:^(BOOL success, NSDictionary *body) {
}];
Arguments
Example:
[[PushManager defaultManager]
updatePurchase:activity
id:@"730"
cuid:[PushManager defaultManager].info.clientUID
completionHandler:^(BOOL success, NSDictionary *body) {
}];