Warning
이 방식은 안드로이드 8.0이상 부터, BACKGROUND SERVICE 제약으로, 더 이상 지원이 불가능하니다. 아래 링크를 참고해서, 새로운 버전으로 적용하시기 바랍니다.
Morpheus Push 는 스마트폰 OS에서 지원하는 PNS(Push Notification Server)를 기반으로 한 메세지 전송 플랫폼이다.
Android Client 에서는 UPMC WAS 에서 제공하는 Push API 를 각각 버전 규격에 맞춰 연동하여 원할하게 Push Service 를 운영하기 위한 라이브러리를 제공한다.
– GCM 서비스 등록을 위한 ID
UPMC 3.6 이상 버전
initPushService => Service 등록 (자동으로 PSID 요청) => User 등록 => 메시지 수신
Android 용 SDK 파일
MPushLibrary
mcore.mobile.lic
– Push 라이센스 정보가 담긴 Push 라이센스 파일
Manifest.xml
– Push 구동을 위한 설정 파일
SDK 적용 방법
Android Project 의 libs 폴더에 Library 파일에 추가
Android Project의 assets/res 폴더에 라이선스 및 설정 파일 추가
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
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<push>
<receiver> <!-- UPMC 설정 정보 -->
<log>y</log>
<!-- UPMC 서버 버전 4.0/4.1/5.0/5.1 등 -->
<version>5.0</version>
<!-- key 교환 방식 암호화 : 라이선스 발급시 요청 (hexa코드 16자리) 서버 3.8.1 이상 -->
<security-indexes>0x??? 0x??? 0x??? </security-indexes>
<!-- UPMC 서버 url(필수 설정) -->
<server>http://pushxx.morpheus.co.kr:18080/</server>
<timeout>20000</timeout>
<!-- FCM설정 -->
<!-- FCM sender-id (push-type이 GCM일경우 필수설정, sender id가 여러개인 경우, 공백없이 ","로 구분하여 등록한다. ) -->
<gcm-sender-id>xxxxxxxxxxxx,bbbbbbbbbbb</gcm-sender-id>
<!-- 푸쉬타입(필수설정)
ALL:유라클UPNS(+FCM dummy)
-->
<android-push-type>ALL</android-push-type>
<!-- 서비스 정책 ,
user : one user multidevice,
device : one user one device,
default : user -->
<policy>device</policy>
<!-- stb(셋탑)/mobile(모바일)/mobile_old(디바이스 아이디 이전 버전) -->
<device-type>mobile</device-type>
<!-- upmc 연동시 휴대폰 번호 사용 여부 -->
<use-phone_number>n</use-phone_number>
<!-- 브로드캐스트 리시버에서 퍼미션 사용 여부를 설정 (Y/N) -->
<use-permission>Y</use-permission>
</receiver>
<upns>
<!-- agent, inapp -->
<agent-service-type>inapp</agent-service-type>
<!-- UPNS RESTART ALARM INTERVAL (초단위) -->
<agent-restart-interval>60</agent-restart-interval>
<!-- auto/manual -->
<agent-receive-confirm>auto</agent-receive-confirm>
<!-- reconnect interval (초단위) - 최소 10초 이상(서버에 대한 부하 고려하여 설정 - 기본값 10초) -->
<reconnect-interval>10</reconnect-interval>
<!-- reconnect interval (초단위) - 최소 10초 이상 (재접속 카운트에 따라 설정, 3회 이후 다시 최초 설정 간격으로 반복)-->
<reconnect-interval>10,20,30</reconnect-interval>
<!-- reallocate interval (v4.1 이상 - 다른 버전 무시) - 최소 10 이상 -->
<!-- 단위: , 1~reallocate-interval 사이의 랜덤한 시간간격으로 호출 요청 (60 이상 권장, 재할당 카운트에 따라 설정, 3회 이후 다시 최초 설정 간격으로 반복) -->
<reallocate-interval>10,30,50</reallocate-interval>
<!-- 사용자 등록 시 재시도 여부 auto / 횟수 (integer) -->
<retry-regist-count>auto</retry-regist-count>
</upns>
</push>
</settings>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="[패키지명]"
android:versionCode="1"
android:versionName="1.0">
<!-- 라이브러리 버전 4.1.0.7 이상부터 추가된 리시버 등록 시 권한 등록위해 선언 (없으면 앱 디폴트 권한) -->
<permission android:name="${applicationId}.permission.MPUSH_PERMISSION" android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.MPUSH_PERMISSION" />
<!-- upns push service&receiver -->
<service android:name="m.client.push.library.service.UPNSService" android:exported="true" />
<receiver android:name="m.client.push.library.receiver.ServiceHandleReceiver">
<intent-filter>
<action android:name="${applicationId}.START_PUSHSERVICE" />
<action android:name="${applicationId}.STOP_PUSHSERVICE" />
<action android:name="${applicationId}.RESTART_PUSHSERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.SCREEN_OFF" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
<receiver android:name="m.client.push.library.receiver.UpnsActionReceiver">
<intent-filter>
<action android:name="${applicationId}.ACTION_UPNS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- push service&receiver -->
<service android:name="m.client.push.library.service.GCMIntentService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- Internal (not exported) receiver used by the app to start its own exported services
without risk of being spoofed. -->
<!-- FirebaseInstanceIdService performs security checks at runtime,
no need for explicit permissions despite exported="true" -->
<service android:name="m.client.push.library.service.GCMInstanceIDListenerService" android:exported="true">
<intent-filter >
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<receiver android:name="[패키지명].receiver.MessageArrivedReceiver">
<intent-filter>
<action android:name="${applicationId}.GCM_MESSAGE_ARRIVED" />
<action android:name="${applicationId}.UPNS_MESSAGE_ARRIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="[패키지명].receiver.PushActionReceiver">
<intent-filter>
<action android:name="${applicationId}.ACTION_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="m.client.push.library.receiver.GcmActionReceiver">
<intent-filter>
<action android:name="${applicationId}.ACTION_GCM" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
Warning
- UPNSService: UPNS 푸시를 수신하기 위한 중요한 역할을 하므로 반드시 추가되어야 한다.
- ServiceHandleReceiver: 라이브러리 내에 존재하는 리시버로 서비스의 생명 주기를 담당하는 리시버이다.
- MessageArrivedReceiver: 서버로부터 메시지를 수신하는 리시버로 데이터 수신 시 화면에 보여줄 방법을 정의하여 사용한다.
- UPNSActionReceiver: 라이브러리 내에 존재하는 리시버로 UPNS 기능에 대한 요청을 받아서 처리한다
Warning
- Public Push 로 제공되는 안드로이드 FCM 에 대한 설정은 기본적으로 안드로이드에서 제공되는 설정 가이드와 다르지 않으며 다만 패키지 명을 주의하여 설정해야 한다.
- Sample
buildscript {
repositories {
google()
jcenter()
}<br/>
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.google.gms:google-services:3.1.0'
// NOTE: Do not place your application dependencies here; they belong<br/>
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
google-service.json 다운로드 :
https://support.google.com/firebase/answer/7015592
https://console.firebase.google.com/u/0/
implementation ('com.google.firebase:firebase-messaging:15.0.2')
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.android.application'
repositories {
maven { url 'https://maven.google.com' }
}
android {
compileSdkVersion 23
buildToolsVersion "26.0.2"
defaultConfig {
applicationId "kr.co.pushdemo"
minSdkVersion 14
targetSdkVersion 23
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
implementation files('libs/*.jar')
implementation ('com.google.firebase:firebase-messaging:15.0.2')
//jar 버전이 포함되지 않은 경우
implementation 'com.google.code.gson:gson:1.7.1'
}
apply plugin: 'com.google.gms.google-services'
Warning
아래와 같이 Error가 발생하는 경우, dependencies 속성이 Gradle 버전과 맞지 않기 때문이므로, implementation 을 compile 로 변경한다.
Error : A problem occurred evaluating project ':app'. > Could not find method implementation() for arguments
-- Push service 등록
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//앱 실행시마다 호출 (4.0이상)
PushManager.getInstance().registerServiceAndUser(Context context, String cuid, String cname);
...
}
-- Push 플러그인 : http://docs.morpheus.co.kr/client/api/plugin-push.html
Arguments
Arguments
Key | Type | Description |
---|---|---|
PushConstants.KEY_CNAME | String | 사용자 닉네임 |
PushConstants.KEY_STB_ID | String | 셋탑 아이디 |
PushConstants.KEY_DEVICE_ID | String | 디바이스id |
PushConstants.KEY_CUSTOM_RECEIVER_SERVER_URL | String | UPMC url |
PushConstants.KEY_CUSTOM_UPNS_SERVER_URL | String | UPNS url |
- 예시 :
JSONObject params = new JSONObject();
// http://xxx.xxx.x.xx:xxxx 연결할 리시버 서버 url
params.put(PushConstants.KEY_CUSTOM_RECEIVER_SERVER_URL, "http://xxx.xxx.x.xx:xxxx");
// tcp://xxx.xxx.x.xx:xxxx 연결할 UPNS 서버 url
params.put(PushConstants.KEY_CUSTOM_UPNS_SERVER_URL, "tcp://xxx.xxx.x.xx:xxxx");
Arguments
Arguments
Key | Type | Description |
---|---|---|
PushConstants.KEY_DEVICE_ID | String | 디바이스id |
PushConstants.KEY_CUSTOM_RECEIVER_SERVER_URL | String | UPMC url |
PushConstants.KEY_CUSTOM_UPNS_SERVER_URL | String | UPNS url |
- 예시 :
JSONObject params = new JSONObject();
params.put(PushConstants.KEY_STB_ID, "{A73E9E2E-9C6B-11E4-AFAE-C55006B96D3C}");
params.put(PushConstants.KEY_DEVICE_ID, "DEVICE-A73E9E2E9C6B11E4AFAEC55006B96D3C"/*생성하여 추가 요망*/);
params.put(PushConstants.KEY_CNAME, "GUEST-A73E9E2E9C6B11E4AFAEC55006B96D3C");
Arguments
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
Key | Type | Necessary | Description |
---|---|---|---|
PushConstants.KEY_CUID | String | 필수 | Client ID |
PushConstants.KEY_CNAME | String | 필수 | Client Name |
PushConstants.KEY_STB_ID | String | 선택 | STB ID |
PushConstants.KEY_DEVICE_ID | String | 선택 | Device ID |
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
Key | Type | Necessary | Description |
---|---|---|---|
PushConstants.KEY_CUID | String | 필수 | Client ID |
PushConstants.KEY_CNAME | String | 필수 | Client Name |
PushConstants.KEY_STB_ID | String | 선택 | STB ID |
PushConstants.KEY_DEVICE_ID | String | 선택 | Device ID |
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
Key | Type | Necessary | Description |
---|---|---|---|
PushConstants.KEY_EDIT_PUSH_TYPE | String | 필수 | Push Type |
-결과값 : Reciver 를 통해, 처리 결과 통보
- 예시 :
JSONObject params = new JSONObject();
params.put(PushConstants.KEY_EDIT_PUSH_TYPE, PushConstants.STR_UPNS_PUSH_TYPE);
Arguments
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
Key | Type | Necessary | Description |
---|---|---|---|
PushConstants.KEY_CUID | String | 필수 | Client ID |
PushConstants.KEY_CNAME | String | 필수 | Client Name |
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
-결과값 : Reciver 를 통해, 처리 결과 통보
Arguments
Key | Type | Necessary | Description |
---|---|---|---|
PushConstants.KEY_CNAME | String | 선택 | Client Name |
PushConstants.KEY_STB_ID | String | 선택 | STB ID |
PushConstants.KEY_DEVICE_ID | String | 선택 | Device ID |
- 예시 :
JSONObject params = new JSONObject();
params.put(PushConstants.KEY_STB_ID, "{A73E9E2E-9C6B-11E4-AFAE-C55006B96D3C}");
params.put(PushConstants.KEY_DEVICE_ID, "DEVICE-A73E9E2E9C6B11E4AFAEC55006B96D3C");
Arguments
New in version 4.0 UPMC
Arguments
:param int badgeCountType
Key | Type | Description |
---|---|---|
PushConstants.BADGE_TYPE_KEEP | String | 1개 읽음 처리, 다음 메시지 수신시, 동일한 값 유지(Default, -1 후 +1 이 됨) |
PushConstants.BADGE_TYPE_RESET | String | 입력 값으로 초기화, 다음 수신된 값은 입력값 +1로 처리됨 |
PushConstants.BADGE_TYPE_UPDATE | String | 카운트에 따라 업데이트 됨 (읽음여부에 상관없이, push 수신 ++) |
Arguments
Arguments
Arguments
Arguments
Arguments
Arguments
Arguments
Arguments
Key | Description (결과값) |
---|---|
PushConstantsEx.COMPLETE_BUNDLE.REG_USER | 사용자 등록 |
PushConstantsEx.COMPLETE_BUNDLE.UNREG_USER | 사용자 등록 |
PushConstantsEx.COMPLETE_BUNDLE.UPDATE_PUSHSERVICE_DATE | push service 갱신 |
PushConstantsEx.COMPLETE_BUNDLE.REG_PUSHSERVICE | 푸시 서비스 등록 |
PushConstantsEx.COMPLETE_BUNDLE.UNREG_PUSHSERVICE | 푸시 서비스 해제 |
PushConstantsEx.COMPLETE_BUNDLE.READ_CONFIRM | 읽음 ack |
PushConstantsEx.COMPLETE_BUNDLE.RECEIVE_CONFIRM | 수신 ack (gcm only) |
PushConstantsEx.COMPLETE_BUNDLE.IS_REGISTERED_SERVICE | 서비스 등록 여부 (register service 호출 시, 수신 될 수 있음) |
PushConstantsEx.COMPLETE_BUNDLE.INITBADGENO | 뱃지 넘버 초기화 |
PushConstantsEx.COMPLETE_BUNDLE.REG_GROUP | 그룹 등록 |
PushConstantsEx.COMPLETE_BUNDLE.UNREG_GROUP | 그릅 해제 |
Key | Description (결과값) |
---|---|
PushConstants.RESULTCODE_OK | 정상 |
PushConstants.RESULTCODE_HTTP_ERR | 통신 오류 - UPMC서버에 접속할 수 없을때 - connection 관련 error |
PushConstants.RESULTCODE_AUTHKEY_ERR | 인증키 획득 오류 |
PushConstants.RESULTCODE_RESPONSE_ERR | 응답 오류 - 오류코드를 수신한 경우 |
PushConstants.RESULTCODE_INTERNAL_ERR | 정의되지 않은 예기치 못한 오류가 발생한 경우 |
PushConstants.RESULTCODE_AUTHKEY_ERR2 | 인증키 획득 오류 |
Key | Description (결과값) |
---|---|
PushConstants.KEY_RESULT | ACTION_COMPLETED에 Extras용 전체 호출값 |
PushConstants.KEY_BUNDLE | 번들용 KEY |
PushConstants.KEY_ISREGISTER | 서비스 등록 여부에 대한 결과값 |
PushConstants.KEY_RESULT_CODE | 결과 코드 (정상 : 200) |
PushConstants.KEY_RESULT_MSG | upmc 통신 이후, 수신된 메시지 |
private BroadcastReceiver mLoginBroadcastReceiver;
public void registerReceiver() {
if (mLoginBroadcastReceiver != null) {
return;
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(LoginActivity.this.getPackageName() + PushConstantsEx.ACTION_COMPLETED);
mLoginBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(!PushUtils.checkValidationOfCompleted(intent, context)){
return;
}
//intent 정보가 정상적인지 판단
String result = intent.getExtras().getString(PushConstants.KEY_RESULT);
String bundle = intent.getExtras().getString(PushConstantsEx.KEY_BUNDLE);
JSONObject result_obj = null;
String resultCode = "";
String resultMsg = "";
try {
result_obj = new JSONObject(result);
resultCode = result_obj.getString(PushConstants.KEY_RESULT_CODE);
resultMsg = result_obj.getString(PushConstants.KEY_RESULT_MSG);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Action에 따라 분기 (이미 서비스 등록이 된 경우 다음 process 이동)
if(bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.REG_USER)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "로그인 성공!", Toast.LENGTH_SHORT).show();
setSendTest();
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if (bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.UNREG_PUSHSERVICE)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "해제 성공!", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if (bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.REG_GROUP)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "그룹 등록 성공!", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if (bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.UNREG_GROUP)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "그룹 해제 성공!", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if (bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.REG_SERVICE_AND_USER)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "로그인 성공!", Toast.LENGTH_SHORT).show();
setSendTest();
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if (bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.INITBADGENO)) {
if (resultCode.equals(PushConstants.SUCCESS_RESULT_CODE)) {
Toast.makeText(context, "Badge Number 초기화 성공 !", Toast.LENGTH_SHORT).show();
PushManager.getInstance().setDeviceBadgeCount(getApplicationContext(), "11");
}else {
Toast.makeText(context, "[LoginActivity] error code: " + resultCode + " msg: " + resultMsg, Toast.LENGTH_SHORT).show();
}
}else if(bundle.equals(PushConstantsEx.COMPLETE_BUNDLE.IS_REGISTERED_SERVICE)){
String isRegister = "";
try {
isRegister = result_obj.getString(PushConstants.KEY_ISREGISTER);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(isRegister.equals("C")){
Toast.makeText(context, "CHECK ON [ 사용자 재등록 필요 !! ]", Toast.LENGTH_LONG ).show();
}else if(isRegister.equals("N")){
Toast.makeText(context, "CHECK ON [ 서비스 재등록 필요 !! ]", Toast.LENGTH_LONG).show();
}else{
Logger.i("서비스 정상 등록 상태 ");
}
}
}
};
// use-permission 설정에 따라 리시버 등록 API를 구분한다.
PushConfigInfo config = PushManager.getInstance().getPushConfigInfo(this);
if (config.usePermission()) {
// 리시버 권한 사용 시
this.registerReceiver(mLoginBroadcastReceiver, intentFilter, this.getPackageName()+PushConstants.PERMISSION_PUSHSERVICE, null);
}
else {
// 리시버 권한 미사용 시
this.registerReceiver(mLoginBroadcastReceiver, intentFilter);
}
}
public void unregisterReceiver() {
if (mLoginBroadcastReceiver != null) {
this.unregisterReceiver(mLoginBroadcastReceiver);
mLoginBroadcastReceiver = null;
}
}
아래 기술된 메시지는 샘플에 대한 예시이며, 프로젝트에서 표현하고자 하는 방식에 따라, Interface 정의서에 의해, 변경이 가능함.
JSONObject key 값에 대한 설명
Key | 활용방법 |
---|---|
MESSAGE | 메시지 타이틀로 이용 |
EXT | 일반 메시지인 경우, 메시지로 이용가능하며, Rich 메시지인 경우, 세부 정보를 추가로 획득하여, 표현 |
SEQNO | Push message의 고유 키값 |
PSID | Push 서비스에 대한 고유 ID( PSID) |
APPID | Push 서비스가 관리되는 앱 ID( Application ID) |
CUID | 사용자 ID( Client ID) |
PUBLIC | Public 망을 이용하는 push 여부 |
SENDERCODE | 발송자 코드 (서버관점) |
SENDDATE | 발송된 시간 (서버관점) |
DB_IN | DB에 저장 여부 (서버 관점) |
BADGENO | 뱃지값 |
{
"BODY":{
"MESSAGE":"일반 알림",
"EXT":"메세지 테스트",
"SEQNO":"304",
"PSID":"9ca385ad63c4cbd5eeda33c2e7a7a024ea83c2d4",
"APPID":"com.uracle.push.test",
"CUID":"test1",
"PUBLIC":"N",
"SENDERCODE":"device-android",
"SENDDATE":"2016041410",
"DB_IN":"Y",
"BADGENO":"9"
}
}
{
"BODY":{
"MESSAGE":"Web 알림",
"EXT":"1|웹페이지|http://lab.morpheus.kr/push/sample/image|http://lab.morpheus.kr/push/sample/webpage",
"SEQNO":"305",
"PSID":"9ca385ad63c4cbd5eeda33c2e7a7a024ea83c2d4",
"APPID":"com.uracle.push.test",
"CUID":"test1",
"PUBLIC":"N",
"SENDERCODE":"device-android",
"SENDDATE":"2016041410",
"DB_IN":"Y",
"BADGENO":"10"
}
}
{
"BODY":{
"MESSAGE":"이미지 알림",
"EXT":"1|웹페이지|http://lab.morpheus.kr/push/sample/image",
"SEQNO":"307",
"PSID":"9ca385ad63c4cbd5eeda33c2e7a7a024ea83c2d4",
"APPID":"com.uracle.push.test",
"CUID":"test1",
"PUBLIC":"N",
"SENDERCODE":"device-android",
"SENDDATE":"2016041410",
"DB_IN":"Y",
"BADGENO":"12"
}
}
안드로이드 6.0 에서 추가된 도즈 모드는 사용자가 화면을 끄고 일정 시간이 지나면 진입하게 되며, 이 상태에서는 네트워크 및 CPU 자원을 사용하지 못하도록 제한함.
현재 공식적인(구글에서 제공된) 예외는 존재하지 않으므로, 도즈 모드에서 UPNS를 이용하기 위해 다음과 같은 설정이 필요함.
GCM:
android.googleapis.com 443,5228,5229,5230
FCM:
fcm.googleapis.com 443,5228,5229,5230
FCM 포트 및 방화벽:
조직에 인터넷 트래픽 송수신을 제한하는 방화벽이 있으면 모바일 기기의 FCM 연결을 허용하도록 구성해야 네트워크의 기기에서 메시지를 수신할 수 있습니다. FCM은 대개 포트 5228을 사용하지만 5229 및 5230을 사용하는 경우도 있습니다.
발신 연결의 경우 Google IP 범위가 매우 자주 변경되며 개발자의 방화벽 규칙이 오래되면 사용자 경험에 영향을 줄 수 있으므로 FCM에서 특정 IP를 제공하지 않습니다. IP 제한 없이 포트 5228~5230을 허용하는 것이 가장 좋습니다. 하지만 IP 제한이 있어야 한다면 Google ASN 15169에 나와 있는 IPv4 및 IPv6 블록의 모든 IP 주소를 허용해야 합니다. 목록의 크기가 크며 규칙을 매월 업데이트하도록 계획을 세워야 합니다. 방화벽 IP 제한으로 인해 발생하는 문제는 보통 간헐적이며 진단하기 어렵습니다.
수신 메시지용으로 열어야 하는 포트:
5228
5229
5230
발신 연결을 허용하는 포트:
다음 중 하나(1번 옵션 권장):
1. IP 제한 없음
2. Google ASN 15169 에 나와 있는 IP 블록에 포함된 모든 IP 주소: 한 달에 한 번 이상 업데이트해야 합니다.