| 파일명 | 설명 |
| SDK_Android_APMS_xxx.jar | APMS 라이브러리 |
| apms.propreties | APMS 설정 파일 |
| org.eclipse.paho.client.mqttv3-1.2.0(mlog).jar | Private 서비스를 사용하기 위해 사용되는 MQTT 라이브러리 |
| apms-sdk.js | Click을 잡는 스크립트 파일 |
FCM 적용으로 인해서 Eclipse는 지원을 하지 않습니다.
Android Studio만 지원을 합니다.
Project로 변경하여 주시기 바랍니다.
SDK_Android_APMS_xxx.jar 파일과 org.eclipse.paho.client.mqttv3-1.2.0(mlog).jar 파일을 넣어 주시기 바랍니다.
build.gradle의 dependencies에 다음 사항을 추가하여 주시기 바랍니다.dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.firebase:firebase-core:16.0.5'
implementation 'com.google.firebase:firebase-messaging:17.3.4'
}build.gradle의 android에 buildToolsVersion을 기입하여 주시기 바랍니다.android {
compileSdkVersion 26
buildToolsVersion '28.0.3'
}build.gradle의 dependencies 밑에 다음 항목을 추가하여 주시기 바랍니다.dependencies {
...
}
apply plugin: 'com.google.gms.google-services'build.gradle 파일에 다음 사항들을 추가하여 주시기 바랍니다.buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.google.gms:google-services:4.1.0'
}
}
allprojects {
repositories {
jcenter()
google()
}
}google-services.json 파일을 app 폴더 아래로 복사를 합니다.
org.eclipse.paho.client.mqttv3-1.2.0(mlog).jarbuild.gradle의 dependencies 밑에 다음 항목을 추가하여 주시기 바랍니다.dependencies {
implementation 'com.android.volley:volley:1.1.1'
...
}Sync Now를 클릭하여서 Build를 완료합니다.assets 디렉토리를 생성합니다.assets 디렉토리 내에 첨부파일에 있었던 apms.properties와 apms-sdk.js 파일을 넣어 줍니다.
APMS sdk = APMS.getInstance(activity.getApplicationContext());
sdk.setPopupNoti(true);
sdk.setRingMode(true);
sdk.setVibeMode(true);
sdk.setIsPopupActivity(true);
sdk.setNotiOrPopup(false);
...APMS수행을 위한 Permission, Service, Receiver, Meta Data등을 설정합니다.
샘플 소스의 AndroidManifest.xml 참조
<!-- push -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.VIBRATE" />
<!-- push -->
<!-- network -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- network --><receiver
android:name="com.apms.sdk.push.PushReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.google.android.fcm.intent.RECEIVE" />
<action android:name="org.mosquitto.android.mqtt.MSGRECVD" />
</intent-filter>
</receiver>
<service
android:name="com.apms.sdk.push.FCMPushService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service><application> 태그내에 추가합니다.<!-- apms push popup activity -->
<activity
android:name="${push_popup_activity}"
android:theme="@style/push_popup_theme"
android:excludeFromRecents="true"
android:taskAffinity=".PushPopupActivity"
android:screenOrientation="portrait"
android:configChanges="orientation" /><application> 태그내에 추가합니다.${push_popup_activity}는 Push수신 시 출력될 Popup Activity의 className을 의미합니다.${push_popup_activity}에 셋팅하시고, apms.properties의 push_popup_activity의 값과 일치시켜 주시면 됩니다.Custom PushPopupActivity 적용 예제 (PushPopupAcitivity className이 "com.custom.push.CusomPushPopupActivity"일 경우)
<!-- apms push popup activity -->
<activity
android:name="com.custom.push.CusomPushPopupActivity"
android:theme="@style/push_popup_theme"
android:excludeFromRecents="true"
android:exported="false"
android:screenOrientation="portrait"
android:configChanges="orientation" />push_popup_activity=com.custom.push.CusomPushPopupActivity<!-- apms push clickNotiReceiver -->
<receiver android:name="${noti_receiver_class}" >
<intent-filter>
<action android:name="${noti_receiver}" />
</intent-filter>
</receiver><application> 태그내에 추가합니다.${noti_receiver_class}는 Push수신 시 출력되는 상단의 Notification을 터치 했을 때, 수행될 Receiver의 className을 의미합니다.${noti_receiver}는 Push수신 시 출력되는 상단의 Notification을 터치 했을 때, broadcasting할 intent action을 의미합니다.noti_receiver항목에 noti receiver(intent action)를 일치시켜 주셔야 합니다.NotiReceiver 적용 예제 (NotiReceiverClass className이 "com.custom.push.CustomNotiReceiverClass"이고, notiReceiver intent action이 "com.custom.push.notifiaction"일 경우)
<!-- apms push clickNotiReceiver -->
<receiver android:name="com.custom.push.CustomNotiReceiverClass" >
<intent-filter>
<action android:name="com.custom.push.notifiaction" />
</intent-filter>
</receiver>noti_receiver=com.custom.push.notifiaction<!-- APMS Private RestartReceiver -->
<receiver android:name="com.apms.sdk.push.mqtt.RestartReceiver">
<intent-filter>
<action android:name="MQTT.START"/>
<action android:name="MQTT.RESTART"/>
<action android:name="MQTT.FORCE_START"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter>
</receiver>
<!-- Private PUSH Service -->
<service
android:name="com.apms.sdk.push.mqtt.MQTTService"
android:enabled="true"
android:label="PushService"
android:process="${process_name}" /><application> 태그내에 추가합니다.${process_name}는 Android Process Name을 의미합니다.${process_name} 적용 예제 (Process Name이 "com.apms.sdk.HumusonpushService"일 경우)
<!-- Private PUSH Service -->
<service
android:name="com.apms.sdk.push.mqtt.MQTTService"
android:enabled="true"
android:label="PushService"
android:process="com.apms.sdk.HumusonpushService" /><meta-data android:name="APMS_NOTI_CONTENT" android:value="${noti_content}" />APMS_NOTI_CONTENT는 사용자가 알림을 확장하지 않았을때 보이는 표시 내용입니다.big_text_mode를 사용하고 계실때 표시됩니다.${noti_content} 적용 예제 (value가 "두손가락을 이용해 아래로 당겨주세요."일 경우)
<meta-data android:name="APMS_NOTI_CONTENT" android:value="두손가락을 이용해 아래로 당겨주세요." /><meta-data android:name="APMS_NOTI_CONTENT" android:value="@string/finger_event" /><meta-data android:name="APMS_SET_ICON" android:resource="@drawable/${icon_file_name}" />
<meta-data android:name="APMS_SET_LARGE_ICON" android:resource="@drawable/${icon_file_name}" />${icon_file_name}는 Notification Icon에 등록될 Icon File Name을 넣으시면 됩니다.<meta-data android:name="APMS_NOTI_BACK" android:value="\#000000" />\(역슬러쉬)는 무조건적으로 해주셔야 합니다.<meta-data android:name="APMS_SET_NOTI_SOUND" android:resource="@raw/${ring_file_name}"/>${ring_file_name} Resource/Raw/ 저장한 벨소리 파일 네임을 넣으시면 됩니다.<uses-library android:name="org.apache.http.legacy" android:required="false"/>APMS mApms = APMS.getInstance(mCon);
mApms.setPopupSetting(false, mCon.getString(R.string.app_name)); // Custom Popup을 사용여부
mApms.setPopupNoti(true); // 팝업창을 사용 여부
mApms.setRingMode(true); // 알림을 사용 여부
mApms.setVibeMode(true); // 진동 사용 여부
mApms.setIsPopupActivity(false); // 다른 앱 실행이 팝업창을 사용 여부
mApms.setNotiOrPopup(false); // Text Popup을 Toast로 사용 여부<!-- push popup theme -->
<style name="push_popup_theme" parent="android:Theme.Light">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
</style># App Key & API Server Url Setting
# FCM발송을 위한 앱의 projectId로 FCM의 pushToken을 가져오는데 사용됩니다.
gcm_project_id=${Google_Project_Number}
# Admin Web에서 앱 생성 시 발급되는 key입니다.
app_key=${App_key}
# Msg-Api Url을 의미합니다.
api_server_url=${Msg_Api_Url}
# Private Server Setting
# mqtt의 사용여부를 의미합니다. ("Y":사용, "N":사용하지 않음)
mqtt_flag=${mqtt_flag}
# private server와 연동 시 필요한 server url을 의미합니다.
# 반드시 다음과 같이 protocol, url, port를 전부 입력해주셔야 합니다. (사용하지 않을시에는 공백처리)
mqtt_server_url_ssl=${mqtt_ssl_url}
mqtt_server_url_tcp=${mqtt_tcp_url}
# DEBUG MODE
# Logcat 관련 설정 입니다.
debug_tag=APMS
debug_flag=Y
# Service에 대한 로그를 파일로 저장 유무를 설정합니다.
debug_log_falg=Y
# APMS SETTING
# Push 수신시 화면 On/Off를 의미 합니다.
screen_wakeup_flag=Y
# Text Notification 생성시 BigText Mode 사용 여부 (사용 : Y , 미사용 : N)
big_text_mode=Y
# Push 수신시 화면에 보여지는 시간을 의미 합니다. (단위 : ms)
push_popup_showing_time=9999999
# Push 노출을 앱 사용중에만 노출 할 것인지(디폴트값) 아니면
# 다른앱을 사용중에만 빼고 노출 할 것인지 설정값입니다. (default = N)
push_popup_showing_flag=N
# Push수신 시 출력될 Popup Activity의 className을 의미합니다.
# (Default Class : "com.apms.sdk.push.PushPopupActivity")
push_popup_activity=${push_popup_activity}
## 푸시 "수신"시 동작하는 Class이름 입니다.
## CustomPushReceiver가 필요할 경우 사용됩니다.
## 직접 구현 하셔야하며 필요하지 않을 경우 작성하지 않으셔도 됩니다.
push_receiver_class=com.example.CustomPushReceiver
# Push수신 시 출력되는 상단의 Notification을 터치 했을 때, broadcasting할 intent action을 의미합니다.
noti_receiver=${noti_receiver}
## 푸시 수신시 표시되는 상단 알림 창을 "클릭"했을때 동작하는 Class이름 입니다
## App에서 따로 직접 구현해야 합니다
noti_receiver_class=com.example.PushNotiReceiver
## 앱 아이콘 오른쪽 상단에 표시되는 벳지의 표시 유무입니다 (Y는 표시, N은 미표시)
noti_o_badge=Y
## Android 7.0이상 부터 적용되는 알림 그룹화 기능입니다 (Y는 그룹화, N은 그룹화 비활성화)
noti_group_flag=YProject Number & API Key 가져오는 방법은 별도의 가이드 문서 참조.push_popup_showing_flag를 Y로 두시면 예전과 동일하게 사용가능 합니다.
noti_group_flag은 Android 7.0이상에서 적용되는 기능입니다. 같은 앱에서 Notification을 여러개 수신하게 되면 하나의 그룹으로 지정해서 한번에 여러개 메세지를 보실 수 있습니다. (아래 이미지 참고)

Google 정책상 BroadcastReceiver가 암시적 Intent에서 명시적 Intent로 변경됨에 따라 Class 경로를 지정하게 되었습니다
Android 8.0에서 알림 배지가 추가됨에 따라 noti_o_badge 값이 추가되었습니다.
Push수신 시 출력되는 Notification Bar의 터치에 대한 특정 로직을 삽입하고자 할 때, 작성하는 class 입니다.
NotiReceiver 셋팅은 pushNotiReceiver 추가항목을 참조 하시기 바랍니다.
BroadcaseReceiver를 extends받아서 작성 합니다.
intent에서 Data를 가져오는 방법은 Push Data항목을 참조 하시기 바랍니다.
package com.custom.push;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class CustomNotiReceiverClass extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// notification 터치 시에 “push notiMsg:${notiMsg}” 라는 텍스트를 Toast로 출력합니다.
Toast.makeText(contetx, "push notiMsg:" + intent.getStringExtra(APMS.KEY_NOTI_MSG),
Toast.LENGTH_SHORT).show();
}
}onReceivePushListener의 intent에서 참조 할 수 있으며, 다음과 같이 데이터를 가져 올 수 있습니다.
intent.getStringExtra(APMS.KEY_MSG_ID) // "i" - 메세지 ID
intent.getStringExtra(APMS.KEY_NOTI_TITLE) // "notiTitle" - notification에 출력될 타이틀
intent.getStringExtra(APMS.KEY_NOTI_MSG) // "notiMsg" - notification에 출력될 메시지 내용
intent.getStringExtra(APMS.KEY_NOTI_IMG) // "notiImg" - notification에 출력될 이미지 URL
intent.getStringExtra(APMS.KEY_MSG) // "message" - (리치) 푸시 내용
intent.getStringExtra(APMS.KEY_SOUND) // "sound" - 푸시 수신 시 출력될 사운드
intent.getStringExtra(APMS.KEY_MSG_TYPE) // "t" - 메시지 타입 : H – html, T – Text, L – Link
intent.getStringExtra(APMS.KEY_DATA) // "d" - 추가 데이터PushMsg pushMsg = new PushMsg(intent.getExtras());
pushMsg.msgId // 메세지 ID
pushMsg.notiTitle // notification에 출력될 타이틀
pushMsg.notiMsg // notification에 출력될 메시지 내용
pushMsg.notiImg // notification에 출력될 이미지 URL
pushMsg.message // (리치) 푸시 내용
pushMsg.sound // 푸시 수신 시 출력될 사운드
pushMsg.msgType // 메시지 타입 : H – html, T – Text, L – Link
pushMsg.data // 추가 데이터등록된 Notification을 터치시 이동하는 Receiver에서 다음과 같이 정의한다.
try {
PushMsg pushMsg = new PushMsg(intent.getExtras());
JSONObject btnLink = new JSONObject(pushMsg.data);
Toast.makeText(context, btnLink.get("l").toString(), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}수신함에서 appLink 추출
Msg msg = APMS.getInstance(context).selectMsgWhereUserMsgId(${해당하는 메세지에대한 UserMsgId});
Toast.makeText(context, msg.appLink, Toast.LENGTH_SHORT).show();이 방법은 SDK와 별도로 제공되는 옵션입니다. 해당 앱에 직접 설정 하셔야 합니다.
삼성 계열의 장치에서만 동작하도록 설정 되어 있습니다.
동작은 방법은 충전을 위해서 케이블을 꼽을 때와 뽑을 때 동작을 하고 장치를 재부팅 시켰을 경우 동작을 하도록 하여 절전 기능으로 안 빠지게 되어 있습니다.
유의 사항은 앱을 사용 중에 충전 케이블을 꼽거나 뽑을 때 투명한 Activity가 화면에 뜨게 되어 눈에는 보이지 않지만 사용자가 계속 터치 중이거나 하면 잠깐 터치가 안될 수 도 있습니다
Androidmanifest.xml 설정
<activity
android:name="${Activity_Class}"
android:excludeFromRecents="true"
android:taskAffinity=":avoidSmartManager"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<receiver
android:name="${Receiver_Class}"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>Activity Class (해당 클래스 명은 바꾸셔도 됩니다)
public class AvoidSmartManagerActivity extends Activity {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CLog.e("AvoidSmartManagerActivity!!!!");
finish();
}
}Receiver Class (해당 클래스 명은 바꾸셔도 됩니다)
public class AvoidSmartManagerReceiver extends BroadcastReceiver {
private static final String SMART_MANAGER_PACKAGE_NAME = "com.samsung.android.sm";
@Override
public void onReceive (final Context context, Intent intent) {
CLog.d("onReceive() " + intent);
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())
|| Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) {
boolean isSmartManagerExist = false;
try {
context.getPackageManager().getPackageInfo(SMART_MANAGER_PACKAGE_NAME, PackageManager.GET_META_DATA);
isSmartManagerExist = true;
} catch (PackageManager.NameNotFoundException e) {
}
if (isSmartManagerExist) {
new Handler().postDelayed(new Runnable() {
@Override
public void run () {
Intent serviceIntent = new Intent(context, AvoidSmartManagerActivity.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(serviceIntent);
}
}, new Random().nextInt(3000));
}
}
}
}6.0 이상의 Device일 경우에 Permission 확인 후 추가를 해주어야 합니다.
// Device 가 6.0 이상일 경우
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
// 확인할 Permission 들을 추가할 ArrayList
ArrayList<String> strArrPermission = new ArrayList<String>();
// READ_PHONE_STATE 퍼미션이 존재 하지 않을 경우 퍼미션 추가 팝업을 띄위기 위해 ArrayList 에 추가
int permissionCheck = ContextCompat.checkSelfPermission([context],
Manifest.permission.READ_PHONE_STATE);
// 만약 해당 퍼미션이 없을 경우 ArrayList에 확인할 퍼미션을 추가합니다.
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
CLog.i("READ_PHONE_STATE PERMISSION_DENIED");
strArrPermission.add(Manifest.permission.READ_PHONE_STATE);
strArrPermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
// Permission 팝업을 띄위기 위한 String array 를 만들어 퍼미션 요청을 수행합니다.
if (strArrPermission.size() > 0) {
String[] strPermission = new String[strArrPermission.size()];
for (int i=0; i<strArrPermission.size(); i++) {
strPermission[i] = strArrPermission.get(i);
}
ActivityCompat.requestPermissions((Activity) this, strPermission, 0);
}
}android {
compileSdkVersion 26
}com.android.support:support-v4라이브러리는 26.1.0이상을 필수적으로 요구합니다dependencies {
...
compile 'com.android.support:support-v4:26.1.0'
}dependencies {
...
compile 'com.google.firebase:firebase-core:16.0.5'
compile 'com.google.firebase:firebase-messaging:17.3.4'
}28.0.3 이상으로 설정해야 합니다.android {
compileSdkVersion 26
buildToolsVersion '28.0.3'
}google()을 추가해야합니다buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.google.gms:google-services:4.1.0'
}
}
allprojects {
repositories {
jcenter()
google()
}
}