본문으로 건너뛰기

고급 설정

이 페이지에서는 피드 지면에서 구현할 수 있는 기능과 각 기능의 설정을 변경하는 방법을 확인할 수 있습니다.

지면 상의 기능을 변경하거나 구현하려면 SDK에서 제공하는 기본 UI를 사용하거나 직접 클래스를 구현해야 합니다. 클래스를 자체적으로 구현하려면 반드시 다음의 조건을 충족해야 합니다.

  • 구현 클래스는 내부 클래스가 아니어야 합니다.
  • 불가피하게 내부 클래스로 생성해야 할 경우, public static 클래스로 구현해야 합니다.

피드를 구성하는 주요 기능들은 아래 그림과 같습니다.

광고 분류 기능

피드 광고 분류 기능은 탭과 필터 UI를 사용하여 유형 별로 분류된 광고를 사용자에게 보여주는 기능입니다. 탭과 필터 기능을 사용하면 사용자가 참여하고 싶은 유형의 광고만 볼 수 있어 사용자의 광고 참여 경험과 광고 효율을 높일 수 있습니다.

광고 분류 기능에 대한 설정은 앱에서 코드를 수정하거나 재배포하지 않고 변경할 수 있습니다. 설정을 변경하려면 버즈빌 담당자에게 연락하세요.

광고 분류 탭과 필터

탭의 갯수, 탭의 이름, 탭으로 모아서 게재할 광고 유형을 설정할 수 있습니다. 탭은 최대 3개까지 설정할 수 있으며, 초기에는 광고 적립, 쇼핑 적립 탭이 설정됩니다. 이 중에서 광고 적립 탭에는 쇼핑 광고를 제외한 나머지 유형의 광고가 노출되며, 쇼핑 적립 탭에는 쇼핑 광고가 노출됩니다.

탭으로 분류할 수 있는 광고의 유형은 노출형 광고, 참여형 광고, 비디오 광고, 소셜 미디어 광고, 쇼핑 광고입니다. 각 탭은 한 개 이상의 광고 유형으로 구성할 수 있습니다. 단, 쇼핑 광고의 경우 다른 광고 유형과 함께 탭으로 구성할 수 없습니다.

탭이 여러 개의 광고 유형으로 구성되면 ‘클릭하기’, ‘참여하기’ 등 광고 유형을 세분화하는 필터 UI가 노출됩니다.

무한 스크롤 기능

피드 무한 스크롤 기능은 사용자가 피드에 진입해 할당된 광고 목록을 끝까지 스크롤 해 더 이상 볼 수 있는 광고가 없으면 자동으로 추가 광고를 할당하여 보여주는 기능입니다. 이 기능은 기본적으로 활성화되어 있으며, 앱에서 코드를 수정하거나 재배포를 하지 않고 무한 스크롤 기능의 활성화 여부를 설정할 수 있습니다. 설정을 변경하려면 버즈빌 담당자에게 연락하세요.

앱 UI에 진입 경로 추가

앱 화면의 아이콘, 버튼, 배너 등 레이아웃 UI에 뷰를 직접 구현하여 피드로 진입하는 경로를 만들 수 있습니다.

진입 경로를 생성할 수 있는 UI 컴포넌트의 예시는 아래 다이어그램을 참고하세요. 또한 샘플 앱에서 제공하는 다양한 커스텀 진입 경로들의 샘플 코드를 확인해 보세요.

준비 사항

⚠️  주의
진입 경로의 정상적인 동작을 위해서는 피드 지면 초기화하기 토픽의 설명에 따라 반드시 BuzzAdBenefitConfigFeedConfig를 추가해야 합니다.

진입 경로 추가하기

액티비티, 프래그먼트, 뷰 내부 등에 피드 진입 경로를 생성할 수 있습니다. 피드 진입 경로를 UI 레이아웃에 추가하려면 UI 레이아웃을 구현한 후 FeedEntryView ViewGroup을 추가하세요.

XML로 진입 경로 구현하기

다음은 your_image를 눌렀을 때 피드 지면이 열리도록 XML로 진입 경로를 구현한 예시입니다.

<?xml version="1.0" encoding="utf-8"?>
<!-- FeedEntryView을 추가합니다. -->
<com.buzzvil.buzzad.benefit.presentation.feed.entrypoint.FeedEntryView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:buzzvilFeedEntryViewName="your_custom_entry_point_1"> // 뷰에 대한 사용자 반응 추적

<!-- 직접 UI를 구현합니다. -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/your_image"
/>

</com.buzzvil.buzzad.benefit.presentation.feed.entrypoint.FeedEntryView>

액티비티에 동적으로 진입 경로 구현하기

레이아웃

다음은 res/layout 하위의 레이아웃 파일(feed_entry_point.xml)에 진입 경로를 동적으로 구현한 예시입니다.

<?xml version="1.0" encoding="utf-8"?>
<!-- FeedEntryView를 추가합니다. -->
<com.buzzvil.buzzad.benefit.presentation.feed.entrypoint.FeedEntryView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:buzzvilFeedEntryViewName="your_custom_entry_point_1"> // 뷰에 대한 사용자 반응 추적

<!-- 직접 UI를 구현합니다. -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/your_image"
/>

</com.buzzvil.buzzad.benefit.presentation.feed.entrypoint.FeedEntryView>
액티비티 레이아웃

다음은 res/layout 하위의 액티비티 레이아웃 파일에 진입 경로를 동적으로 구현한 예시입니다.

<FrameLayout
android:id="@+id/entryPointPlaceholder"/>
액티비티 코드

다음은 액티비티 소스 코드 파일에 진입 경로를 동적으로 구현한 예시입니다.

final ViewGroup parent = findViewById(R.id.entryPointPlaceholder);
final FeedEntryView entryView = (FeedEntryView) getLayoutInflater().inflate(R.layout.feed_entry_point, null);
entryView.setFeedEntryViewName("your_custom_entry_point_1"); // 뷰에 대한 사용자 반응 추적
parent.addView(entryView);

적립 가능한 포인트 표시하기

아래 그림과 같이 적립 가능한 포인트를 표시하여 아직 피드에 진입하지 않은 사용자의 참여율을 높일 수 있습니다.

적립 가능한 포인트를 사용자에게 미리 보여 주려면, 아래 순서대로 구현하세요.

  1. 피드 광고를 할당하기 위해 buzzAdFeed.load()를 호출하세요.
  2. 광고 할당이 성공하면 onSuccess() 콜백 이벤트가 호출됩니다.
  1. onSuccess() 콜백 이벤트에서 buzzAdFeed.getAvailableRewards()를 호출하면, 적립 가능한 총 포인트 금액을 조회할 수 있습니다.
  2. 위에서 조회한 적립 가능한 총 포인트 금액 값으로 뷰를 업데이트하세요.

다음은 onResume()을 실행할 때마다 피드를 새로 고침하고 뷰를 업데이트하는 예시입니다.

✏️  참고
사용자가 광고에 참여하여 리워드를 받거나 피드를 아래로 스크롤하여 새로운 광고를 불러올 경우, 피드 진입 뷰에 표시된 적립 가능한 포인트 값과 실제로 적립 가능한 포인트 값에 차이가 발생할 수도 있습니다.

private BuzzAdFeed buzzAdFeed;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
buzzAdFeed = new BuzzAdFeed.Builder().build();
}

@Override
protected void onResume() {
super.onResume();

buzzAdFeed.load(new BuzzAdFeed.FeedLoadListener() {
@Override
public void onSuccess() {
// 할당된 광고가 있으면 호출됩니다.
int feedTotalReward = buzzAdFeed.getAvailableRewards(); // 적립 가능한 총 포인트 금액
// TODO: 뷰 업데이트하는 함수를 호출합니다.
updateMessages(feedTotalReward);
}

@Override
public void onError(AdError error) {
// 할당된 광고가 없으면 호출됩니다.
// TODO: 적립 가능 포인트를 0으로 표시합니다.
updateMessages(0);
Log.e(TAG, "Failed to load a native ad.", error);
}
});
}
// TODO: 적립 가능한 총 포인트 금액 값으로 뷰를 업데이트하도록 구현합니다.
private void updateMessages(final int points) {

}

툴바 자체 구현하기

피드 툴바의 디자인을 변경할 수 있습니다. 툴바 영역의 UI를 변경하는 방법은 2가지입니다. SDK에서 제공하는 기본 UI를 사용하거나 Custom View를 구현하여 툴바의 디자인을 구현하세요.

✏️  참고

프래그먼트(FeedFragment)로 피드 지면을 연동한 경우에는 툴바를 자체 구현할 수 없습니다.

SDK 기본 UI 사용하기

BuzzAd Android용 SDK에서 제공하는 기본 UI를 수정하여 타이틀 혹은 배경색을 변경할 수 있습니다.

다음은 기본 UI를 수정하여 툴바를 변경하는 예시입니다. 이 예시에서는 DefaultFeedToolbarHolder를 상속받은 클래스를 구현하고, 기본 UI인 FeedToolbar를 사용하여 타이틀 혹은 배경색을 변경합니다. 그리고 FeedConfig에 구현한 클래스를 추가합니다.

public class YourFeedToolbarHolder extends DefaultFeedToolbarHolder {

@Override
public View getView(Activity activity, @NonNull final String unitId) {
super.toolbar = new FeedToolbar(activity); // FeedToolbar 에서 제공하는 기본 템플릿을 사용합니다.
toolbar.setTitle("YourFeedToolbarHolder");
toolbar.setIconResource(R.drawable.your_icon); // 이미지 사이즈 규격은 24dp 입니다.
toolbar.setBackgroundColor(Color.parseColor("#123456"));

super.addInquiryMenuItemView(activity); // 문의하기 버튼은 이 함수를 통해 추가할 수 있습니다.
super.addSettingsMenuItemView(activity); // 세팅 버튼은 이 함수를 통해 추가할 수 있습니다.
addRightMenuItemView1(activity); // 커스터마이징한 버튼 추가할 수 있습니다.
return toolbar;
}

// 커스터마이징한 버튼을 추가하려면 DefaultMenuLayout 를 사용하여 View 를 생성하고
// toolbar.addRightMenuButton 를 사용하여 toolbar 에 추가합니다.
private void addRightMenuItemView1(@NonNull final Activity activity) {
MenuLayout menuLayout = new DefaultMenuLayout(activity, R.mipmap.ic_launcher);
menuLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showInquiry(); // showInquiry 를 호출하여 문의하기 페이지로 연결합니다.
}
});
toolbar.addRightMenuButton(menuLayout);
}
}
final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
.feedToolbarHolderClass(YourFeedToolbarHolder.class)
.build();

직접 구현한 Custom View 사용하기

BuzzAd Android용 SDK에서 제공하는 UI를 사용하지 않고 직접 Custom View를 구현하여 툴바의 디자인을 변경할 수 있습니다.

Custom View를 직접 생성하여 툴바를 변경하려면 다음의 절차를 따르세요.

  1. DefaultFeedToolbarHolder의 서브클래스를 생성하세요.
  2. 툴바 Custsom View를 your_toolbar_holder_layout.xml에 구현하세요.
public class YourFeedToolbarHolder extends DefaultFeedToolbarHolder {

@Override
public View getView(final Activity activity, @NonNull final String unitId) {
final LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.your_toolbar_holder_layout, null);
}

@Override
public void onTotalRewardUpdated(int totalReward) {
// 적립 가능한 리워드를 UI에 적용할 수 있습니다.
}
}

✏️  참고
DefaultFeedToolbarHolder에는 액션형 광고의 사용자 문의를 처리하기 위한 문의하기 페이지를 연결하는 showInquiry(); 함수가 기본적으로 포함되어 있습니다. 그러므로 Custom View로 구현하는 FeedToolbar도 showInquiry();를 호출하여 문의하기 페이지를 연결할 수 있습니다.

  1. FeedConfig 객체를 생성한 후 feedToolbarHolderClass()DefaultFeedToolbarHolder 서브클래스를 추가하세요.
final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
.feedToolbarHolderClass(YourFeedToolbarHolder.class)
.build();

직접 구현한 툴바 높이 값 수정하기

Custom View의 높이가 안드로이드 액티비티의 기본 액션바 높이와 다를 경우, 직접 구현한 View가 정상적으로 보이지 않을 수 있습니다. 이 경우에는 BuzzAdFeedTheme 객체의 toolbarHeight() 속성에서 툴바의 높이 값을 수정하세요.

final BuzzAdFeedTheme buzzAdFeedTheme = 
BuzzAdFeedTheme.getDefault()
.toolbarHeight(R.dimen.YOUR_TOOL_BAR_HEIGHT);
BuzzAdFeed.setDefaultTheme(buzzAdFeedTheme);

헤더 영역 자체 구현하기

피드 헤더 영역을 자유롭게 활용할 수 있습니다. 예를 들어, 피드 영역을 설명하는 공간으로 활용하거나 적립 가능한 금액을 표시할 수도 있습니다.

✏️ 참고
헤더 영역을 구현하지 않으면 총 적립 가능 금액을 보여주는 기본 헤더가 표시됩니다.
헤더 영역을 사용하지 않으려면 아래 내용을 참고하여 Custom View(your_feed_header_layout)의 높이가 0인 비어있는 뷰를 적용하세요.

다음은 헤더 영역을 변경하는 예시입니다.

FeedHeaderViewAdapter 인터페이스를 구현하는 클래스를 생성하고 Custom View(your_feed_header_layout)를 헤더 영역에 구현합니다. 그리고 FeedConfigfeedHeaderViewAdapterClass() 속성에 새로 구현한 클래스를 추가합니다.

public class CustomFeedHeaderViewAdapter implements FeedHeaderViewAdapter {

@Override
public View onCreateView(final Context context, final ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return inflater.inflate(R.layout.your_feed_header_layout, parent, false);
}

@Override
public void onBindView(final View view, final int reward) {
// Display total reward on the header if needed.
final TextView textView = view.findViewById(R.id.your_textview);
textView.setText(String.format("리워드 %d원", reward));
}

@Override
public void onDestroyView() {
// Use this this callback for clearing memory
}
}
final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
.feedHeaderViewAdapterClass(CustomFeedHeaderViewAdapter.class)
.build();

기본 적립 포인트 알림 팝업 자체 구현하기

사용자가 광고에 참여하지 않아도 피드에 접근하면 일정 주기마다 포인트를 지급합니다. 기본 포인트 지급 알림 팝업을 직접 구현하고 디자인을 변경하여 사용자 경험을 개선할 수 있습니다.

다음은 기본 적립 포인트 지급 알림 팝업을 직접 구현하는 예시입니다.

  1. BaseRewardNotificationAdapter 인터페이스를 구현하는 클래스를 생성하세요.

    public class CustomBaseRewardNotificationAdapter implements BaseRewardNotificationAdapter {

    @NonNull
    @Override
    public View onCreateView(@NonNull Context context, @NonNull ViewGroup viewGroup) {
    return LayoutInflater.from(context).inflate(R.layout.YOUR_LAYOUT, viewGroup, false);
    }

    @Override
    public void onBindView(@NonNull View view, int reward) {
    TextView textView = view.findViewById(R.id.YOUR_TEXT_ID);
    textView.setText(reward + " 포인트가 적립되었습니다.");
    }
    }
  2. 이전 단계에서 생성한 CustomBaseRewardNotificationAdapterFeedConfig에 설정하세요.

    final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
    .baseRewardNotificationAdapterClass(CustomBaseRewardNotificationAdapter.class)
    .build();

광고 디자인 자체 구현하기

BuzzAd Android용 SDK에서 제공하는 광고는 일반 광고와 쇼핑 광고가 있습니다.

  • 일반 광고: 쇼핑 광고를 제외한 나머지 유형의 광고입니다.
  • 쇼핑 광고: 사용자가 광고를 통해 물건 구매를 달성하는 경우 사용자에게 구매 금액의 일정 비율을 포인트로 돌려주는 광고입니다.

두 유형 모두 광고를 표현할 수 있는 다양한 정보로 구성됩니다. 일반 광고와 쇼핑 광고를 구성하는 요소와 UI에 대해서는 아래의 표를 참고하세요.

광고 유형구성 요소설명
공통(일반, 쇼핑)광고 제목 (필수)광고의 제목입니다. 최대 10자까지 권장하며, 필요에 따라 글자 수에 상관 없이 일정 부분은 생략 부호로 대체할 수 있습니다.
광고 소재 (필수)
  • 이미지, 동영상 등 광고 소재입니다. 광고 소재의 종횡비는 반드시 유지해야 합니다.
  • com.buzzvil.buzzad.benefit.presentation.media.MediaView를 사용해서 표시해야 합니다.
  • 사이즈: 1,200 x 627 (px)
  • 여백을 추가할 수 있습니다. 자세한 내용은 버즈빌 담당자에게 문의하세요.
광고 설명 (필수)광고에 대한 상세 설명입니다. 최대 40자까지 권장하며, 필요에 따라 글자 수에 상관 없이 일정 부분은 생략 부호로 대체할 수 있습니다.
광고주 아이콘 (필수)
  • 광고주 아이콘 이미지입니다. 반드시 아이콘의 종횡비를 유지해야 합니다.
  • 사이즈: 80 x 80 (px)
CTA 버튼 (필수)
  • 광고의 참여를 유도하는 버튼입니다. 최대 7자까지 권장하며, 필요에 따라 글자 수에 상관 없이 일정 부분은 생략 부호로 대체할 수 있습니다.
  • com.buzzvil.buzzad.benefit.presentation.media.DefaultCtaView를 사용해서 표시해야 합니다.

  • ✏️  참고
    CTA 버튼의 디자인을 변경하려면 CTA 버튼 커스터마이징하기 토픽을 참고하세요.
광고 알림 문구 (권장)광고임을 명시하는 문구입니다. (예: 광고, ad, 스폰서, Sponsored)
쇼핑 적립OriginalPrice View (권장)상품의 원가를 표시합니다.
Price View (권장)상품의 할인된 가격을 표시합니다.
DiscountRate View (권장)상품 가격의 할인율을 표시합니다. 할인율은 원가와 할인가로 비교하여 산출해서 표시해야 합니다.

일반 광고 디자인 자체 구현하기

일반 광고의 디자인을 변경하려면 다음의 절차를 따르세요.

  1. 일반 광고용 NativeAdView의 규격에 맞는 레이아웃(your_feed_ad.xml)을 구현하세요.

    <!-- your_feed_ad.xml -->

    <com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView
    android:id="@+id/native_ad_view" ...>

    <!-- MediaView와 DefaultCtaView는 NativeAdView의 하위 컴포넌트로 구현해야 합니다. -->

    <LinearLayout ... >
    <com.buzzvil.buzzad.benefit.presentation.media.MediaView
    android:id="@+id/mediaView" ... />
    <TextView
    android:id="@+id/textTitle" ... />
    <TextView
    android:id="@+id/textDescription" ... />
    <ImageView
    android:id="@+id/imageIcon" ... />
    <com.buzzvil.buzzad.benefit.presentation.media.DefaultCtaView
    android:id="@+id/ctaView" ... />
    </LinearLayout>

    </com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView>
  2. AdsAdapter의 상속 클래스를 구현하세요.

  • onCreateViewHolder에서 your_feed_ad.xml을 사용하여 NativeAdView를 생성하세요.

  • onBindViewHolder에서 NativeAdViewBinder를 이용하여 광고 데이터(NativeAd)를 앞서 생성한 NativeAdView에 바인딩하세요.

    public class CustomAdsAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> {

    @NonNull
    @Override
    public NativeAdViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    final NativeAdView feedNativeAdView = (NativeAdView) inflater.inflate(R.layout.your_feed_ad, parent, false);
    return new NativeAdViewHolder(feedNativeAdView);
    }

    @Override
    public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) {
    super.onBindViewHolder(holder, nativeAd);
    final NativeAdView view = (NativeAdView) holder.itemView;

    // 광고 레이아웃 컴포넌트를 생성합니다.
    final MediaView mediaView = view.findViewById(R.id.mediaView);
    final TextView titleView = view.findViewById(R.id.textTitle);
    final ImageView iconView = view.findViewById(R.id.imageIcon);
    final TextView descriptionView = view.findViewById(R.id.textDescription);
    final DefaultCtaView ctaView = view.findViewById(R.id.ctaView);

    // 광고 데이터(NativeAd)를 바인딩합니다.
    final NativeAdViewBinder viewBinder = new NativeAdViewBinder.Builder(view, mediaView)
    .titleTextView(titleView)
    .descriptionTextView(descriptionView)
    .iconImageView(iconView)
    .ctaView(ctaView)
    .build();
    viewBinder.bind(nativeAd);
    }
    }
  • NativeAdEventListener를 통해 광고 콜백 이벤트 수신 기능을 부가적으로 추가할 수도 있습니다.

    ✏️  참고
    리워드 적립 결과(RewardResult) 종류는 리워드 적립 결과(RewardResult) 종류를 참고하세요.

    public class CustomAdsAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> {
    private NativeAdEventListener listener;

    // 부가 기능: 광고 콜백 이벤트 수신 기능을 추가합니다.

    @Override
    public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) {
    ...생략...

    viewBinder.bind(nativeAd);

    if (listener != null) {
    nativeAd.removeNativeAdEventListener(listener);
    }
    listener = buildNativeAdEventListener(holder.itemView);
    nativeAd.addNativeAdEventListener(listener);
    }



    private NativeAdEventListener buildNativeAdEventListener(@NonNull View view) {
    return new NativeAdEventListener() {
    @Override
    public void onImpressed(final @NonNull NativeAd nativeAd) {

    }

    @Override
    public void onClicked(@NonNull NativeAd nativeAd) {

    }

    @Override
    public void onRewardRequested(@NonNull NativeAd nativeAd) {

    }

    @Override
    public void onRewarded(@NonNull NativeAd nativeAd, @Nullable RewardResult nativeAdRewardResult) {
    Toast.makeText(view.getContext(), "onRewarded: " + nativeAdRewardResult, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onParticipated(final @NonNull NativeAd nativeAd) {

    }
    };
    }
    }
  1. FeedConfig에 위에서 작성한 CustomAdsAdapter를 광고 어댑터 클래스로 설정하세요.

    final FeedConfig feedConfig = new FeedConfig.Builder(context, "YOUR_FEED_UNIT_ID")
    .adsAdapterClass(CustomAdsAdapter.class)
    .build();

쇼핑 적립 광고 디자인 자체 구현하기

쇼핑 적립 광고의 디자인을 변경하려면 다음의 절차를 따르세요.

  1. 일반 광고용 레이아웃에 discountedPriceText, originalPriceText, discountPercentageText를 추가하여 쇼핑 적립 광고용 NativeAdView의 규격에 맞는 레이아웃(your_feed_ad_cps.xml)을 구현하세요.

    <!-- your_feed_ad_cps.xml -->

    <?xml version="1.0" encoding="utf-8"?>
    <com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView
    android:id="@+id/native_ad_view" ...>

    <!-- MediaView와 DefaultCtaView는 NativeAdView의 하위 컴포넌트로 구현해야 합니다. -->

    <LinearLayout ... >
    <com.buzzvil.buzzad.benefit.presentation.media.MediaView
    android:id="@+id/mediaView" ... />
    <TextView
    android:id="@+id/textTitle" ... />
    <TextView
    android:id="@+id/textDescription" ... />
    <ImageView
    android:id="@+id/imageIcon" ... />
    <com.buzzvil.buzzad.benefit.presentation.media.DefaultCtaView
    android:id="@+id/ctaView" ... />

    <!-- 쇼핑 적립 광고 구성 요소를 추가하세요 -->
    <TextView
    android:id="@+id/discountedPriceText"
    ...생략... />
    <TextView
    android:id="@+id/originalPriceText"
    ...생략... />
    <TextView
    android:id="@+id/discountPercentageText"
    ...생략... />
    </LinearLayout>

    </com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView>
  2. 일반 광고 디자인 자체 구현하기 토픽을 참고해 AdsAdapter의 상속 클래스를 구현하세요.
    다음의 예시 코드를 참고하세요.

    public class CustomCPSAdsAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> {

    @NonNull
    @Override
    public NativeAdViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    final NativeAdView feedNativeAdView = (NativeAdView) inflater.inflate(R.layout.your_feed_ad_cps, parent, false);
    return new NativeAdViewHolder(feedNativeAdView);
    }

    @Override
    public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) {
    super.onBindViewHolder(holder, nativeAd);
    final NativeAdView view = (NativeAdView) holder.itemView;

    // 광고 레이아웃 컴포넌트를 생성합니다.
    final MediaView mediaView = view.findViewById(R.id.mediaView);
    final TextView titleView = view.findViewById(R.id.textTitle);
    final ImageView iconView = view.findViewById(R.id.imageIcon);
    final TextView descriptionView = view.findViewById(R.id.textDescription);
    final DefaultCtaView ctaView = view.findViewById(R.id.ctaView);
    final TextView discountedPriceText = view.findViewById(R.id.discountedPriceText);
    final TextView originalPriceText = view.findViewById(R.id.originalPriceText);
    final TextView discountPercentageText = view.findViewById(R.id.discountPercentageText);

    final Product product = nativeAd.getShoppingProduct();
    if (product != null) {
    if (product.getDiscountedPrice() != null) {
    // 할인이 있는 쇼핑 광고
    originalPriceText.setPaintFlags(originalPriceText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
    int percentage = 0;
    if (product.getPrice() > product.getDiscountedPrice()) {
    percentage = Math.round(((product.getPrice() - product.getDiscountedPrice()) / product.getPrice() * 100));
    }
    if (percentage > 0) {
    priceText.setText(getCommaSeparatedPrice(product.getDiscountedPrice().longValue()));
    originalPriceText.setText(getCommaSeparatedPrice((long) product.getPrice()));
    discountPercentageText.setText(String.format(Locale.ROOT, "%d%%", percentage));
    discountPercentageText.setVisibility(View.VISIBLE);
    } else {
    priceText.setText(getCommaSeparatedPrice((long) product.getPrice()));
    originalPriceText.setText("");
    discountPercentageText.setVisibility(View.GONE);
    }
    } else {
    // 할인이 없는 쇼핑 광고
    priceText.setText(getCommaSeparatedPrice((long) product.getPrice()));
    originalPriceText.setText("");
    discountPercentageText.setVisibility(View.GONE);
    }
    }

    // 광고 데이터(NativeAd)를 바인딩합니다.
    final NativeAdViewBinder viewBinder = new NativeAdViewBinder.Builder(view, mediaView)
    .titleTextView(titleView)
    .descriptionTextView(descriptionView)
    .iconImageView(iconView)
    .ctaView(ctaView)
    // 부가 기능: 텍스트를 클릭할 수 있도록 설정합니다.
    .addClickableView(discountPercentageText)
    .addClickableView(discountedPriceText)
    .addClickableView(originalPriceText)
    .build();
    viewBinder.bind(nativeAd);
    }

    private String getCommaSeparatedPrice (long price){
    return String.format(Locale.getDefault(), "₩%,d", price);
    }
    }
  3. FeedConfig에 위에서 작성한 CustomCPSAdsAdapter를 쇼핑 적립형 광고 어댑터 클래스로 설정하세요.

    final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
    .cpsAdsAdapterClass(YourCPSAdsAdapter.class)
    .build();

CTA 버튼 자체 구현하기

BuzzAd Android용 SDK에서 기본으로 제공하는 UI를 사용하지 않고 CTA 버튼을 자체적으로 구현할 수 있습니다.

CTA 버튼을 직접 구현하려면 다음의 절차를 따르세요.

 중요
v3.0.0, v3.0.1 또는 v3.1.0, v3.1.1을 연동한 후 아직 최신 패치 버전으로 업데이트하지 않은 경우, 하단의 CTA 버튼 자체 구현하기(v3.0.0, v3.0.1, v3.1.0, v3.1.1))를 참고하세요.

  1. 뷰 레이아웃(view_customized_cta.xml)을 구현하세요. 다음은 레이아웃 리소스로 뷰 레이아웃을 구현한 예시입니다.

    <!-- view_customized_cta.xml -->

    <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryDark">
    <!-- CTA 버튼의 텍스트 -->
    <TextView
    android:id="@+id/textCta"/>

    <!-- CTA 버튼의 아이콘 이미지 -->
    <ImageView
    android:id="@+id/imageReward"
    android:layout_width="24dp"
    android:layout_height="24dp"
    android:src="아이콘 이미지 리소스"/>

    <!-- CTA 버튼의 리워드 텍스트 -->
    <TextView
    android:id="@+id/textReward"/>
    </LinearLayout>
  2. CtaView 클래스를 상속하는 서브클래스인 CustomCtaView를 생성하세요.

  3. CtaView 클래스에서 사용하던 CTA View 레이아웃을 inflate하도록 구현하세요.

  4. 사용자의 광고 참여 상태에 따라 호출되는 아래의 오버라이딩 메소드에서 CTA 버튼의 아이콘 이미지, 텍스트, 리워드 값을 구현하세요.

  • renderViewParticipatingState : 사용자가 광고에 참여 중인 상태 (예: 액션형 광고의 랜딩 페이지에 진입한 상태)

  • renderViewParticipatedState : 사용자가 광고 참여를 완료한 상태

  • renderViewRewardAvailableState : 사용자가 아직 광고에 참여하지 않은 상태

  • renderViewRewardNotAvailableState : 사용자가 획득할 리워드가 없는 광고

    public class CustomCtaView extends CtaView {
    private final ImageView rewardImageView;
    private final TextView rewardTextView;
    private final TextView ctaTextView;

    public CustomCtaView(@NonNull Context context) {
    this(context, null);
    }

    public CustomCtaView(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
    }

    public CustomCtaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    // TODO: 기존에 사용하던 CTA View 레이아웃을 inflate 하도록 구현하세요.
    inflate(getContext(), R.layout.view_customized_cta, this);
    this.rewardImageView = findViewById(R.id.imageReward);
    this.rewardTextView = findViewById(R.id.textReward);
    this.ctaTextView = findViewById(R.id.textCta);
    }

    // CTA 텍스트 설정
    public void setCtaText(String ctaText) {
    ctaTextView.setText(ctaText);
    }
    // CTA 리워드 값 설정
    public void setRewardText(String rewardText) {
    rewardTextView.setText(rewardText);
    }
    // CTA 아이콘 설정
    public void setRewardIcon(@DrawableRes int iconResId) {
    rewardImageView.setImageResource(iconResId);
    rewardImageView.setVisibility(View.VISIBLE);
    }
    // CTA 아이콘 숨기기 처리
    public void hideRewardIcon() {
    rewardImageView.setVisibility(View.GONE);
    }

    // 사용자가 광고에 참여 중인 상태
    @Override
    public void renderViewParticipatingState(@NonNull String callToAction) {
    setCtaText("참여 확인 중");
    hideRewardIcon();
    setRewardText("");
    }
    // 사용자가 광고 참여를 완료한 상태
    @Override
    public void renderViewParticipatedState(@NonNull String callToAction) {
    setRewardIcon(R.drawable.my_participated_icon);
    setRewardText("");
    setCtaText("참여 완료");
    }
    // 사용자가 아직 광고에 참여하지 않은 상태
    @Override
    public void renderViewRewardAvailableState(@NonNull String callToAction, int reward) {
    setRewardIcon(R.drawable.my_reward_icon);
    setRewardText(String.format(Locale.US, "+%,d", reward));
    setCtaText(callToAction);
    }
    // 사용자가 획득할 리워드가 없는 광고
    @Override
    public void renderViewRewardNotAvailableState(@NonNull String callToAction) {
    hideRewardIcon();
    setRewardText("");
    setCtaText(callToAction);
    }
    }
  1. 새로 생성한 CustomCtaView 클래스의 경로를 Feed 광고 레이아웃에 설정하세요.
    다음은 피드 광고의 레이아웃 예시입니다.

    <com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/native_ad_view">
    <com.buzzvil.buzzad.benefit.presentation.media.MediaView
    android:id="@+id/mediaView"/>
    <TextView
    android:id="@+id/textTitle"/>
    <TextView
    android:id="@+id/textDescription"/>
    <ImageView
    android:id="@+id/imageIcon"/>
    <!-- TODO: 새로 생성한 CustomCtaView 클래스 경로를 설정합니다. -->
    <com.your.packagename.CustomCtaView
    android:id="@+id/customCtaView"/>
    </com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView>
  2. 다음 순서에 따라 직접 구현한 CTA 버튼을 피드 광고에 반영하세요.

    i. 광고 디자인 자체 구현하기를 참고하여 CustomAdsAdapter를 구현하세요.

    ii. CustomAdsAdapter.onBindViewHolder에서 CustomCtaView를 객체화하세요.

    iii. NativeAdViewBinder.Builder에 새로 생성한 CustomCtaView를 바인딩하세요.

    class CustomAdAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> {
    // 생략...

    @Override
    public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) {
    super.onBindViewHolder(holder, nativeAd);

    // 생략...
    final CustomCtaView ctaView = view.findViewById(R.id.ctaView);

    final NativeAdViewBinder viewBinder = new NativeAdViewBinder.Builder(view, mediaView)
    // 생략...
    .ctaView(customCtaView)
    .build();
    viewBinder.bind(nativeAd);
    }
    }

✏️  참고
SDK에서 제공하는 DefaultCtaView로 구현한 CTA 버튼의 디자인을 변경하려면 CTA 버튼 커스터마이징하기 토픽을 참고하세요.

⚠️ 주의
CustomCtaView 클래스는 난독화 되지 않도록 Proguard 설정에서 제외해야 합니다. Proguard 설정 파일에 다음 라인을 추가하세요.

-keep class com.your.packagename.CustomCtaView { *; }

CTA 버튼 자체 구현하기(v3.0.0, v3.0.1, v3.1.0, v3.1.1)

v3.0.0, v3.0.1 또는 v3.1.0, v3.1.1을 연동한 후 아직 최신 패치 버전으로 업데이트하지 않은 경우,아래 절차에 따라 CTA 버튼을 직접 구현할 수 있습니다.

  1. 뷰 레이아웃(view_customized_cta.xml)을 구현하세요. 다음은 레이아웃 리소스로 뷰 레이아웃을 구현한 예시입니다.

    <!-- view_customized_cta.xml -->
     
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        ...(생략)...>
        <TextView
            android:id="@+id/textCta"
            ...(생략)...
            tools:text="CTA 텍스트"/>
     
        <ImageView
            android:id="@+id/imageReward"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:src=[아이콘 이미지 리소스] />
     
        <TextView
            android:id="@+id/textReward"
            ...(생략)...
            tools:text="+1"/>
    </LinearLayout>
  2. CtaView 를 상속하는 서브클래스를 생성하세요.다음은 CTA View 클래스를 생성한 예시입니다.

    public class CustomCtaView extends CtaView {
        private final ImageView rewardImageView;
        private final TextView rewardTextView;
        private final TextView ctaTextView;
     
        public CustomCtaView(@NonNull Context context) {
            this(context, null);
        }
     
        public CustomCtaView(@NonNull Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
     
        public CustomCtaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
     
            inflate(getContext(), R.layout.bz_view_customized_cta, this);
            this.rewardImageView = findViewById(R.id.imageReward);
            this.rewardTextView = findViewById(R.id.textReward);
            this.ctaTextView = findViewById(R.id.textCta);
        }
     
        @NonNull
        @Override
        public TextView rewardTextView() {
            return rewardTextView;
        }
     
        @NonNull
        @Override
        public TextView ctaTextView() {
            return ctaTextView;
        }
     
        @NonNull
        @Override
        public ImageView rewardImageView() {
            return rewardImageView;
        }
    }
  3. 피드 광고 레이아웃에서 자체 구현한 CTA 뷰를 사용하세요.다음은 레이아웃 예시입니다.

    <com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView
        android:id="@+id/native_ad_view">
        <com.buzzvil.buzzad.benefit.presentation.media.MediaView
            android:id="@+id/mediaView"/>
        <TextView
            android:id="@+id/textTitle"/>
        <TextView
            android:id="@+id/textDescription"/>   
        <ImageView
            android:id="@+id/imageIcon"/>       
        <!-- CtaView 서브클래스로 Cta View를 등록합니다. -->
        <com.your.packagename.CustomCtaView
            android:id="@+id/customCtaView"/>
    </com.buzzvil.buzzad.benefit.presentation.nativead.NativeAdView>
  4. CustomCtaView 객체에 위에서 설정한 CTA View를 가져오고, NativeAdViewBinder에서 광고 데이터를 바인딩하세요.

    final NativeAdView nativeAdView = findViewById(R.id.your_native_ad_view);
     
    // TODO: CustomCtaView로 위의 CTA View를 가져옵니다. 
    final CustomCtaView customCtaView = nativeAdView.findViewById(R.id.customCtaView)
                                                    .ctaView(customCtaView) ; // TODO: customCtaView로 설정합니다.
                                                     
    // TODO: 광고 데이터를 바인딩합니다.
    final NativeAdViewBinder viewBinder = new NativeAdViewBinder.Builder(nativeAdView, mediaView)
        .ctaView(customCtaView) // customCtaView로 설정합니다.
        .build();

광고 미할당 안내 디자인 자체 구현하기

피드 지면에 진입한 시점에 노출할 광고가 없다면 광고 미할당 안내 UI가 표시됩니다. 미할당 안내 디자인은 자체 구현하여 변경할 수 있습니다.

광고 미할당 안내 디자인을 직접 구현하려면 다음의 절차를 따르세요.

  1. 피드 지면에 광고가 할당되지 않았을 때의 화면에 추가할 에러 이미지(feedErrorImageView), 타이틀(feedErrorTitle), 상세 설명(feedErrorDescription) 레이아웃을 작성하세요.

    <!-- custom_feed_error_view.xml -->

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:padding="40dp">

    <ImageView
    android:id="@+id/feedErrorImageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

    <TextView
    android:id="@+id/feedErrorTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="32dp"
    android:textColor="@color/bz_text_emphasis"
    android:textSize="16sp" />

    <TextView
    android:id="@+id/feedErrorDescription"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="8dp"
    android:textAlignment="center"
    android:textColor="@color/bz_text_description"
    android:textSize="14sp" />

    </LinearLayout>
  2. FeedErrorViewHolder를 구현하는 커스텀 클래스 CustomErrorView를 새로 생성하고, 자동으로 완성되는 getView(), updateErrorView() 메소드를 다음과 같이 구현하세요.

    public class CustomErrorView extends FeedErrorViewHolder {
    View errorView = activity.getLayoutInflater().inflate(R.layout.custom_feed_error_view, null, false);
    final ImageView errorImageView = errorView.findViewById(R.id.feedErrorImageView);
    final TextView errorTitle = errorView.findViewById(R.id.feedErrorTitle);
    final TextView errorDescription = errorView.findViewById(R.id.feedErrorDescription);

    @NonNull
    @Override
    public View getErrorView(@NonNull Activity activity) {
    // TODO: 1번에서 생성한 custom_feed_error_view 레이아웃을 inflate

    errorImageView.setImageResource(R.drawable.bz_ic_feed_profile_coin); // 에러 이미지 설정
    errorTitle.setText("타이틀: 광고가 없습니다. "); // 에러 타이틀 텍스트 설정
    errorDescription.setText("디스크립션: 할당된 광고가 없습니다!"); // 에러 상세 텍스트 설정

    return errorView;
    }

    @Override
    public updateErrorView(AdErrorType adErrorType) {
    // TODO: 위에서 선언한 View를 업데이트 할 수 있는 코드를 작성하세요.
    ...
    }
    }
  3. FeedConfigfeedErrorViewHolderClass 속성에 이전 단계에서 생성한 CustomErrorView 클래스를 추가하세요.

    // Feed 지면 초기화
    // TODO: feedErrorViewHolderClass 속성에 2번에서 생성한 CustomErrorView 클래스를 설정합니다.
    final FeedConfig feedConfig = new FeedConfig.Builder(YOUR_FEED_UNIT_ID)
    .feedErrorViewHolderClass(CustomErrorView.class)
    .build();

광고 타입 확인하기

BuzzAd Android용 SDK는 노출형, 액션형 등 다양한 광고 유형별로 차별화된 리워드 제공 등 다양한 기획을 지원하기 위해 광고 유형을 확인할 수 있는 API를 제공합니다. API에 대한 자세한 내용은 자주 하는 질문광고 타입 확인하기를 참고하세요.

개인정보 제3자 제공 동의 UI

 중요
버즈빌과 개인정보 위수탁 관계이며 앱에서 자체적으로 제공하는 개인정보 처리방침 정책에 버즈빌을 수탁자로 포함하고 있다면, 여기에서 안내하는 개인정보 제3자 제공 동의 UI를 띄우지 않아도 됩니다.

기존에 제공하던 함수가 Deprecated 되었고, BuzzAd Android v3.27.x 부터는 아래의 코드는 삭제하는것을 권장합니다. 아래 코드가 없더라도 원격 제어가 가능합니다.

  • BuzzAdBenefit.getPrivacyPolicyManager()
  • PrivacyPolicyManager.showConsentUI()
  • PrivacyPolicyManager.grantConsent()
  • PrivacyPolicyManager.revokeConsent()
  • PrivacyPolicyManager.isConsentGranted()

❗️ DEPRECATED
BuzzAd Android용 SDK v3.27.x부터는 서버에서 개인정보 제3자 제공 동의 UI 표시를 제어합니다. BuzzAd Android용 SDK v3.27.x에서 표시 여부를 설정하려면 버즈빌 담당자에게 연락하세요.

개인 정보 보호법과 구글 정책에 따라, 개인 정보 수집 및 사용에 대한 사용자의 동의가 필요합니다. BuzzAd Android용 SDK는 동의를 얻기 위한 UI를 제공하며, 사용자가 개인 정보 수집에 동의하지 않으면, 피드 지면에 광고가 할당되지 않습니다. 피드 지면에 처음 진입한 사용자에게는 아래와 같은 UI가 표시됩니다.

사용자 프로필 입력 배너 노출 여부 설정하기

사용자가 출생연도 또는 성별 정보를 제공하지 않으면 헤더 영역에 프로필 정보를 입력하는 배너가 기본적으로 노출됩니다.

FeedConfig를 수정하여 프로필 정보 입력 배너의 노출 여부를 설정할 수 있습니다.
다음은 프로필 입력 배너를 표시하지 않는 예시입니다.

final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
.profileBannerEnabled(false) // 프로필 배너 미노출
.build();

✏️  참고
FeedConfig.feedHeaderViewAdapterClass를 자체 구현하는 경우에는 프로필 입력 배너 노출 여부를 설정할 수 없습니다.

프래그먼트로 피드 연동하기

더 다양한 연동 방식을 제공하기 위해 BuzzAd Android용 SDK는 피드 지면을 제공하는 기본 방식인 액티비티 외에도 프래그먼트를 통한 연동을 지원합니다.

프래그먼트로 피드 지면을 연동하려면, 액티비티에 프래그먼트를 추가하고 해당 액티비티의 onCreate()에서 프래그먼트를 초기하세요.

다음은 FeedFragment를 연동하는 예시입니다.

class YourActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_your);

// 광고를 새로 할당 받기 위해 필요한 부분입니다.
final BuzzAdFeed buzzAdFeed = new BuzzAdFeed.Builder().build();

final FeedFragment feedFragment = buzzAdFeed.getFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, feedFragment)
.commitAllowingStateLoss();

}
}
<?xml version="1.0" encoding="utf-8"?>
<!--activity_your.xml-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".feed.FeedFragmentActivity">

<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

✏️  참고
FeedFragment의 UI를 변경하려면 디자인 커스터마이징 토픽을 참고하세요.