# Android SDK 기본 통합 가이드

이 섹션에서는 Pushwoosh SDK를 Android 애플리케이션에 통합하는 방법에 대한 정보를 제공합니다.

## 전제 조건

Pushwoosh Android SDK를 앱에 통합하려면 다음이 필요합니다:

<TranslatedFragment id="prerequisites-android" />

## 통합 단계


### 1. Firebase Cloud Messaging 설정

먼저, Android 프로젝트를 Firebase와 연결합니다:

- Android Studio에서 프로젝트를 엽니다
- **도구 > Firebase > Cloud Messaging**으로 이동하여 "Firebase Cloud Messaging 설정"을 클릭합니다
- 마법사 지침을 따릅니다. 마지막 단계에서 마법사가 필요한 종속성을 `build.gradle` 파일에 추가합니다

### 2. Pushwoosh SDK 추가

애플리케이션의 build.gradle에 pushwoosh 라이브러리 종속성을 추가합니다:

```groovy title="build.gradle"
implementation 'com.pushwoosh:pushwoosh-firebase:6.+'
```

"+"를 현재 버전의 [Pushwoosh Android SDK](https://github.com/Pushwoosh/pushwoosh-android-sdk/releases/latest)로 교체하세요

<Aside type="caution" title="자체 FirebaseMessagingService가 있으신가요?">
앱이 이미 자체 `FirebaseMessagingService`를 정의하고 있는 경우(예: 푸시 알림을 다른 화면으로 라우팅하기 위해), Pushwoosh 푸시 알림을 가로채지 않도록 하세요. `PushwooshFcmHelper.isPushwooshMessage(remoteMessage)`가 true인 푸시 알림의 경우 모든 메시지를 `PushwooshFcmHelper.onMessageReceived(this, remoteMessage)`를 통해 전달하세요.

이 호출을 건너뛰면 Pushwoosh는 메시지에 대한 가시성을 잃게 됩니다. 메시지가 계속 표시될지 여부는 자체 핸들러에 따라 다릅니다. 핸들러가 데이터를 기반으로 알림을 생성하면 사용자는 정상적으로 보게 됩니다. 그렇지 않으면 아무것도 표시되지 않습니다. 어느 쪽이든 Pushwoosh는 메시지가 전달되거나 열렸는지 알 수 없으므로 해당 메시지의 전달 및 열람 통계는 0으로 유지됩니다. 전체 라우팅 예제는 [다른 FCM 서비스와 Pushwoosh SDK 사용하기](/ko/developer/pushwoosh-sdk/android-sdk/android-faq/#using-pushwoosh-sdk-with-other-fcm-services)를 참조하세요.
</Aside>

### 3. AndroidManifest.xml에 Pushwoosh 메타데이터 추가

AndroidManifest.xml 파일을 열고 `<application>` 태그 안에 다음 메타데이터를 추가합니다:

```xml
<meta-data android:name="com.pushwoosh.appid" android:value="__YOUR_APP_CODE__" />
<meta-data android:name="com.pushwoosh.apitoken" android:value="__YOUR_DEVICE_API_TOKEN__" />
```

여기서:
- `com.pushwoosh.appid`는 Pushwoosh 애플리케이션 코드입니다
- `com.pushwoosh.apitoken`은 [Pushwoosh Device API Token](/ko/developer/api-reference/api-access-token/#device-api-token)입니다

> **중요:** Pushwoosh 제어판에서 토큰에 올바른 앱에 대한 액세스 권한을 부여해야 합니다. [자세히 알아보기](/ko/developer/api-reference/api-access-token/#edit-token)

### 4. 초기화 코드

초기화 로직에 다음 코드를 추가하여 푸시 알림을 등록합니다:

```java
Pushwoosh.getInstance().registerForPushNotifications()
```

### 5. 프로젝트 실행

1. 프로젝트를 빌드하고 실행합니다.
2. Pushwoosh 제어판으로 이동하여 [푸시 알림을 보냅니다](/ko/product/messaging-channels/push-notifications/send-push-notifications/one-time-push).
3. 앱에서 알림을 볼 수 있어야 합니다.

## 확장 통합

이 단계에서 SDK를 이미 통합했으며 푸시 알림을 보내고 받을 수 있습니다. 이제 핵심 기능을 살펴보겠습니다

### 푸시 알림

Pushwoosh SDK에는 푸시 알림 처리를 위해 설계된 두 가지 콜백이 있습니다:
- `onMessageReceived`: 이 메서드는 푸시 알림을 수신할 때 호출됩니다.
- `onMessageOpened`: 이 메서드는 사용자가 알림과 상호 작용(열기)할 때 호출됩니다

이러한 콜백을 통해 개발자는 애플리케이션 내에서 푸시 알림 수신 및 사용자 상호 작용을 관리할 수 있습니다:

```xml title="AndroidManifest.xml"
<meta-data
    android:name="com.pushwoosh.notification_service_extension"
    android:value="com.your.package.YourNotificationServiceExtension" />
```

<Tabs syncKey="code-example">
<TabItem label="Kotlin">
```kotlin
import android.util.Log
import com.pushwoosh.notification.NotificationServiceExtension
import com.pushwoosh.notification.PushMessage

class YourNotificationServiceExtension : NotificationServiceExtension() {
    
    override fun onMessageReceived(data: PushMessage): Boolean {
        Log.d("Pushwoosh", "onMessageReceived: ${data.toJson()}")
        return false
    }

    override fun onMessageOpened(message: PushMessage) {
        Log.d("Pushwoosh", "onMessageOpened: ${message.toJson()}")
    }

}
```
</TabItem>
<TabItem label="Java">
```java
import android.util.Log;
import com.pushwoosh.notification.NotificationServiceExtension;
import com.pushwoosh.notification.PushMessage;

public class YourNotificationServiceExtensionJava extends NotificationServiceExtension {

    @Override
    public boolean onMessageReceived(PushMessage data) {
        Log.d("Pushwoosh", "onMessageReceived: " + data.toJson());
        return false;
    }

    @Override
    public void onMessageOpened(PushMessage message) {
        Log.d("Pushwoosh", "onMessageOpened: " + message.toJson());
    }
}
```
</TabItem>
</Tabs>

### 사용자 구성

개별 사용자 행동 및 선호도에 초점을 맞춤으로써 개인화된 콘텐츠를 제공하여 사용자 만족도와 충성도를 높일 수 있습니다

<Tabs syncKey="code-example">
<TabItem label="Kotlin">
```kotlin
import com.pushwoosh.Pushwoosh
import com.pushwoosh.tags.TagsBundle
import java.util.Date

class Registration {

    public void afterUserLogin(User user) {
        Pushwoosh pushwoosh = Pushwoosh.getInstance()

        // Set user ID
        if (user.getUserId() != null) {
            pushwoosh.setUserId(user.getUserId())
        }

        // Set user email
        if (user.getEmail() != null) {
            pushwoosh.setEmail(user.getEmail())
        }

        // Setting additional user information as tags for Pushwoosh
        if (user.getUserDetails() != null) {
            val details = user.getUserDetails()
            val tagsBuilder = TagsBundle.Builder()
            
            if (details.getAge() != null) {
                tagsBuilder.putInt("age", details.getAge())
            }
            
            if (details.getUserName() != null) {
                tagsBuilder.putString("name", details.getUserName())
            }
            
            if (details.lastLoginDate() != null) {
                tagsBuilder.putDate("last_login", details.getLastLoginDate())
            }
            
            // Build and send tags
            val tags = tagsBuilder.build()
            if (!tags.isEmpty()) {
                pushwoosh.setTags(tags)
            }
        }
    }
}
```
</TabItem>
<TabItem label="Java">
```java
import com.pushwoosh.Pushwoosh;
import com.pushwoosh.tags.TagsBundle;
import java.util.Date;

public class Registration {

    public void afterUserLogin(User user) {
        Pushwoosh pushwoosh = Pushwoosh.getInstance();

        // Set user ID
        if (user.getUserId() != null) {
            pushwoosh.setUserId(user.getUserId());
        }

        // Set user email
        if (user.getEmail() != null) {
            pushwoosh.setEmail(user.getEmail());
        }

        // Set user SMS number
        if (user.getSmsNumber() != null) {
            pushwoosh.registerSMSNumber(user.getSmsNumber());
        }

        // Set user WhatsApp number
        if (user.getWhatsAppNumber() != null) {
            pushwoosh.registerWhatsappNumber(user.getWhatsAppNumber());
        }

        // Setting additional user information as tags for Pushwoosh
        if (user.getUserDetails() != null) {
            UserDetails details = user.getUserDetails();
            TagsBundle.Builder tagsBuilder = new TagsBundle.Builder();

            if (details.getAge() != null) {
                tagsBuilder.putInt("age", details.getAge());
            }

            if (details.getUserName() != null) {
                tagsBuilder.putString("name", details.getUserName());
            }

            if (details.getLastLoginDate() != null) {
                tagsBuilder.putDate("last_login", details.getLastLoginDate());
            }

            // Build and send tags
            TagsBundle tags = tagsBuilder.build();
            if (!tags.isEmpty()) {
                pushwoosh.setTags(tags);
            }
        }
    }
}
```
</TabItem>
</Tabs>

### 태그

태그는 사용자 또는 기기에 할당된 키-값 쌍으로, 선호도나 행동과 같은 속성을 기반으로 세분화를 허용하여 타겟 메시징을 가능하게 합니다.

<Tabs syncKey="code-example">
<TabItem label="Kotlin">
```kotlin
import com.pushwoosh.Pushwoosh
import com.pushwoosh.tags.TagsBundle
import java.util.List

class UpdateUser {
    public void afterUserUpdateProfile(User user) {
        val pushwoosh = Pushwoosh.getInstance()
        val tagsBuilder = TagsBundle.Builder()

        // Set list of favorite categories
        if (user.favoriteCategories != null && user.favoriteCategories.isNotEmpty()) {
            tagsBuilder.putList("favorite_categories", user.getFavoriteCategories())
        }

        // Set payment information
        tagsBuilder.putBoolean("is_subscribed", user.isSubscribed())
        tagsBuilder.putString("payment_status", user.getPaymentStatus())
        tagsBuilder.putString("billing_address", user.getBillingAddress())

        // Build and send tags
        pushwoosh.setTags(tagsBuilder.build())
    }
}
```
</TabItem>
<TabItem label="Java">
```java
import com.pushwoosh.Pushwoosh;
import com.pushwoosh.tags.TagsBundle;
import java.util.List;

public class UpdateUser {
    public void afterUserUpdateProfile(User user) {
        Pushwoosh pushwoosh = Pushwoosh.getInstance();
        TagsBundle.Builder tagsBuilder = TagsBundle.Builder();

        // Set list of favorite categories
        if (user.getFavoriteCategories() != null && !user.getFavoriteCategories().isEmpty()) {
            tagsBuilder.putList("favorite_categories", user.getFavoriteCategories());
        }

        // Set payment information
        tagsBuilder.putBoolean("is_subscribed", user.isSubscribed());
        tagsBuilder.putString("payment_status", user.getPaymentStatus());
        tagsBuilder.putString("billing_address", user.getBillingAddress());

        // Build and send tags
        pushwoosh.setTags(tagsBuilder.build());
    }
}
```
</TabItem>
</Tabs>

### 이벤트

이벤트는 앱 내에서 발생하는 특정 사용자 행동 또는 발생으로, 행동을 분석하고 해당 메시지나 작업을 트리거하기 위해 추적할 수 있습니다

<Tabs syncKey="code-example">
<TabItem label="Kotlin">
```kotlin
import com.pushwoosh.Pushwoosh
import com.pushwoosh.inapp.InAppManager
import com.pushwoosh.tags.TagsBundle
import java.util.Date

class Registration {

    public void afterUserLogin(User user) {
        if (user.getUserName() != null && user.getLastLoginDate() != null) {
            val attributes = TagsBundle.Builder()
                .putString("name", user.getUserName())
                .putDate("last_login", user.getLastLoginDate())
                .build()
            
            InAppManager.getInstance().postEvent("login", attributes)
        }
    }

    public void afterUserPurchase(User user, Product product) {
        Pushwoosh pushwoosh = Pushwoosh.getInstance()

        // Track purchase event
        val purchaseAttributes = TagsBundle.Builder()
            .putString("product_id", product.getId())
            .putString("product_name", product.getName())
            .putDouble("price", product.getPrice())
            .putInt("quantity", product.getQuantity())
            .build()
        
        InAppManager.getInstance().postEvent("purchase", purchaseAttributes)

        // Set user tags
        val tagsBuilder = TagsBundle.Builder()
        tagsBuilder.putDate("last_purchase_date", Date())
        val lifetimeSpend = getCurrentLifetimeSpend() + product.getPrice()
        tagsBuilder.putDouble("lifetime_spend", getCurrentLifetimeSpend())
        pushwoosh.setTags(tagsBuilder.build())
    }
}
```
</TabItem>
<TabItem label="Java">
```java
import com.pushwoosh.Pushwoosh;
import com.pushwoosh.tags.TagsBundle;
import java.util.Date;

public class Registration {

    public void afterUserLogin(User user) {
        if (user.getUserName() != null && user.getLastLoginDate() != null) {
            TagsBundle attributes = new TagsBundle.Builder()
                .putString("name", user.getUserName())
                .putDate("last_login", user.getLastLoginDate())
                .build();

            Pushwoosh.getInstance().postEvent("login", attributes);
        }
    }

    public void afterUserPurchase(User user, Product product) {
        Pushwoosh pushwoosh = Pushwoosh.getInstance();

        // Track purchase event
        TagsBundle purchaseAttributes = new TagsBundle.Builder()
            .putString("product_id", product.getId())
            .putString("product_name", product.getName())
            .putDouble("price", product.getPrice())
            .putInt("quantity", product.getQuantity())
            .build();

        Pushwoosh.getInstance().postEvent("purchase", purchaseAttributes);

        // Set user tags
        TagsBundle.Builder tagsBuilder = new TagsBundle.Builder();
        tagsBuilder.putDate("last_purchase_date", new Date());
        double lifetimeSpend = getCurrentLifetimeSpend() + product.getPrice();
        tagsBuilder.putDouble("lifetime_spend", getCurrentLifetimeSpend());
        pushwoosh.setTags(tagsBuilder.build());
    }
}
```
</TabItem>
</Tabs>

### 리치 미디어

리치 미디어는 사용자 참여를 향상시키기 위해 알림 및 인앱 메시지에 사용되는 이미지, 비디오 또는 HTML과 같은 대화형 및 멀티미디어 콘텐츠를 의미합니다


**모달 리치 미디어** 기능을 활성화하려면 애플리케이션의 `AndroidManifest.xml` 파일에 다음 메타데이터 항목을 추가하여 구성해야 합니다:

```xml title="AndroidManifest.xml"
<meta-data
    android:name="com.pushwoosh.rich_media_type"
    android:value="Modal" />
```

<Tabs syncKey="code-example">
<TabItem label="Kotlin">
```kotlin
import android.util.Log
import com.pushwoosh.richmedia.RichMedia
import com.pushwoosh.richmedia.RichMediaManager
import com.pushwoosh.richmedia.RichMediaPresentingDelegate
import com.pushwoosh.inapp.view.config.ModalRichmediaConfig
import com.pushwoosh.inapp.view.config.enums.*

class MainActivity : AppCompatActivity(), RichMediaPresentingDelegate {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        RichMediaManager.setDelegate(this)

        // Configure the modal rich media
        val config = ModalRichmediaConfig()
            .setViewPosition(ModalRichMediaViewPosition.BOTTOM)
            .setPresentAnimationType(ModalRichMediaPresentAnimationType.SLIDE_UP)
            .setDismissAnimationType(ModalRichMediaDismissAnimationType.SLIDE_DOWN)
            
        // Apply the configuration
        RichMediaManager.setDefaultRichMediaConfig(config)
    }
    
    override fun shouldPresent(richMedia: RichMedia): Boolean {
        Log.d("Pushwoosh", "Rich media will be presented with: ${richMedia.content}")
        return true
    }

    override fun onPresent(richMedia: RichMedia) {
        Log.d("Pushwoosh", "Rich media has been presented: ${richMedia.content}")
    }

    override fun onClose(richMedia: RichMedia) {
        Log.d("Pushwoosh", "Rich media has been closed: ${richMedia.content}")
    }

    override fun onError(richMedia: RichMedia, pushwooshException: PushwooshException) {
        Log.e("Pushwoosh", "Failed to present rich media: ${richMedia.content}. Error: ${pushwooshException.message}")
    }
}
```
</TabItem>
<TabItem label="Java">
```java
import android.util.Log;
import com.pushwoosh.richmedia.RichMedia;
import com.pushwoosh.richmedia.RichMediaManager;
import com.pushwoosh.richmedia.RichMediaPresentingDelegate;
import com.pushwoosh.inapp.view.config.ModalRichmediaConfig;
import com.pushwoosh.inapp.view.config.enums.*;

public class MainActivity extends AppCompatActivity implements RichMediaPresentingDelegate {

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

        // Configure the modal rich media
        ModalRichmediaConfig config = new ModalRichmediaConfig()
            .setViewPosition(ModalRichMediaViewPosition.BOTTOM)
            .setPresentAnimationType(ModalRichMediaPresentAnimationType.SLIDE_UP)
            .setDismissAnimationType(ModalRichMediaDismissAnimationType.SLIDE_DOWN);

        // Apply the configuration
        RichMediaManager.setDefaultRichMediaConfig(config);
    }

    @Override
    public boolean shouldPresent(RichMedia richMedia) {
        Log.d("Pushwoosh", "Rich media will be presented with: " + richMedia.getContent());
        return true;
    }

    @Override
    public void onPresent(RichMedia richMedia) {
        Log.d("Pushwoosh", "Rich media has been presented: " + richMedia.getContent());
    }

    @Override
    public void onClose(RichMedia richMedia) {
        Log.d("Pushwoosh", "Rich media has been closed: " + richMedia.getContent());
    }

    @Override
    public void onError(RichMedia richMedia, PushwooshException pushwooshException) {
        Log.e("Pushwoosh", "Failed to present rich media: " + richMedia.getContent() + ". Error: " + pushwooshException.getMessage());
    }
}
```
</TabItem>
</Tabs>

## 문제 해결

통합 과정에서 문제가 발생하면 [지원 및 커뮤니티](/ko/developer/pushwoosh-sdk/support-and-community) 섹션을 참조하세요.