Push for UPNS + FCM 연동

1. 라이브러리 및 샘플

Note

최신 샘플 및 라이브러리는 아래 링크를 통해, 다운로드 받을 수 있습니다.

2. 개요

Morpheus Push 는 스마트폰 OS에서 지원하는 PNS(Push Notification Server)를 기반으로 한 메세지 전송 플랫폼이다. Android Client 에서는 UPMC WAS 에서 제공하는 Push API 를 각각 버전 규격에 맞춰 연동하여 원할하게 Push Service 를 운영하기 위한 라이브러리를 제공한다.

3. 용어

UPNS

  • Uracle Push Notification System 의 줄임말.

  • UPNS는 MQTT Protocol 기반으로 Android 애플리케이션으로 테이터를 전송하게 해주는 private 서비스이다.

  • 서버에서 가져와야할 새로운 데이터가 있음을 Android 애플리케이션에 알리는 적은 용량의 메시지이거나, 최대 256Mbyte를 지원하나, 4k를 권고한다.

  • Android application은 message를 받기 위해 background service가 실행되고 있음.

  • UPNS는 단순히 원시 data를 android 단말로 보내며, 이 data를 통해 application에서 제어함.

  • Android 2.2 이상을 지원.

UPMC

  • Uracle Push Message Center 의 줄임말.

  • HTTP 프로토콜을 이용하여, Server 대 Server 로 연계하여 구동하는 WAS(Web Application Server) 이다.

  • Receiver 라고도 불림

Service 등록

  • UPNS 로 부터 PSID 를 할당 받고 UPMC 로 Push 서비스를 사용하겠다고 등록하는 절차

Service 등록 및 사용자 등록

  • UPNS 로 부터 PSID 를 할당 받고 UPMC 로 Push 서비스를 사용하겠다고 등록하는 절차 와 사용자를 동록하는 절차가 동시에 이뤄짐

Service 해제

  • UPMC 로 Push 서비스를 사용하지 않겠다고 등록을 삭제하는 절차

User 등록

  • UPMC 로 Push 서비스에 대한 사용자를 등록 또는 변경하는 절차

수신 확인

  • 메시지를 수신 후 UPNS 로 Ack를 주는 절차

  • MQTT 프로토콜 규약을 따르며, 라이브러리 내부적으로 처리한다.

읽음 확인

  • App에서 메세지를 읽었을때 UPMC 로 Ack를 주는 절차

Application ID

  • AppID라고도 함

  • App의 lic 파일에 포함된 application_id 값으로 앱을 구분하기 위한 코드값.


– FCM 서비스 등록을 위한 ID

Client ID

  • 사용자로 등록할 Client 의 고유한 ID (CUID 라고도 함)

  • Email, UserID, Phone Number 또는 Device-UUID 등을 CUID 로 사용

Client Name

  • 사용자로 등록할 Client 의 이름 (CNAME 라고도 함)

  • 사용자의 이름이나 Nickname 또는 Device Name 을 CNAME 으로 사용

GROUPSEQ

  • Group Sequence Number 의 준말로 User Group의 고유한 Sequence Number

PSID

  • Push Service ID 의 줄임말

  • Push 서비스에 대한 고유 ID

  • UPNS에서 할당 받은 Device Token을 사용

CHECK ON SERVICE

  • 단말이 Push 서비스에 등록되어 있는지를 확인함

  • 4.0 이상 지원

Push Notification System ID

  • PNSID라고 함.

  • FCM, UPNS, APNS등이 여기에 속함

App Alive

  • 앱의 설치여부를 24시간 주기로 체크 할 수 있도록 함

  • 체크 방식 : 앱 구동 후 Push Resister method를 사용시(내부적으로 작동)

4.0

  • 대용량 Push(100만 이상)를 위해 설계된 push 시스템

Packge Name

  • google play에서 안드로이드 앱을 구별하기 위한 unique 값으로, AndoridManifest.xml 에 선언한다.

4. Push 서비스 절차

서비스 순서

UPMC 4.x 이상 버전

Service 등록 및 사용자 등록 를 통해, 서비스 등록 및 사용자 등록이 동시에 이뤄짐

DataFlow Diagram

../_images/upns-dataflow-new.png

Sequence Diagram

../_images/push-data-flow.png

RegisterService & User Sequence Diagram (SUCCESS)

../_images/registerandservice.png

RegisterService & User Sequence Diagram (FAIL)

../_images/regserviceanduser_fail.png

Read Message Sequence Diagram

../_images/read-message.png

Service Register Sequence Diagram [option]

../_images/service-register.png

User Register Sequence Diagram [option]

../_images/user-register.png

5. 라이브러리 및 설정 파일

5.1. 라이브러리

  • PushLibrary.jar – UPNS/FCM Push 를 활용할 수 있는 라이브러리

5.2. 공통 설정 파일

  • mcore.mobile.lic – Push 라이센스 정보가 담긴 Push 라이센스 파일

  • Manifest.xml – Push 구동을 위한 설정 파일

6. SDK 및 설정 파일

6.1. SDK 버전

  • Android 용 SDK 파일

    • MPushLibrary

      • FCM / UPNS Push를 활용할 수 있는 라이브러리

    • mcore.mobile.lic

      – Push 라이센스 정보가 담긴 Push 라이센스 파일

    • Manifest.xml

      – Push 구동을 위한 설정 파일

  • SDK 적용 방법

    • Android Project 의 libs 폴더에 Library 파일에 추가
      • Push Library.jar

      • mqtt-android-push.jar

      ../_images/push-libs-fcm.png
    • Android Project의 assets/res 폴더에 라이선스 및 설정 파일 추가
      • Manifest.xml

      • mcore.mobile.lic

      ../_images/push-lib-setting.png

6.2. 플러그인 버전

  • 플러그인 적용 방법

    • IDE 에서 MPush Plugin 을 업데이트 후 적용

6.3. 공통 설정 파일

  • 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 서비스를 운용하는 중에 생성되는 사용자 또는 단말기의 식별 가능한 데이타를 암호화 하여 저장

6.4. 적용 순서

  1. 프로젝트 생성

  2. 라이선스 반영

    가. assets > mcore.mobile.lic
    나. jni 파일 추가 : libMCore.so
    
  3. fcm console 이동 : sender id 발급 / google-service.json 파일 다운로드

  4. Manifest.xml 설정

  5. AndroidManifest.xml 설정

  6. dummy 용 png 파일 적용

  7. Gradle 설정

6.5. google-service.json 파일 다운로드 및 적용

6.6. Manifest.xml 설정

  • Push 구동을 위한 설정 파일

<?xml version="1.0" encoding="UTF-8"?>
<settings>
        <push>
                <receiver> <!-- UPMC 설정 정보 -->

                        <!-- console log -->
                        <log>y</log>

                        <!-- file log -->
                        <file-log>n<file-log>

                        <!-- key 교환 방식 암호화 : 라이선스 발급시 요청 (hexa코드 16자리) -->
                        <security-indexes>0x??? 0x??? 0x??? </security-indexes>

                        <!-- 서버 버전 5.0-->
                        <version>5.0</version>
                        <!-- receiver 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:구글GCM / FCM(Public Push) : FCM 이용시도 하위 호환성을 위해, GCM으로 표기함
                         UPNS:유라클UPNS(Private Push)
                         ALL : doze mode 대응 (gcm : dummy data, upns : real data)
                        -->
                        <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>

                        <!-- 안드로이드 8.0이상 필수, 브로드캐스트 리시버에서 퍼미션 사용 여부를 설정 (Y/N) -->
                        <use-permission>Y</use-permission>
                </receiver>

                <upns>
                        <!-- agent, inapp -->
                        <agent-service-type>inapp</agent-service-type>

                        <!-- assets 안에 agent apk 파일이 있는 경우 -->
                        <!-- <agent-apk-name></agent-apk-name>
                        <agent-classpath></agent-classpath>
                        <agent-package-name></agent-package-name>  -->


                        <!-- UPNS RESTART ALARM INTERVAL (초단위) : JobScheduler 이벤트 시간-->
                        <agent-restart-interval>120</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>
  • settings.push.receiver 에 대한 설정값

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, 5.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 : 수동, 직접 구현)

reconnect-interval

String

재연결 요청 간격 (기본값: 10초) : 서버의 부하를 고려하여 설정 (반대로 너무 길 경우 재연결이 오래 걸리므로 주의)

reallocate-interval

String

서버 4.1 이상 이용 시 연결 실패에 따른 서버 재할당 간격 (기본값: 600ms) : 서버의 부하를 고려하여 설정

retry-regist-count

String

사용자 등록 시 재시도 여부 auto / 횟수 (integer)

Note

파일로그 위치 : 스토리지 > Android > data > [package name] > log > pushlog.log

6.7. AndroidManifest.xml 설정 (FCM 설정)

  • Push ALL 설정에 대한 UPNS/FCM 선언

<?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">

          <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
          <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" />

        <!-- 안드로이드 9.0 이상 필수 : targetSdkVersion = 28 이상인 경우 -->
          <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

         <!-- push service&receiver -->
         <!-- 5.1.x 버전 추가 : JobScheduler 를 이용한 서비스 Start-->
          <service
              android:name="m.client.push.library.service.UPNSJobService"
              android:exported="false">
               <intent-filter>
                  <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
               </intent-filter>
           </service>

       <service android:name="m.client.push.library.service.UPNSConnectService"
            android:exported="false"/>

         <!-- 5.1.x 버전 추가 : JobScheduler 를 이용한 서비스 End-->

          <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.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>

        <!-- FCM setting start -->
        <!-- 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>


        <!-- FCM setting End -->

        <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>


</manifest>

6.8. Gradle Settings [Project]

  • Sample

buildscript {

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.3'
        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()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

6.9. Gradle Settings [Module]

  • dependencies (적용 버전은 유동적임)

implementation (‘com.google.firebase:firebase-messaging:20.2.1’)

  • apply (build.gradle 맨 하단에 적용)

apply plugin: ‘com.google.gms.google-services’

  • Sample

apply plugin: 'com.android.application'
repositories {
    maven { url 'https://maven.google.com' }
}


android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "kr.co.pushdemo"
        minSdkVersion 14
        targetSdkVersion 29
        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:20.2.1')
    implementation 'com.google.firebase:firebase-iid:21.1.0'
    implementation 'com.firebase:firebase-jobdispatcher:0.8.6'
    //jar 버전이 포함되지 않은 경우
    implementation 'com.google.code.gson:gson:1.7.1'
}
apply plugin: 'com.google.gms.google-services'

6.10. FCM 구현시 주의 사항

  • Public Push 로 제공되는 안드로이드 FCM 에 대한 설정은 기본적으로 안드로이드에서 제공되는 설정 가이드와 다르지 않으며, 패키지 명 선언에 주의하여 설정해야 한다.

6.11. UPNS 구현시 주의 사항

  • UPNSJobService: UPNS 푸시를 수신하기 위한 중요한 역할을 하므로 반드시 추가되어야 한다.

  • ServiceHandleReceiver: 라이브러리 내에 존재하는 리시버로 서비스의 생명 주기를 담당하는 리시버이다.

  • MessageArrivedReceiver: 서버로부터 메시지를 수신하는 리시버로 데이터 수신 시 화면에 보여줄 방법을 정의하여 사용한다.

  • UPNSActionReceiver: 라이브러리 내에 존재하는 리시버로 UPNS 기능에 대한 요청을 받아서 처리한다

6.12. Eclipse 프로젝트 Gradle 변환

기존 프로젝트를 Gradle 환경으로 변경한다.

6.13. Android Studio 환경에서, Eclipse 프로젝트 참조하기

7. Push Service 연동

7.1. 라이브러리 버전

Case #1. Push service 등록

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //앱 실행시마다 호출 (4.0이상)
        PushManager.getInstance().registerServiceAndUser(getApplicationContext(), cuid, cname);
        ...
}

7.2. 플러그인 버전

8. Push APIs

Initialize Push Server

PushManager.getInstance().initPushServer(Context context);
  • Manifest.xml 설정 파일에서 라이브러리를 초기화하기 위한 정보를 가져온다.

Parameters
  • context (Context) – 현재 Context

PushManager.getInstance().initPushServer(Context context, JSONObject params);
  • Manifest.xml 설정 파일에서 라이브러리를 초기화하기 위한 정보를 가져온다

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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");

Register Service (deprecated)

Note

deprecated api이고, Register Service and User 를 이용한다.

PushManager.getInstance().registerPushService(Context context);
  • FCM 및 UPNS에 푸시 서비스를 등록 한다.

Parameters
  • context (Context) – 현재 context

PushManager.getInstance().registerPushService(Context context, JSONObject params);
  • FCM / UPNS 에 푸시 서비스를 등록한다.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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");

Register User

Note

deprecated api이고, Register Service and User 를 이용한다.

PushManager.getInstance().registerPushUser(Context context, String cuid, String cname);
  • Client IDClient Name 으로 User 등록

  • 푸시 서비스를 이용할 사용자를 등록한다. 서비스 등록이 성공한 이후 사용자 등록이 가능하다.

Parameters
  • context (Context) – 현재 Context

  • cuid (String) – Client ID

  • cname (String) – Client Name

-결과값 : Reciver 를 통해, 처리 결과 통보

PushManager.getInstance().registerPushUser (Context context, JSONObject params);
  • Client IDClient Name 으로 User 등록

  • 푸시 서비스를 이용할 사용자를 등록한다. 서비스 등록이 성공한 이후 사용자 등록이 가능하다.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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 를 통해, 처리 결과 통보

Register Service and User

PushManager.getInstance().registerServiceAndUser(Context context, String cuid, String cname);
  • Client IDClient Name 으로 User 등록

  • FCM or UPNS에 푸시 서비스와 사용자을 동시에 처리 함.

  • 지원버전 : 서버 UPMC 3.7.2.9 이상, client 3.8.0.4 이상

Parameters
  • context (Context) – 현재 Context

  • cuid (String) – Client ID

  • cname (String) – Client Name

-결과값 : Reciver 를 통해, 처리 결과 통보

PushManager.getInstance().registerServiceAndUser (Context context, JSONObject params);
  • Client IDClient Name 으로 User 등록

  • FCM or UPNS에 푸시 서비스와 사용자을 동시에 처리 함.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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 를 통해, 처리 결과 통보

Change Service

PushManager.getInstance().changePushService (Context context, JSONObject params);
  • Manifest 푸시 타입에 따라 최초 등록 이후, 서비스 타입을 동적으로 변경한다.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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);

UnRegister User

PushManager.getInstance().unregisterPushUser(Context context, String cuid, String cname);
  • Client IDClient Name 으로 User 등록해제

  • FCM or UPNS에 푸시 서비스를 이용할 사용자를 등록헤재 한다

Parameters
  • context (Context) – 현재 Context

  • cuid (String) – Client ID

  • cname (String) – Client Name

-결과값 : Reciver 를 통해, 처리 결과 통보

PushManager.getInstance().unregisterPushUser (Context context, JSONObject params);
  • Client IDClient Name 으로 User 등록 해제

  • FCM or UPNS에 푸시 서비스를 이용할 사용자를 등록해제 한다.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

Key

Type

Necessary

Description

PushConstants.KEY_CUID

String

필수

Client ID

PushConstants.KEY_CNAME

String

필수

Client Name

-결과값 : Reciver 를 통해, 처리 결과 통보

Unregister Service

PushManager.getInstance().unregisterPushService(Context context);
  • FCM 및 UPNS에 푸시 서비스를 해제 한다.

Parameters
  • context (Context) – 현재 context

-결과값 : Reciver 를 통해, 처리 결과 통보

PushManager.getInstance().unregisterPushService(Context context, JSONObject params);
  • FCM / UPNS 에 푸시 서비스를 해제 한다.

Parameters
  • context (Context) – 현재 Context

  • params (JSONObject) – 정보셋팅

  • JSONObject key 값에 대한 설명

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");

Read Push Message

PushManager.getInstance().pushMessageReadConfirm (Context context, String notification);
  • 사용자가 메시지를 확인 하는 경우, 메시지 확인 전문을 전송한다.

Parameters
  • context (Context) – 현재 context

  • notification (String) – 수신한 push message(JSONObject의 string값)

PushManager.getInstance().pushMessageReadConfirm (Context context, String notification, int badgeCountType);
  • 사용자가 메시지를 확인 하는 경우, 메시지 확인 전문을 전송하며, 서버와 badge count를 동기화 한다.

New in version 4.0: UPMC

Parameters
  • context (Context) – 현재 context

  • notification (String) – 수신한 push message(JSONObject의 string값)

:param int badgeCountType

  • badgeCountType key 값에 대한 설명

Key

Type

Description

PushConstants.BADGE_TYPE_KEEP

String

1개 읽음 처리, 다음 메시지 수신시, 동일한 값 유지(Default, -1 후 +1 이 됨)

PushConstants.BADGE_TYPE_RESET

String

입력 값으로 초기화, 다음 수신된 값은 입력값 +1로 처리됨

PushConstants.BADGE_TYPE_UPDATE

String

카운트에 따라 업데이트 됨 (읽음여부에 상관없이, push 수신 ++)

Receive Push Message

PushManager.getInstance().pushMessageReceiveConfirm (Context context, String notification);
  • FCM Only

  • 메시지 수신 시 메시지 수신 전문을 전송한다.

Parameters
  • context (Context) – 현재 context

  • notification (String) – 수신한 push message(JSONObject의 string값)

PushManager.getInstance().upnsMessageReceiveConfirm (Context context, String msgID);
  • UPNS Only

  • mqtt를 통해 수신한 메시지에 대한 응답 (Manifest.xml 에서 <agent-receive-confirm> 값이 “manual”인 경우 작동한다)

Parameters
  • context (Context) – 현재 context

  • msgID (String) – 수신된 푸시 인텐트로부터 받은 MESSAGEID

UPNS Subscribe

PushManager.getInstance().upnsSubscribe(Context context);
  • UPNS Only

  • UPNS 서버에 subscribe 요청을 다시한다. (요청 시 오프라인 메시지 수신 [서버로 부터 발송이 실패되어 저장중인 메시지] – 부하가 될 수 있으므로 주의 사용)

Parameters
  • context (Context) – 현재 context

Register Group

PushManager.getInstance().registerUserGroup (Context context, String groupSeq);
  • 사용자 그룹에 등록한다.

Parameters
  • context (Context) – 현재 context

  • groupSeq (String) – 등록하고자 하는 그룹의 sequence number

UnRegister Group

PushManager.getInstance().unregisterUserGroup (Context context, String groupSeq);
  • 사용자 그룹에서 등록을 해제 한다.

Parameters
  • context (Context) – 현재 context

  • groupSeq (String) – 해제하고자 하는 그룹의 sequence number

Init Badge Number

PushManager.getInstance().initBadgeNo (Context context, String badgeNo);
  • 서버의 Badge NO를 강제 셋팅 또는 초기화

  • Badge NO 최소값 : 0

  • Badge NO 최대값 : 1000

Parameters
  • context (Context) – 현재 context

  • badgeNo (String) – 서버에서 관리되는 뱃지 count에 대한 초기값 (0을 셋팅하는 경우, push수신시 1로 셋팅됨)

Set DeviceBadge Count

PushManager.getInstance().setDeviceBadgeCount (Context context, String badgeNo);
  • 폰의 Badge NO를 표기함

  • 폰의 설치된 런처에 따라, 작동하지 않을 수 있음

  • Badge NO 최소값 : 0

  • Badge NO 최대값 : 1000

Parameters
  • context (Context) – 현재 context

  • badgeNo (String) – 서버에서 관리되는 뱃지 count에 대한 초기값 (0을 셋팅하는 경우, push수신시 1로 셋팅됨)

Get Reg Status

PushManager.getInstance().getPushRegStatus (Context context);
  • retry-regist-count 재시도 옵션이 auto 혹은 임의의 수일 경우 현재 등록 태스트의 상태 반환

  • PushConstants.PushRegistStatus.REGISTER_RUNNING : 등록 수행중 상태

  • PushConstants.PushRegistStatus.ALREADY_REGISTERED : 등록 완료 상태

  • PushConstants.PushRegistStatus.NOT_REGISTERED : 미등록 상태

Parameters
  • context (Context) – 현재 context

9. Push APIs 키값 정의

ver 4.0 이상

  • API 호출에 따른 결과값 (BroadCastReceiver bundle key)

    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

    그릅 해제

    • BroadCastReceiver bundle key return 값 (STATUS CODE - 통신관련)

    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

    인증키 획득 오류

    • BroadCastReceiver Intent 관련 키값 (처리 결과 )

    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 통신 이후, 수신된 메시지

10. UPMC용 BroadcastReceiver 등록 방법 (예시)

receiver 등록

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);

}

receiver 해제

public void unregisterReceiver() {
        if (mLoginBroadcastReceiver != null) {
                LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLoginBroadcastReceiver);
                mLoginBroadcastReceiver = null;
        }
}

11. UPNS Push Payload [ UPNS ]

  • 아래 기술된 메시지는 샘플에 대한 예시이며, 프로젝트에서 표현하고자 하는 방식에 따라, 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

      뱃지값

일반(text) push 메시지 예시

{
   "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"
   }
}

웹 브라우저 호출 push 메시지 예시

{
   "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"
   }
}

이미지 push 메시지 예시

{
   "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"
   }
}

12. UPNS Reallocate

  • 푸시 서버 버전 4.1이상에서 서버 장애 시 UPNS 재연결에 대한 동작 추가 (이하 버전에서는 해당 시나리오 동작안함.)

  • 재연결 3회 실패 시 랜덤한 시간 간격으로 UPMC에 새로운 UPNS IP/PORT를 요청 후 응답 정보를 이용하여 재연결 요청

Sequence Diagram

../_images/upns-reallocate.png

13. 방화벽 OPEN [for Client]

  • GCM:

    android.googleapis.com 443,5228,5229,5230
    
  • FCM:

    fcm.googleapis.com 443,5228,5229,5230
    
  • FCM 참고 문서

  • 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 주소:  달에   이상 업데이트해야 합니다.
    
  • Google ASN 15169 문서