Note
최신 샘플 및 라이브러리는 아래 링크를 통해, 다운로드 받을 수 있습니다.
Note 최소 지원 버전 : 안드로이드 4.4 (minSdk 19)
Morpheus Push 는 스마트폰 OS에서 지원하는 PNS(Push Notification Server)를 기반으로 한 메세지 전송 플랫폼이다.
Android Client 에서는 UPMC WAS 에서 제공하는 Push API 를 각각 버전 규격에 맞춰 연동하여 원할하게 Push Service 를 운영하기 위한 라이브러리를 제공한다.
– FCM 서비스 등록을 위한 ID
UPMC 3.5 이하 버전
initPushService => 토큰 요청 => User 등록 => Service 등록 => 메시지 수신
UPMC 3.6 이상 버전
initPushService => Service 등록 (자동으로 Token 요청) => User 등록 => 메시지 수신
Android 용 SDK 파일
SDK 적용 방법
Android Project 의 libs 폴더에 Library 파일에 추가 ( Push Library xxx.jar)
Android Project의 assets/res 폴더에 라이선스 및 설정 파일 추가
- Manifest.xml
- mcore.mobile.lic
mcore.mobile.lic - Push 라이센스 정보가 담긴 Push 라이센스 파일 - application_id 값을 Application ID 로 사용
#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 라이센스 파일을 바탕으로 생성한 Security Indexes 값으로 Push 서비스를 운용하는 중에 생성되는 사용자 또는 단말기의 식별 가능한 데이타를 암호화 하여 저장
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<push>
<option>
</option>
<receiver> <!-- UPMC 설정 정보 -->
<!-- console log -->
<log>y</log>
<!-- file log -->
<file-log>n</file-log>
<!-- key 교환 방식 암호화 : 라이선스 발급시 요청 (hexa코드 16자리) 서버 3.8.1 이상 -->
<security-indexes>0x??? 0x??? 0x??? </security-indexes>
<!-- 서버 버전 3.6/3.7/3.8/4.0-->
<version>5.0</version>
<!-- UPMC server url(필수 설정) -->
<server>http://pushxx.morpheus.co.kr:18080/</server>
<timeout>20000</timeout>
<!-- FCM설정 -->
<!-- FCM sender-id (push-type이 FCM일 경우 필수설정, sender id는 1개만 등록 가능. ) -->
<fcm-sender-id>xxxxxxxxxxxx</fcm-sender-id>
<!-- 푸쉬타입(필수설정)
FCM:구글FCM(Public Push)
UPNS:유라클UPNS(Private Push)
ALL : Doze Mode 대응 (FCM : Dummy Data, UPNS : real Data)
-->
<android-push-type>FCM</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) android 8.0 이상 필수 -->
<use-permission>Y</use-permission>
</receiver>
</push>
</settings>
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 |
device-type | String | 서비스 디바이스에 대한 성정 (빈값 : mobile, mobile : mobile용, stb : 셋탑용) |
agent-service-type | String | UPNS 서비스 방식 (inapp : 라이브러리형, agent : 별도의 Agent 앱 구현시) |
agent-restart-interval | String | 앱이 살아 있는지 체크를 위한 시간 설정 (단위 : sec) |
agent-receive-confirm | String | upns 메시지 수신 결과에 대한 ack 전송 방법 (auto : 자동 (default), manual : 수동, 직접 구현) |
Note
파일로그 위치 : 스토리지 > Android > data > [package name] > log > pushlog.log
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="[패키지명]"
android:versionCode="1"
android:versionName="1.0">
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<!-- push service&receiver -->
<service android:name="m.client.push.library.service.FCMIntentService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver android:name="[패키지명].receiver.MessageArrivedReceiver" android:exported="false">
<intent-filter>
<action android:name="${applicationId}.GCM_MESSAGE_ARRIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="m.client.push.library.receiver.GcmActionReceiver" android:exported="false">
<intent-filter>
<action android:name="${applicationId}.ACTION_GCM" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!--UPNS remove-->
<service
android:name="m.client.push.library.service.UPNSConnectService"
android:exported="false"
android:foregroundServiceType="dataSync"
tools:node="remove"/>
<receiver
android:name="m.client.push.library.receiver.ServiceHandleReceiver"
android:exported="true"
tools:node="remove"/>
<receiver
android:name="m.client.push.library.receiver.UpnsActionReceiver"
android:exported="false"
tools:node="remove"/>
</application>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 안드로이드 8.0이상 필수 라이브러리 버전 4.1.0.7 이상부터 추가된 리시버 등록 시 권한 등록위해 선언 (없으면 앱 디폴트 권한) -->
<permission android:name="${applicationId}.permission.MPUSH_PERMISSION" android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.MPUSH_PERMISSION" />
</manifest>
morpheus_push_library_5.2.0.15 version 이상의 라이브러리를 사용하는 경우 위의 예시로 제공하는 AndroidManifest.xml 설정이 필요하지 않으며, 별도로 커스텀 notification 으로 사용되는 경우 아래와 같이 별도의 "receiver"로 정의해주어야 합니다.
<receiver android:name="[패키지명].receiver.MessageArrivedReceiver" android:exported="false" >
<intent-filter>
<action android:name="${applicationId}.GCM_MESSAGE_ARRIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
classpath 'com.google.gms:google-services:4.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
implementation 'com.google.code.gson:gson:2.8.6'
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation ('com.google.firebase:firebase-messaging:23.1.2')
implementation ('com.google.firebase:firebase-iid:21.1.0')
implementation 'androidx.work:work-runtime:2.7.1'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.android.application'
repositories {
maven { url 'https://maven.google.com' }
}
android {
//필수
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
signingConfigs {
config {
}
}
compileSdkVersion 33
defaultConfig {
applicationId "com.push.democlient"
minSdkVersion 19
targetSdkVersion 33
multiDexEnabled true
}
lintOptions {
abortOnError false
}
buildTypes {
release {
// minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
debuggable false
jniDebuggable false
renderscriptDebuggable false
signingConfig signingConfigs.config
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
//필수 start ================================================
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.firebase:firebase-messaging:23.1.2'
implementation 'com.google.firebase:firebase-iid:21.1.0'
implementation 'androidx.work:work-runtime:2.7.1'
//필수 end ========================================
//universal-image-loader jar 파일이 존재하지 않는경우
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
}
//반드시, script 맨 하단에 작성 [위치 옮기지 말것 ]
apply plugin: 'com.google.gms.google-services'
Warning
Public Push 로 제공되는 안드로이드 FCM 에 대한 설정은 기본적으로 안드로이드에서 제공되는 설정 가이드와 다르지 않으며 다만 패키지 명을 주의하여 설정해야 한다.
Warning
아래와 같이 Error가 발생하는 경우, dependencies 속성이 Gradle 버전과 맞지 않기 때문이므로, implementation 을 compile 로 변경한다.
Error : A problem occurred evaluating project ':app'. > Could not find method implementation() for arguments
Case #1. Push service 등록
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//앱 실행시마다 호출
PushManager.getInstance().registerServiceAndUser(Context context, String cuid, String cname);
...
}
-- Push 플러그인 : https://wiki.uracle.co.kr/madp/client/api/plugin/push
Note
푸시 초기화(InitPushService method)는 custom data 를 이용할 경우에만 진행한다. Application class 에서는 Manifest.xml parsing 과정에서, 오류가 발생할 수 있으므로 Activity 에서 호출
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");
Note
deprecated api이고, Register Service and User 를 이용한다.
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");
Note
deprecated api 이고, Register Service and User 를 이용한다.
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_CUSTOM_RECEIVER_SERVER_URL | String | 선택 | UPMC URL |
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 |
-결과값 : 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
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
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 (FCM 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("서비스 정상 등록 상태 ");
}
}
}
};
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mLoginBroadcastReceiver, intentFilter);
}
public void unregisterReceiver() {
if (mLoginBroadcastReceiver != null) {
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLoginBroadcastReceiver);
mLoginBroadcastReceiver = null;
}
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d("RemoteMessage_Log",remoteMessage.getData().toString());
if(PushUtils.isMorpheusPush(remoteMessage)) {
Logger.e(remoteMessage.toString());
PushMessagingManager.getInstance().messageReceived(getApplicationContext(), remoteMessage);
}
else{
//기타 타 시스템 푸시 처리
}
}
implementation ('com.google.firebase:firebase-messaging:23.0.0')
apply plugin: 'com.google.gms.google-services'
아래 기술된 메시지는 샘플에 대한 예시이며, 프로젝트에서 표현하고자 하는 방식에 따라, Interface 정의서에 의해, 변경이 가능함.
JSONObject key 값에 대한 설명 [key가 소문자임]
Key | 활용방법 |
---|---|
alert | 메시지 타이틀로 이용 |
alert.aif | 수신음 파일명 (적용여부는 상황에 맞게 판단) |
ext | 일반 메시지인 경우, 메시지로 이용가능하며, Rich 메시지인 경우, 세부 정보를 추가로 획득하여, 표현 |
seqno | Push message의 고유 키값 |
appid | Push 서비스가 관리되는 앱 ID ( Application ID) |
sender | 발송자 코드 (서버관점) |
senddate | 발송된 시간 (서버관점) |
db_in | DB에 저장 여부 (서버 관점) |
badge | 뱃지값 |
pushkey | public push의 토큰 유효성을 위해 관리되는 키 (서버관점) |
{
"aps":{
"badge":"14",
"sound":"alert.aif",
"alert":"일반 알림"
},
"mps":{
"appid":"com.uracle.push.test",
"seqno":"288",
"sender":"device-android",
"senddate":"2016041409",
"db_in":"Y",
"pushkey":"2427efdf1b62cd9dbdf174bbdff048f8051461e1"
"sms":"N",
"title":"메시지 테스트",
"body":"테스트 메시지 입니다."
}
}
{
"aps":{
"badge":"15",
"sound":"alert.aif",
"alert":"Web 알림"
},
"mps":{
"appid":"com.uracle.push.test",
"ext":"1|웹페이지|http://lab.morpheus.kr/push/sample/image|http://lab.morpheus.kr/push/sample/webpage",
"seqno":"290",
"sender":"device-android",
"senddate":"2016041409",
"db_in":"Y",
"pushkey":"2427efdf1b62cd9dbdf174bbdff048f8051461e1"
"title":"웹 알림메시지 테스트",
"body":"테스트 메시지 입니다."
}
}
{
"aps":{
"badge":"16",
"sound":"alert.aif",
"alert":"동영상 알림"
},
"mps":{
"appid":"com.uracle.push.test",
"ext":"2|기본동영상|http://lab.morpheus.kr/push/sample/image|https://youtu.be/IIu0VMdOe10",
"seqno":"292",
"sender":"device-android",
"senddate":"2016041409",
"db_in":"Y",
"pushkey":"2427efdf1b62cd9dbdf174bbdff048f8051461e1"
"title":"동영상 알림메시지 테스트",
"body":"테스트 메시지 입니다."
}
}
{
"aps":{
"badge":"17",
"sound":"alert.aif",
"alert":"이미지 알림"
},
"mps":{
"appid":"com.uracle.push.test",
"ext":"3|기본이미지|http://lab.morpheus.kr/push/sample/image",
"seqno":"294",
"sender":"device-android",
"senddate":"2016041409",
"db_in":"Y",
"pushkey":"2427efdf1b62cd9dbdf174bbdff048f8051461e1"
"title":"이미지 알림메시지 테스트",
"body":"테스트 메시지 입니다."
}
}
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번 옵션 권장):
- IP 제한 없음
- Google ASN 15169 에 나와 있는 IP 블록에 포함된 모든 IP 주소: 한 달에 한 번 이상 업데이트해야 합니다.