Skip to content

고급 푸시 알림 예시

다음 가이드에서는 Braze SDK의 몇 가지 고급 푸시 알림 예제를 다룹니다.

Prerequisites

이 기능을 사용하려면 먼저 Android Braze SDK를 통합해야 합니다. 푸시 알림도 설정해야 합니다.

커스텀 알림 레이아웃

Braze 알림은 데이터 메시지로 전송되므로 앱이 백그라운드에 있을 때 시스템에서 자동으로 처리할 수 있는 알림 메시지와 달리 백그라운드에서도 항상 응답하고 그에 따라 동작을 수행할 수 있는 기회를 갖게 됩니다. 이와 같이 애플리케이션은 예를 들어 알림 트레이에 전달된 알림 내에서 개인화된 UI 요소를 표시하여 경험을 사용자 지정할 수 있습니다. 이 방식으로 푸시를 구현하는 것이 일부에게는 낯설 수 있지만, Braze의 잘 알려진 기능 중 하나인 푸시 스토리는 커스텀 뷰 컴포넌트를 사용하여 몰입감 있는 경험을 만드는 좋은 예입니다!

인터페이스를 사용하여 IBrazeNotificationFactory 인터페이스를 사용하여 Braze 푸시 알림이 표시되는 방식을 사용자 지정할 수 있습니다. BrazeNotificationFactory 을 확장하면 사용자에게 알림이 표시되기 전에 Braze가 공장의 createNotification() 메소드를 호출합니다. 그런 다음 Braze 대시보드 또는 REST API를 통해 전송된 사용자 지정 키-값 쌍이 포함된 페이로드를 전달합니다.

이 섹션에서는 야생동물 구조팀이 누가 가장 많은 올빼미를 구할 수 있는지 경쟁하는 새로운 게임 쇼의 호스트인 슈퍼 올빼미와 파트너가 됩니다. 이들은 Android 앱에서 실시간 업데이트 알림을 활용하여 진행 중인 경기의 상태를 표시하고 실시간으로 알림을 동적으로 업데이트할 수 있도록 하려고 합니다.

슈퍼 올빼미가 보여주고 싶은 라이브 업데이트는 '야생 조류 기금'과 '올빼미 구조대'의 진행 중인 경기를 보여줍니다. 현재 4쿼터, 스코어는 2-4로 OWL이 앞서고 있습니다.

1단계: 커스텀 레이아웃 추가하기

프로젝트에 하나 이상의 커스텀 알림 리모트뷰 레이아웃을 추가할 수 있습니다. 이는 접거나 펼쳤을 때 알림이 표시되는 방식을 처리하는 데 유용합니다. 디렉토리 구조는 다음과 비슷해야 합니다:

1
2
3
4
5
6
.
├── app/
└── res/
    └── layout/
        ├── liveupdate_collapsed.xml
        └── liveupdate_expanded.xml

각 XML 파일에서 커스텀 레이아웃을 만듭니다. Superb Owl은 축소 및 확장된 RemoteView 레이아웃에 대해 다음과 같은 레이아웃을 만들었습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/notification_title"
        style="@style/TextAppearance.Compat.Notification.Title"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>
샘플 코드 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_gravity="center"

        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/team1logo"
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:src="@drawable/team_default1"/>

        <TextView
            android:id="@+id/team1name"
            android:textAlignment="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1.6"
        android:layout_gravity="center"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/score"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2-4"
            android:textColor="#555555"
            android:textAlignment="center"
            android:textSize="32sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/timeInfo"
            android:textAlignment="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>


    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_gravity="center"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/team2logo"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:src="@drawable/team_default2"/>

        <TextView
            android:id="@+id/team2name"
            android:textAlignment="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</LinearLayout>

2단계: 사용자 지정 알림 팩토리 만들기

애플리케이션에서 MyCustomNotificationFactory.kt 이라는 이름의 새 파일을 만들어 확장자 BrazeNotificationFactory 을 확장하여 커스텀 리모트뷰 레이아웃이 표시되는 방식을 처리합니다.

다음 예시에서는 슈퍼 올빼미가 진행 중인 경기에 대한 리모트뷰 레이아웃을 표시하는 커스텀 알림 팩토리를 만들었습니다. 다음 단계에서는 getTeamInfo 이라는 새로운 메서드를 만들어 팀의 데이터를 활동에 매핑합니다.

샘플 코드 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import android.app.Notification
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import com.braze.models.push.BrazeNotificationPayload
import com.braze.push.BrazeNotificationFactory
import com.braze.push.BrazeNotificationUtils.getOrCreateNotificationChannelId
import com.braze.support.BrazeLogger.brazelog

class MyCustomNotificationFactory : BrazeNotificationFactory() {
    override fun createNotification(payload: BrazeNotificationPayload): Notification? {
        if (payload.extras.containsKey("live_update")) {
            val kvp = payload.extras
            val notificationChannelId = getOrCreateNotificationChannelId(payload)
            val context = payload.context

            if (context == null) {
                brazelog { "BrazeNotificationPayload has null context. Not creating notification" }
                return null
            }

            val team1 = kvp["team1"]
            val team2 = kvp["team2"]
            val score1 = kvp["score1"]
            val score2 = kvp["score2"]
            val time = kvp["time"]
            val quarter = kvp["quarter"]

            // Superb Owl will define the 'getTeamInfo' method in the next step.
            val (team1name, team1icon) = getTeamInfo(team1)
            val (team2name, team2icon) = getTeamInfo(team2)

            // Get the layouts to use in the custom notification.
            val notificationLayoutCollapsed = RemoteViews(BuildConfig.APPLICATION_ID, R.layout.liveupdate_collapsed)
            val notificationLayoutExpanded = RemoteViews(BuildConfig.APPLICATION_ID, R.layout.liveupdate_expanded)

            // Very simple notification for the small layout
            notificationLayoutCollapsed.setTextViewText(
                R.id.notification_title,
                "$team1 $score1 - $score2 $team2\n$time $quarter"
            )

            notificationLayoutExpanded.setTextViewText(R.id.score, "$score1 - $score2")
            notificationLayoutExpanded.setTextViewText(R.id.team1name, team1name)
            notificationLayoutExpanded.setTextViewText(R.id.team2name, team2name)
            notificationLayoutExpanded.setTextViewText(R.id.timeInfo, "$time - $quarter")
            notificationLayoutExpanded.setImageViewResource(R.id.team1logo, team1icon)
            notificationLayoutExpanded.setImageViewResource(R.id.team2logo, team2icon)

            val customNotification = NotificationCompat.Builder(context, notificationChannelId)
                .setSmallIcon(R.drawable.notification_small_icon)
                .setStyle(NotificationCompat.DecoratedCustomViewStyle())
                .setCustomContentView(notificationLayout)
                .setCustomBigContentView(notificationLayoutExpanded)
                .build()
            return customNotification
        } else {
            // Use the BrazeNotificationFactory for all other notifications
            return super.createNotification(payload)
        }
    }
}

3단계: 사용자 지정 데이터 매핑

MyCustomNotificationFactory.kt 에서 라이브 업데이트가 표시될 때 데이터를 처리하는 새로운 메서드를 만듭니다.

슈퍼 올빼미는 각 팀의 이름과 로고를 확장된 라이브 업데이트에 매핑하는 방법을 다음과 같이 만들었습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CustomNotificationFactory : BrazeNotificationFactory() {
    override fun createNotification(payload: BrazeNotificationPayload): Notification? {
        // Your existing code
        return super.createNotification(payload)
    }

    // Your new method
    private fun getTeamInfo(team: String?): Pair<String, Int> {
        return when (team) {
            "WBF" -> Pair("Wild Bird Fund", R.drawable.team_wbf)
            "OWL" -> Pair("Owl Rehab", R.drawable.team_owl)
            else  -> Pair("Unknown", R.drawable.notification_small_icon)
        }
    }
}

4단계: 사용자 지정 알림 팩토리 설정

애플리케이션 클래스에서 customBrazeNotificationFactory를 사용하여 사용자 지정 알림 팩토리를 설정합니다.

1
2
3
4
5
6
7
8
9
10
import com.braze.Braze

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        // Tell Braze to use your custom factory for notifications
        Braze.customBrazeNotificationFactory = MyCustomNotificationFactory()
    }
}

5단계: 활동 보내기

REST API 엔드포인트를 사용하여 /messages/send REST API 엔드포인트를 사용하여 사용자의 Android 디바이스로 푸시 알림을 보낼 수 있습니다.

curl 명령 예제

Superb Owl은 다음 curl 명령을 사용하여 요청을 보냈습니다:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
curl -X POST "https://BRAZE_REST_ENDPOINT/messages/send" \
  -H "Authorization: Bearer {REST_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{
    "external_user_ids": ["USER_ID"],
    "messages": {
      "android_push": {
        "title": "WBF vs OWL",
        "alert": "2 to 4 1:33 Q4",
        "extra": {
          "live_update": "true",
          "team1": "WBF",
          "team2": "OWL",
          "score1": "2",
          "score2": "4",
          "time": "1:33",
          "quarter": "Q4"
        },
        "notification_id": "ASSIGNED_NOTIFICATION_ID"
      }
    }
  }'

요청 매개변수

Step 6: 활동 업데이트

기존 RemoteView 알림을 새 데이터로 업데이트하려면 messages.extra 에 할당된 관련 키-값 페어를 수정한 다음 동일한 notification_id 을 사용하여 /messages/send 엔드포인트를 다시 호출하세요.

개인화된 푸시 알림

푸시 알림은 사용자 지정 보기 계층 구조 내에 사용자별 정보를 표시할 수 있습니다. 다음 예제에서는 API 트리거를 사용하여 앱에서 특정 작업을 완료한 후 현재 진행 상황을 추적할 수 있도록 사용자에게 개인화된 푸시 알림을 보냅니다.

개인화된 푸시 대시보드 예시

대시보드에서 개인화된 푸시를 설정하려면 표시하려는 특정 카테고리를 등록한 다음 Liquid를 사용하여 표시하려는 관련 사용자 속성을 설정하세요.

개인화된 푸시 대시보드 예시

Prerequisites

이 기능을 사용하려면 먼저 Swift Braze SDK를 통합해야 합니다. You’ll also need to set up push notifications.

Notification content app extensions

Two push messages shown side-by side. The message on the left shows what a push looks like with the default UI. The message on the right shows a coffee punch card push made by implementing a custom push UI.

Notification content app extensions provide you a great option for push notification customization. Notification content app extensions display a custom interface for your app’s notifications when a push notification is expanded.

Push notifications can be expanded in three different ways:

  • A long press on the push banner
  • Swiping down on the push banner
  • Swiping the banner to the left and selecting “View”

These custom views offer smart ways to engage customers by displaying distinct types of content, including interactive notifications, notifications populated with user data, and even push messages that can capture information like phone numbers and email. One of our well-known features at Braze, Push Stories, are a prime example of what a push notification content app extension can look like!

Requirements

  • Push notifications successfully integrated in your app
  • The following files generated by Xcode based on your coding language:

Swift

  • NotificationViewController.swift
  • MainInterface.storyboard

Objective-C

  • NotificationViewController.h
  • NotificationViewController.m
  • MainInterface.storyboard

Interactive push notification

Push notifications can respond to user actions inside a content app extension. For users running iOS 12 or later, this means you can turn your push notifications into fully interactive messages! This provides an exciting option to introduce interactivity to your promotions and applications. For example, your push notification can include a game for users to play, a spin-to-win wheel for discounts, or a “like” button to save a listing or song.

The following example shows a push notification where users are able to play a match game inside the expanded notification.

A diagram of what the phases of a interactive push notification could look like. A sequence shows a user pressing into a push notification that displays an interactive matching game.

Dashboard configuration

To create an interactive push notification, you must set a custom view in your dashboard.

  1. From the Campaigns page, click Create Campaign to start a new push notification campaign.
  2. On the Compose tab, toggle on Notification Buttons.
  3. Enter a custom iOS category in the iOS Notification Category field.
  4. In the .plist of your Notification Content Extension Target, set the UNNotificationExtensionCategory attribute to your custom iOS category. The value given here must match what is set in the Braze dashboard under iOS Notification Category.
  5. Set the UNNotificationExtensionInteractionEnabled key to true to enable user interactions in a push notification.

The notification button options found in the push message composer settings.

Personalized push notifications

Two iPhones displayed side-by-side. The first iPhone shows the unexpanded view of the push message. The second iPhone shows the expanded version of the push message displaying a "progress" shot of how far they are through a course, the name of the next session, and when the next session must be completed.

Push notifications can display user-specific information inside a content extension. This allows you to create user-focused push content, such as adding the option to share your progress across different platforms, show unlocked achievements, or display onboarding checklists. This example shows a push notification displayed to a user after they have completed a specific task in the Braze Learning course. By expanding the notification, the user can see their progress through their learning path. The information provided here is user-specific and can be fired off as a session is completed or a specific user action is taken by leveraging an API trigger.

Dashboard configuration

To create a personalized push notification, you must set a custom view in your dashboard.

  1. From the Campaigns page, click Create Campaign to start a new push notification campaign.
  2. On the Compose tab, toggle on Notification Buttons.
  3. Enter a custom iOS category in the iOS Notification Category field.
  4. In the Settings tab, create key-value pairs using standard Liquid. Set the appropriate user attributes you want the message to show. These views can be personalized based on specific user attributes of a specific user profile.
  5. In the .plist of your Notification Content Extension Target, set the UNNotificationExtensionCategory attribute to your custom iOS category. The value given here must match what is set in the Braze dashboard under iOS Notification Category.

Four sets of key-value pairs, where "next_session_name" and "next_session_complete_date" are set as an API trigger property using Liquid, and "completed_session count" and "total_session_count" are set as a custom user attribute using Liquid.

Handling key-value pairs

The method didReceive is called when the notification content app extension has received a notification. This method can be found within the NotificationViewController. The key-value pairs provided in the dashboard are represented in the code through the use of a userInfo dictionary.

Parsing Key-Value Pairs from Push Notifications

1
2
3
4
5
6
7
8
9
func didReceive(_ notification: UNNotification) {
  let userInfo = notification.request.content.userInfo
     
  guard let value = userInfo["YOUR-KEY-VALUE-PAIR"] as? String,
        let otherValue = userInfo["YOUR-OTHER-KEY-VALUE-PAIR"] as? String,
  else { fatalError("Key-Value Pairs are incorrect.")}
 
  ...
}
1
2
3
4
5
6
7
8
9
10
11
- (void)didReceiveNotification:(nonnull UNNotification *)notification {
  NSDictionary *userInfo = notification.request.content.userInfo;
   
  if (userInfo[@"YOUR-KEY-VALUE-PAIR"] && userInfo[@"YOUR-OTHER-KEY-VALUE-PAIR"]) {
 
  ...
 
  } else {
    [NSException raise:NSGenericException format:@"Key-Value Pairs are incorrect"];
  }
}

Information capture push notification

Push notifications can capture user information inside a content app extension, pushing the limits of what is possible with a push. Requesting user input through push notifications allows you to not only request basic information like name or email, but also prompt users to submit feedback or complete an unfinished user profile.

In the following flow, the custom view is able to respond to state changes. Those state change components are represented in each image.

  1. User receives a push notification.
  2. Push is opened. After expanded, the push prompts the user for information. In this example, the user’s email address is requested, but you could request any sort of information.
  3. Information is provided, and if in the expected format, the registration button is shown.
  4. Confirmation view is displayed, and push gets dismissed.

Dashboard configuration

To create an information capture push notification, you must set a custom view in your dashboard.

  1. From the Campaigns page, click Create Campaign to start a new push notification campaign.
  2. On the Compose tab, toggle on Notification Buttons.
  3. Enter a custom iOS category in the iOS Notification Category field.
  4. In the Settings tab, create key-value pairs using standard Liquid. Set the appropriate user attributes you want the message to show.
  5. In the .plist of your Notification Content Extension Target, set the UNNotificationExtensionCategory attribute to your custom iOS category. The value given here must match what is set in the Braze dashboard under iOS Notification Category.

As seen in the example, you may also include an image in your push notification. To do this, you must integrate rich notifications, set the notification style in your campaign to Rich Notification, and include a rich push image.

A push message with three sets of key-value pairs. 1. "Braze_id" set as a Liquid call to retrieve Braze ID. 2. "cert_title" set as "Braze Marketer Certification". 3. "Cert_description" set as "Certified Braze marketers drive...".

Handling button actions

Each action button is uniquely identified. The code checks if your response identifier is equal to the actionIndentifier, and if so, knows that the user clicked the action button.

Handling Push Notification Action Button Responses

1
2
3
4
5
6
7
func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
  if response.actionIdentifier == "YOUR-REGISTER-IDENTIFIER" {
    // do something
  } else {
    // do something else
  }
}
1
2
3
4
5
6
7
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response completionHandler:(void (^)(UNNotificationContentExtensionResponseOption))completion {
  if ([response.actionIdentifier isEqualToString:@"YOUR-REGISTER-IDENTIFIER"]) {
    completion(UNNotificationContentExtensionResponseOptionDismiss);
  } else {
    completion(UNNotificationContentExtensionResponseOptionDoNotDismiss);
  }
}

Dismissing pushes

Push notifications can be automatically dismissed from an action button press. There are three pre-built push dismissal options that we recommend:

  1. completion(.dismiss) - Dismisses the notification
  2. completion(.doNotDismiss) - Notification stays open
  3. completion(.dismissAndForward) - Push dismisses and the user gets forwarded into the application
New Stuff!