> For the complete documentation index, see [llms.txt](https://docs.dfinery.ai/developer-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dfinery.ai/developer-guide/platform/android/action/push-notification.md).

# 푸시

DFINERY는 Firebase Cloud Messaging을 사용하여 푸시를 수신받으므로 어플리케이션에서 Firebase 연동이 필요합니다.

## 시작하기 전에

### 푸시 알림 수신 허용 유무 등록하기

광고성 목적이 있는 푸시의 경우 [정보통신망법](https://www.law.go.kr/%EB%B2%95%EB%A0%B9/%EC%A0%95%EB%B3%B4%ED%86%B5%EC%8B%A0%EB%A7%9D%20%EC%9D%B4%EC%9A%A9%EC%B4%89%EC%A7%84%20%EB%B0%8F%20%EC%A0%95%EB%B3%B4%EB%B3%B4%ED%98%B8%20%EB%93%B1%EC%97%90%20%EA%B4%80%ED%95%9C%20%EB%B2%95%EB%A5%A0/%EC%A0%9C50%EC%A1%B0)에 따라 유저에게 사전 수신동의를 받아야 합니다. 유저에게 푸시 알림이 허용되었다는 정보를 DFINERY에 등록하기 위해서 다음의 일련의 작업을 수행하여 주시기 바랍니다.

1. 유저에게 푸시 알림 허용에 대한 고지하기
2. 유저의 허용/거부 의사에 대한 값을 유저 프로필에 등록

[알림 수신 동의 설정하기](/developer-guide/platform/android/user-profile.md#consent)를 참고하여 유저가 동의한 항목에 대해 값을 입력해주시기 바랍니다. 아래 코드는 푸시 채널에 관해 정보성, 광고성 수신 동의를 허용한 예시입니다.

{% tabs %}
{% tab title="Java" %}

```java
Map<String, Object> consents = new HashMap<>();
consents.put(DFUserProfile.PUSH_ADS_OPTIN, true);
DfineryProperties.setUserProfiles(consents);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val consents = mapOf<String, Any>(
    DFUserProfile.PUSH_ADS_OPTIN to true
)
DfineryProperties.setUserProfiles(consents)
```

{% endtab %}
{% endtabs %}

### 콘솔에서 Firebase 정보 등록하기

[DFINERY 콘솔](https://console.dfinery.ai)에서 부가설정/채널 부가 설정/푸시/Android 설정관리에 들어가 발신자 ID를 입력하고 JSON 형식의 Firebase 사용자 인증 정보 비공개 키 파일을 업로드합니다.

* [발신자 ID 확인 방법](#check-sender-id)
* [Firebase 사용자 인증 정보 비공개 키 파일 발급 방법](#create-firebase-private-key)

### Support Library 의존성 추가하기

DFINERY는 푸시 알림을 작성하는데 [Support Library](https://developer.android.com/jetpack/androidx/releases/core?hl=ko)를 필요로 하므로 다음의 일련의 단계를 완료하세요.

{% hint style="warning" %}
`androidx.core:core`는 `1.5.0` 이상 버전을 사용해야 합니다.
{% endhint %}

1. 앱의 모듈 디렉터리 내에 있는 `build.gradle` 파일을 엽니다.
2. dependencies에 Support Library 의존성을 추가합니다.

{% tabs %}
{% tab title="build.gradle" %}

```groovy
 dependencies {
    implementation 'androidx.core:core:1.9.0'
}
```

{% endtab %}

{% tab title="build.gradle.kts" %}

```groovy
 dependencies {
    implementation ("androidx.core:core:1.9.0")
}
```

{% endtab %}
{% endtabs %}

## Firebase Cloud Messaging 연동

### Android 프로젝트에 Firebase 추가하기

Firebase에서 제공되는 [Android 프로젝트에 Firebase 추가](https://firebase.google.com/docs/android/setup?hl=ko#next_steps)의 지시사항에 따라 Android 프로젝트에 Firebase를 추가합니다.

### Firebase Cloud Messaging 설정하기

Firebase에서 제공되는 [Android에서 Firebase 클라우드 메시징 클라이언트 앱 설정](https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko)의 지시사항에 따라 다음의 항목을 적용합니다.

* [앱 매니페스트에 FirebaseMessagingService를 상속받는 서비스 추가](https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko#manifest)
* [Android 13 이상에서 적용되는 런타임 알림 권한 요청 작성](https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko#request-permission13)
* [기기 등록 토큰 액세스 연동](https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko#sample-register)

## 토큰을 DFINERY에 연동하기

Firebase에서 발급된 토큰을 DFINERY에 연동하기 위해서 다음과 같이 작성해 주시기 바랍니다.

### 현재 등록 토큰 가져오기 시 연동

{% hint style="success" %}

* Application을 상속받은 객체의 [onCreate()](https://developer.android.com/reference/android/app/Application#onCreate\(\)) 메소드에 작성하시는 것을 권장드립니다.
* 토큰 값은 SDK에서 캐시하므로 여러번 호출해도 같은 값일 경우 서버에 호출되지 않습니다.
  {% endhint %}

{% tabs %}
{% tab title="Java" %}

```java
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
    @Override
    public void onComplete(@NonNull Task<String> task) {
        if (!task.isSuccessful()) {
            Log.w(TAG, "Fetching FCM registration token failed", task.getException());
            return;
        }

        // Get new FCM registration token
        String token = task.getResult();
        DfineryProperties.setPushToken(token);
    }
});
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result
    DfineryProperties.setPushToken(token)
})
```

{% endtab %}
{% endtabs %}

### 토큰 생성 모니터링 시 연동

FirebaseMessagingService를 상속받은 클래스에서 [onNewToken(String)](https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService#onNewToken\(java.lang.String\)) 메소드를 Override 하여 토큰을 DFINERY에 등록합니다.

{% tabs %}
{% tab title="Java" %}

```java
@Override
public void onNewToken(@NonNull String token) {
    Log.d(TAG, "Refreshed token: " + token);
    DfineryProperties.setPushToken(token);
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onNewToken(token: String) {
    Log.d(TAG, "Refreshed token: $token")
    DfineryProperties.setPushToken(token)
}
```

{% endtab %}
{% endtabs %}

## 푸시 알림 채널을 DFINERY에 연동하기

### 푸시 알림 채널 생성

Android 8.0부터는 알림을 수신받기 위해 알림 채널 생성이 필요합니다. Android에서 제공하는 [알림 채널 만들기 및 관리](https://developer.android.com/training/notify-user/channels?hl=ko)의 지시사항과 [알림 채널 생성 따라해보기](#create-notification-channel)를 참고하여 알림 채널을 생성해주시기 바랍니다.

### 생성한 푸시 알림 채널 ID 등록

DfineryConfig의 `setDefaultNotificationChannelId()` 메소드를 사용하거나 `res/values/dfinery.xml`을 사용하여 생성한 알림 채널의 ID를 등록합니다.

{% tabs %}
{% tab title="Java" %}

```java
DfineryConfig config = new DfineryConfig.Builder()
    .setDefaultNotificationChannelId("NOTIFICATION_CHANNEL_ID")
    .build();
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val config = DfineryConfig.Builder()
    .setDefaultNotificationChannelId("NOTIFICATION_CHANNEL_ID")
    .build()
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config)
```

{% endtab %}

{% tab title="dfinery.xml" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="com_igaworks_dfinery_default_notification_channel_id" translatable="false">
      NOTIFICATION_CHANNEL_ID
    </string>
</resources>
```

{% endtab %}
{% endtabs %}

## 푸시 알림 아이콘 설정하기

푸시 알림을 표시하기 위해서는 아이콘 설정이 필요합니다. DfineryConfig의 `setNotificationIcon()` 메소드를 사용하거나 `res/values/dfinery.xml`을 사용하여 아이콘을 설정해주시기 바랍니다.

{% hint style="info" %}
알림 아이콘은 시스템이 색조(tint)를 적용할 수 있으므로, 투명한 배경을 사용하는 것이 좋습니다.
{% endhint %}

{% tabs %}
{% tab title="Java" %}

```java
DfineryConfig config = new DfineryConfig.Builder()
    .setNotificationIcon(R.drawable.icon)
    .build();
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val config = DfineryConfig.Builder()
    .setNotificationIcon(R.drawable.icon)
    .build()
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config)
```

{% endtab %}

{% tab title="dfinery.xml" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <drawable name="com_igaworks_dfinery_notification_icon">
      @drawable/NOTIFICATION_ICON_DRAWABLE 
    </drawable>
</resources>
```

{% endtab %}
{% endtabs %}

## 푸시 알림 강조색 지정하기 <a href="#push_accent_color" id="push_accent_color"></a>

알림 아이콘 강조색은 `setNotificationAccentColor(int argb)`를 호출하여 변경할 수 있습니다. 색상을 지정하지 않으면 시스템 기본 색상으로 표시됩니다.

{% hint style="info" %}

* 푸시 알림 강조색은 사용 중인 OS 버전과 런처에 따라 다르게 표시될 수 있습니다.
* `dfinery.xml`을 사용할 경우 Hex color codes 형태로 입력해야 합니다.
  {% endhint %}

{% tabs %}
{% tab title="Java" %}

```java
DfineryConfig config = new DfineryConfig.Builder()
    .setNotificationAccentColor(Color.parseColor("#0c8900"))
    .build();
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val config = DfineryConfig.Builder()
    .setNotificationAccentColor(Color.parseColor("#0c8900"))
    .build()
Dfinery.getInstance().init(this, "{YOUR_SERVICE_ID}", config)
```

{% endtab %}

{% tab title="dfinery.xml" %}

```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="com_igaworks_dfinery_notification_accent_color" translatable="false">
      #E00052
    </string>
</resources>
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="푸시 알림 강조색 지정안함" %}
![System Default Color](/files/oEKCDqEcfg3fcVqacYAI)
{% endtab %}

{% tab title="푸시 알림 강조색 지정함" %}
![Userset Accent Color](/files/BJhkLjCVWTvcPy3sj05z)
{% endtab %}
{% endtabs %}

## 푸시 알림 수신 처리하기

푸시가 수신되면 FirebaseMessagingService를 상속받은 객체에 푸시 알림이 수신 됩니다. DFINERY는 수신된 푸시 페이로드를 토대로 알림을 생성하므로 해당 객체의 [onMessageReceived(RemoteMessage)](https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService#onMessageReceived\(com.google.firebase.messaging.RemoteMessage\)) 메소드 내에 다음과 같이 작성하여 주시기 바랍니다.

{% tabs %}
{% tab title="Java" %}

```java
@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    if(Dfinery.getInstance().handleRemoteMessage(getApplicationContext(), remoteMessage.getData())){
        //dfinery push
    }else{
        //This is not a push notification sent from Dfinery.
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onMessageReceived(remoteMessage: RemoteMessage) {
  if(Dfinery.getInstance().handleRemoteMessage(applicationContext, remoteMessage.getData())){
        //dfinery push
    }else{
        //This is not a push notification sent from Dfinery.
    }
}
```

{% endtab %}
{% endtabs %}

## 푸시 알림 클릭 처리하기

딥 링크 정보를 가지고 있는 푸시를 클릭하면 딥링크에 설정된 [Activity](https://developer.android.com/reference/android/app/Activity)가 실행됩니다. 딥링크가 정보가 없을 경우 `android.intent.action.MAIN` 액션을 가지고 있는 Activity가 실행됩니다.

{% hint style="info" %}
Activity에 딥 링크를 연동하는 방법은 Android에서 제공하는 [앱 콘텐츠 딥 링크 만들기](https://developer.android.com/training/app-links/deep-linking?hl=ko)를 참고하여 주시기 바랍니다.
{% endhint %}

해당하는 Activity에 `setIntent()` 코드를 추가해 주시기 바랍니다.

{% tabs %}
{% tab title="Java" %}

```java
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent); 
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    setIntent(intent)
}
```

{% endtab %}
{% endtabs %}

### 수동으로 클릭 이벤트 처리하기 (선택 사항) <a href="#handle-push-notification-opened" id="handle-push-notification-opened"></a>

Dfinery SDK는 기본적으로 Activity Lifecycle을 통해 푸시 클릭을 **자동으로 트래킹**하므로, 별도의 코드를 작성하지 않아도 됩니다. 다만, 하이브리드 앱의 브릿지 구현이나 특수한 인텐트 제어가 필요한 경우 아래 메서드를 사용하여 수동으로 처리할 수 있습니다.

* **메서드**: `Dfinery.getInstance().handlePushNotificationOpened(Activity activity)`
* **특징**: 이 메서드를 직접 호출하더라도 SDK 내부의 **중복 처리 방지 로직**이 작동하여 클릭 이벤트가 중복으로 기록되지 않으니 안심하고 사용하셔도 됩니다.

{% hint style="info" %}
SDK `2.6.0` 이상 버전을 사용할 경우 필요시 `Dfinery.getInstance().handlePushNotificationOpened(Intent intent)` 사용이 가능합니다.
{% endhint %}

{% tabs %}
{% tab title="Java" %}

```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Dfinery.getInstance().handlePushNotificationOpened(this);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
    Dfinery.getInstance().handlePushNotificationOpened(this);
}
```

#### 클릭 인텐트 데이터 직접 활용하기 (선택 사항) <a href="#handle-push-notification-data" id="handle-push-notification-data"></a>

**1. 인텐트 엑스트라 키(Intent Extra Keys) 명세**

Activity로 전달되는 Intent에는 다음과 같은 키 값으로 데이터가 담겨 있습니다. 모든 데이터는 **JSON String** 형태 혹은 **Boolean**으로 전달됩니다.

| Key                                               | 타입            | 설명                                         |
| ------------------------------------------------- | ------------- | ------------------------------------------ |
| `com.igaworks.dfinery.push.extra.PUSH_PAYLOAD`    | String (JSON) | 수신된 푸시 데이터 전체 (`dfn` 내부 데이터와 동일)           |
| `com.igaworks.dfinery.push.extra.CLICK_RESULT`    | String (JSON) | **사용자가 실제 클릭한 지점**(알림 본체 혹은 특정 버튼)의 액션 데이터 |
| `com.igaworks.dfinery.push.extra.IS_DFINERY_PUSH` | Boolean       | Dfinery에서 발송한 푸시인지 여부                      |

**2. 데이터 상세 명세**

{% hint style="info" %}
수신 시 전달받은 알림 원본의 정보는 [푸시 페이로드 명세](https://docs.dfinery.ai/developer-guide/common/specification/android-push-payload)를 참고하여 주시기 바랍니다.
{% endhint %}

**PUSH\_PAYLOAD (`dfn` 내부 구조)**

전체 페이로드에는 알림의 원본 정보가 모두 포함되어 있습니다.

```json
{
  "tit": "sign up",
  "bd": "내용입니다",
  "img": "https://...",
  "n_id": 1715243891,
  "u_id": "80em2be",
  "click_act": { ... }, // 기본 클릭 설정
  "btn": [ ... ],       // 버튼 설정 리스트
  "is_test": 1
}
```

**CLICK\_RESULT (정제된 클릭 데이터)**

사용자가 **실제로 누른 지점**의 데이터만 SDK가 선별하여 제공합니다. 버튼을 클릭했다면 해당 버튼의 정보가, 알림 본체를 클릭했다면 본체의 `click_act` 정보가 담깁니다.

```json
{
  "l_id": "1",
  "l_type": "Content",
  "act_type": "Deeplink",
  "uri": "dfinery://pushlist"
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
override fun onCreate() {
    super.onCreate()
    setContentView(R.layout.activity_main)
    Dfinery.getInstance().handlePushNotificationOpened(this)
}

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    setIntent(intent)
    Dfinery.getInstance().handlePushNotificationOpened(this)
}
```

{% endtab %}
{% endtabs %}

## 완료

푸시 설정이 완료되었습니다.

## 더 알아보기

### 알림 채널 생성 따라해보기 <a href="#create-notification-channel" id="create-notification-channel"></a>

알림 채널을 생성하는 예제입니다. [Android에서 제공하는 예제](https://developer.android.com/develop/ui/views/notifications/channels?hl=ko#CreateChannel)도 있으므로 참고 바랍니다.

**1. 알림 채널을 생성합니다.**

알림 채널 API는 [Android 8.0](https://developer.android.com/about/versions/oreo?hl=ko)이상에서 지원합니다.

* 첫번째 파라미터 id는 알림 채널의 ID를 의미합니다.
* 두번째 파라미터 name은 알림 채널의 이름을 의미합니다. 해당 값은 `설정/알림`에서 유저에게 노출됩니다.
* 세번째 파라미터 importance는 이 알림 채널로 수신될 푸시 알림의 [중요도](https://developer.android.com/develop/ui/views/notifications/channels?hl=ko#importance)를 의미합니다.

{% tabs %}
{% tab title="Java" %}

```java
NotificationChannel notificationChannel = new NotificationChannel("NOTIFICATION_CHANNEL_ID", "NOTIFICATION_CHANNEL_NAME", NotificationManager.IMPORTANCE_HIGH);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val notificationChannel = NotificationChannel("NOTIFICATION_CHANNEL_ID", "NOTIFICATION_CHANNEL_NAME", NotificationManager.IMPORTANCE_HIGH)
```

{% endtab %}
{% endtabs %}

**2. 알림 채널의 설명을 설정합니다. (Optional)**

해당 값은 `설정/알림`에서 유저에게 노출됩니다.

{% tabs %}
{% tab title="Java" %}

```java
notificationChannel.setDescription("NOTIFICATION_CHANNEL_DESCRIPTION");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
notificationChannel.description = "NOTIFICATION_CHANNEL_DESCRIPTION"
```

{% endtab %}
{% endtabs %}

**3. 알림 채널의 진동 유무를 설정합니다. (Optional)**

알림 채널의 값은 DFINERY 콘솔에서 설정 한 값 중 '앱 실행 중 푸시 메시지 노출'을 제외한 모든 설정보다 항상 우선시됩니다.

{% tabs %}
{% tab title="Java" %}

```java
notificationChannel.enableVibration(true);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
notificationChannel.enableVibration(true)
```

{% endtab %}
{% endtabs %}

**4. 알림 채널의 알림음을 설정합니다. (Optional)**

시스템 기본 알림음을 재생하도록 설정한 예제입니다.

{% tabs %}
{% tab title="Java" %}

```java
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
AudioAttributes audioAttributes = new AudioAttributes.Builder()
        .setUsage(AudioAttributes.USAGE_NOTIFICATION)
        .build();
notificationChannel.setSound(soundUri, audioAttributes);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val audioAttributes = AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
    .build()
notificationChannel.setSound(soundUri, audioAttributes)
```

{% endtab %}
{% endtabs %}

**5. NotificationManager에 생성한 알림 채널을 등록합니다.**

{% tabs %}
{% tab title="Java" %}

```java
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(notificationChannel)
```

{% endtab %}
{% endtabs %}

**6. 완료되었습니다.**

### Firebase 사용자 인증 정보 비공개 키 파일 발급 따라해보기 <a href="#create-firebase-private-key" id="create-firebase-private-key"></a>

**1.** [**서비스 계정**](https://console.cloud.google.com/iam-admin/serviceaccounts)**에 접속합니다.**

**2. 발급 하고 싶은 키의 프로젝트를 선택합니다.**

프로젝트가 없을 경우 Firebase 프로젝트 생성이 되지 않았다는 뜻이므로 [Android 프로젝트에 Firebase 추가하기](https://firebase.google.com/docs/android/setup?hl=ko#next_steps)를 참고하여 Firebase 프로젝트를 생성합니다.

<img src="/files/DxLClT8lWHU1xzedby9D" alt="select a recent project" data-size="original">

**3. 우측 하단의 작업에서 ⋮를 클릭합니다.**

<img src="/files/dvrsjLpBYuP0UiKeg77r" alt="click a action" data-size="original">

**4. 드롭다운에서 키 관리를 클릭합니다.**

<img src="/files/C5yO3hKpoU9Bn5IKXZq3" alt="click a manage keys" data-size="original">

**5. 키 추가를 선택합니다.**

이미 생성된 키가 있을 경우, 기존에 키를 생성한 이력이 있다는 뜻이며 해당 키를 사용하시면 됩니다. 해당 키를 찾을 수 없을 경우 새로 키를 생성하여 주시기 바랍니다.

<img src="/files/5F9MXBPZ3nAIZw98PS3C" alt="click a add key" data-size="original">

**6. 드롭다운에서 새 키 만들기를 클릭합니다.**

<img src="/files/bvdhm20VIvWCUWrF1YZc" alt="click a create new key" data-size="original">

**7. JSON을 선택 후 만들기를 클릭합니다.**

<img src="/files/04x6v0wpAr02d4gQ9YT4" alt="create a key" data-size="original">

**8. 키 발급이 완료되었습니다.**

### 발신자 ID 확인 방법 <a href="#check-sender-id" id="check-sender-id"></a>

1. [Firebase Console](https://console.firebase.google.com/)로 이동합니다.
2. 프로젝트를 선택합니다.
3. 좌측 패널에서 프로젝트 개요 오른쪽 ⚙️ 아이콘을 클릭합니다.
4. 프로젝트 설정을 클릭합니다.
5. 프로젝트 설정 상단 탭에서 클라우드 메시징을 클릭합니다.
6. [발신자 ID](https://firebase.google.com/docs/cloud-messaging/concept-options?hl=ko#senderid)를 확인합니다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dfinery.ai/developer-guide/platform/android/action/push-notification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
