> For the complete documentation index, see [llms.txt](https://developers.fingerpush.com/app-push/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.fingerpush.com/app-push/sdk-manual/android.md).

# Android SDK 매뉴얼

{% hint style="info" %}
본 가이드는 Android Studio 21.1.1 기준으로 작성되었습니다.

SDK가 지원하는 최소 버전은 Android API 21 이상입니다.
{% endhint %}

### SDK 다운로드

1\) SDK를 다운로드 합니다.

{% content-ref url="/pages/teXz81azxFOb0wIYwH4F" %}
[SDK 다운로드](/app-push/sdk-manual/sdk-down.md)
{% endcontent-ref %}

### FCM APP 생성

{% hint style="danger" %}
기존 GCM 프로젝트가 있는 경우, 반드시 기존 GCM 프로젝트를 추가해서 사용해야 합니다.
{% endhint %}

1\) 프로젝트를 추가합니다.

![](/files/jW9rw0HUSPswSIW5fJE9)

2\) 앱 추가 후, 다운로드한 'google-services.json' 파일을 프로젝트 앱 모듈 루트 디렉토리로 이동 시킵니다.

![](/files/5QDkRsa47TCiP9x7IG57) ![](/files/GkExtKOPTwi7DiTtsJ5h)

3\) '프로젝트 설정 > 서비스 계정' 메뉴로 이동하여 '새 비공개 키 생성' 버튼을 클릭하여 비공개 키(\*.json)를 생성 및 다운로드 받습니다.

<figure><img src="/files/LifGyEKBJLoAaQpv4EP2" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
비공개 키는 복수로 생성할 수 있으나, 생성된 키는 1회만 다운로드 가능하니 안전한 위치에 저장합니다.
{% endhint %}

<div data-full-width="true"><figure><img src="/files/KvhkLzB2DKIJiuU5Duq4" alt="" width="375"><figcaption></figcaption></figure></div>

4\) 비공개 키를 생성하고 '클라우드 메시징' 메뉴에서 FCM API(V1)이 '사용 중지됨' 된 경우 'Google Cloud Console > APIS' 로 이동하여 사용 설정해야 합니다.

<figure><img src="/files/K0UT8YBaWmldEvMhCWYE" alt=""><figcaption></figcaption></figure>

{% embed url="<https://console.cloud.google.com/apis>" %}

5\) API 항목에서 Firebase Cloud Messaging API 를 선택한 뒤, 사용을 클릭하여 '사용 설정됨' 으로 변경되어 있는지 확인합니다.

<figure><img src="/files/OhecOm2emF7EZRIrjoS6" alt=""><figcaption></figcaption></figure>

### 핑거푸시 사용자 콘솔 APP 생성

1\) 핑거푸시 사용자 콘솔에서 '앱 등록' 버튼을 누른 뒤 앱을 생성합니다.

<figure><img src="/files/2tjl5Yj4dxJ27bmkvpF1" alt=""><figcaption></figcaption></figure>

2\) '앱 설정' 메뉴로 이동하면 App Key, App Secret을 확인할 수 있습니다.

<figure><img src="/files/rvN4XjAmm8xiMTrr7d4p" alt=""><figcaption></figcaption></figure>

3\) 플랫폼 설정 내 FCM > 설정을 클릭하여 다운로드 받은 비공개 키(\*.json) 및 프로젝트 패키지명을 입력하고 등록합니다.

<figure><img src="/files/GH43dGTns1vMTYmlYItd" alt=""><figcaption></figcaption></figure>

<div align="left"><figure><img src="/files/MEbJ70BB50yu5su1VWGN" alt=""><figcaption></figcaption></figure> <figure><img src="/files/ZsF5Lcm6IsevJlE1xSHr" alt=""><figcaption></figcaption></figure></div>

### SDK 적용하기

#### Gradle 설정

a. 프로젝트 레벨의 build.gradle 에 'com.google.gms:google-services' 라이브러리와 kotlin 라이브러리를 추가합니다.

{% code title="<project>/build.gradle" %}

```
buildscript {
    ...
    dependencies {
        ...
        classpath 'com.google.gms:google-services:4.4.3'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"
    }
}
```

{% endcode %}

b. 앱 레벨의 build.gradle 하단에 google-services 플러그인을 추가합니다.

{% code title="<project>/<app-module>/build.gradle" %}

```
apply plugin: 'com.google.gms.google-services'
```

{% endcode %}

c. 다운받은 SDK 를 libs 폴더로 옮긴 뒤, 앱 레벨의 build.gradle 에 핑거푸시 SDK 및 firebase 모듈을 추가합니다.

{% code title="<project>/<app-module>/build.gradle" %}

```
dependencies {
    ...
    implementation files('libs/fingerpush_3.8.2.aar')
    implementation 'com.google.firebase:firebase-core:21.1.1'
    implementation 'com.google.firebase:firebase-messaging:24.1.2'
}
```

{% endcode %}

d. gradle.properties 파일에서 두 개의 플래그를 사용합니다.

{% code title="gradle.properties" %}

```
android.useAndroidX=true
android.enableJetifier=true
```

{% endcode %}

#### 핑거푸시 키 설정

a. Application class에서 핑거푸시 키를 설정합니다.

{% hint style="danger" %} <mark style="color:red;">앱키, 앱시크릿 변경시 기존 설정값들이 적용되지 않을 수 있기 때문에 앱 삭제 후 재설치를 권장드립니다.</mark>
{% endhint %}

```java
FingerPushManager.setAppKey(String appKey);
FingerPushManager.setAppSecret(String secretKey);
```

#### 알림 권한 추가 및 요청

Android 13(API Level33) 이상에서 알림 수신을 위해 권한 요청 및 허용되어야 합니다.

{% code title="AndroidManifest.xml" %}

```xml
<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>
```

{% endcode %}

{% code title="MainActivity.java" %}

```java
// 핑거푸시 단말기 등록 (앱 실행 시 매번 호출되어야 합니다.)
private void setDevice() {
    FingerPushManager.getInstance(this).setDevice(new NetworkUtility.ObjectListener() {
        @Override
        public void onComplete(String code, String message, JSONObject jsonObject) {
            // code 200, 201 단말기 등록.
        }

        @Override
        public void onError(String code, String message) {
            // code 504 단말기가 이미 등록됨.
        }
    });
}

// 알림 권한 요청 결과
private final ActivityResultLauncher<String> requestPermissionLauncher =
        registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
            setDevice()
        });

// 알림 권한 요청
private void askNotificationPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
            // 이미 알림 권한이 허용된 상태
            setDevice();
        } else {
            // 사용자에게 알림 권한 요청
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
        }
    } else {
        setDevice();
    }
}
```

{% endcode %}

#### 채널 생성

{% hint style="danger" %}
Android 8(API Level 26) 이상은 Channel 을 생성해야 알림이 노출됩니다.

채널 생성은 앱을 시작할 때 생성하는게 안전합니다.

Channel 에 대한 상세 내용은 아래 주소를 참고바랍니다.
{% endhint %}

{% embed url="<https://developer.android.com/training/notify-user/channels>" %}

{% code title="MainActivity.java" %}

```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    String channelId  = getString(R.string.default_notification_channel_id);
    String channelName = getString(R.string.default_notification_channel_name);
    fingerNotification.createChannel(channelId, channelName);
}   
```

{% endcode %}

#### 알림 수신부

a. IntentService 클래스를 생성한 뒤, 'FingerPushFcmListener' 를 상속받습니다.

{% code title="IntentService.java" %}

```java
public class IntentService extends FingerPushFcmListener {
    @Override
    public void onMessage(Context context, Bundle data) {
        createNotification(data);
    }
}
```

{% endcode %}

b. onMessage(Context context, Bundle data) 에서 PayLoad 데이터를 확인할 수 있으며, 푸시 알림을 구현할 수 있습니다.

#### Payload 데이터

```
data.msgTag : 메세지 번호
data.code : CD:1;IM:0;PT:DEFT    <!-- (CD:커스텀데이터 여부(0없음, 1있음), IM:이미지여부(0없음, 1있음) ,PT:메세지타입 (DEFT:일반, LNGT:롱푸시, STOS:타겟푸시)  -->
data.time : 보낸시간
data.appTitle : 핑거푸시 앱이름
data.badge : 뱃지
data.sound : 사운드
data.title : 메세지 제목
data.message : 메세지내용
data.weblink : 웹링크 url
data.labelCode : 라벨코드
data.img : 이미지 여부            <!-- (0:없음;1:있음) -->
data.imgUrl : 이미지url
data.cd1 : 커스텀 데이터 
data.cd2 : 커스텀 데이터
data.cd3 : 커스텀 데이터
```

#### 알림 생성

기본 Notification 생성방법입니다.

{% code title="IntentService.java" %}

```java
private void createNotification(Bundle data) {
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        String channelId  = getString(R.string.default_notification_channel_id);
        String channelName = getString(R.string.default_notification_channel_name);
        
        NotificationChannel mChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        mChannel.setDescription(null);
        mNotificationManager.createNotificationChannel(mChannel);
    }
 
    Intent intent = new Intent(IntentService.this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
 
    PendingIntent pendingIntent;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        pendingIntent = PendingIntent.getActivity(IntentService.this, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
    } else {
        pendingIntent = PendingIntent.getActivity(IntentService.this, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_CANCEL_CURRENT);
    }
 
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
        .setSmallIcon(R.mipmap.ic_launcher)
        .setContentTitle(data.getString("data.title"))
        .setContentText(data.getString("data.message"));
    mBuilder.setContentIntent(pendingIntent);
 
    mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
```

{% endcode %}

핑거푸시에서 제공하는 Notification 생성 방법입니다.

{% code title="IntentService.java" %}

```java
private void createNotification(Bundle data) {
    Intent intent = new Intent(IntentService.this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
 
    PendingIntent pendingIntent;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        pendingIntent = PendingIntent.getActivity(IntentService.this, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
    } else {
        pendingIntent = PendingIntent.getActivity(IntentService.this, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_CANCEL_CURRENT);
    }
 
    FingerNotification fingerNotification = new FingerNotification(this);
    fingerNotification.setNotificationIdentifier((int) System.currentTimeMillis());
    fingerNotification.setIcon(R.drawable.m_ic_launcher);
    fingerNotification.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
    fingerNotification.setVibrate(new long[]{0, 500, 600, 1000});
    fingerNotification.setLights(Color.parseColor("#ffff00ff"), 500, 500);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        fingerNotification.setColor(Color.rgb(0, 114, 162));
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        String channelId  = getString(R.string.default_notification_channel_id);
        String channelName = getString(R.string.default_notification_channel_name);
        fingerNotification.createChannel(channelId, channelName);
    }                  
    fingerNotification.showNotification(data, pendingIntent);
}
```

{% endcode %}

c. FingerPush MessageID, MessageLabel, PushMode 값은 아래 함수를 통해 확인 가능합니다.

```java
String messageId = FingerPushManager.getMessageId(Bundle bundle);
String messageLabel = FingerPushManager.getMessageLabel(Bundle bundle);
String pushMode = FingerPushManager.getPushMode(Bundle bundle);
```

#### allowBackup 설정

a. allowBackup 값을 false 로 설정합니다.

{% code title="AndroidManifest.xml" %}

```
<application
    ...
    android:allowBackup="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">
    ...
</application>
```

{% endcode %}

b. 푸시 수신을 서비스를 추가합니다.

{% code title="AndroidManifest.xml" %}

```xml
<manifest ...>
    ...
    <application ...>
        <service
            android:name=".IntentService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
    </application>
</manifest>
```

{% endcode %}

{% hint style="info" %}
ProGuard를 사용하는 경우 룰을 추가합니다.
{% endhint %}

```
# For FingerPush SDK
-dontwarn com.fingerpush.**
```

### Android API Reference

Android API 는 아래 링크에서 확인 할 수 있습니다.

{% content-ref url="/pages/fx2bsLtt8TXjECxe6mfO" %}
[Android API Reference](/app-push/api-reference/android.md)
{% endcontent-ref %}

## API 연동 결과 코드

<table><thead><tr><th width="150">코드</th><th width="326">내용</th><th>비고</th></tr></thead><tbody><tr><td>200</td><td>정상 처리</td><td></td></tr><tr><td>403</td><td>App_key, secret오류, 권한 없음</td><td></td></tr><tr><td>404</td><td>조회 대상 없음, 조회 결과 없음</td><td></td></tr><tr><td>500</td><td>처리 중 에러</td><td></td></tr><tr><td>503</td><td>필수 값 없음</td><td></td></tr><tr><td>504</td><td>이미 등록된 토큰</td><td>디바이스 등록에서만 사용</td></tr></tbody></table>
