Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

BuzzAd-Benefit SDK: Type B - Feed

...

본 가이드는 BuzzAd-Benefit SDK의 피드 타입 광고를 연동하는 방법을 다루는 문서입니다.

※ 주의사항

  1. Feed 타입을 연동하기 전, 공통 가이드의 연동 사항을 모두 적용했는지 확인해주세요.

  2. Feed 의 커스터마이즈는 상단 툴바, 광고 리스트 아이템 영역, 헤더, 디자인 커스터마이즈가 가능합니다.

(중요) Basic Usage 를 모두 적용한 뒤, 하단의 Advanced Usage를 적용해해주세요.

Index

Table of Contents
exclude.*(BuzzAd-Benefit SDK|주의사항)

Basic Usage

...

FeedConfig 및 FeedHandler 설정

  1. Feed unit id로 FeedConfig를 설정합니다.

  2. FeedConfig 객체를 사용하여 FeedHandler를 생성합니다.

  3. startFeedActivity()를 호출하여 Feed 액티비티를 실행합니다.

Code Block
languagejava
final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID").build();
final FeedHandler feedHandler = new FeedHandler(feedConfig);
feedHandler.startFeedActivity(this);

Recommended Usage

...

Feed의 광고 현황 확인

Basic Usage처럼 바로 startFeedActivity를 호출하는 경우 Feed 액티비티가 실행되면서 광고를 로드하게 되어, 유저에게 보여줄 수 있는 광고가 없어 빈 화면이 보이게 될 수도 있습니다. 이에 Feed 액티비티를 실행하기 전에 preload()를 호출한 뒤 onPreloaded() 콜백을 호출하여 상태를 확인한 후 광고가 있을때만 피드로 진입할 수 있도록 하는 것을 추천합니다.

...

Code Block
languagejava
// 일회성 사용의 예
private void preloadFeed() {
    // WeakReference가 적용된 FeedHandler가 지역변수로서 선언이 되어서, 메모리에서 지워져 아래의 Listener 코드가 실행되지 않을 수 있습니다
    final FeedHandler feedHandler = new FeedHandler(getFeedConfig());
    feedHandler.preload(new FeedHandler.FeedPreloadListener() {
        @Override
        public void onPreloaded() { // 실행되지 않을 수 있습니다 }

        @Override
        public void onError(AdError error) { // 실행되지 않을 수 있습니다 }
    });
}


Advanced Usage

...

디자인 커스터마이즈

(중요) Feed Customization 주의사항

  • FeedToolbarHolder, FeedAdsAdapter, FeedHeaderViewAdapter class의 custom class를 생성할때 다음 조건중 하나를 사용해야합니다.

    1. 각 클래스는 inner class 가 아니어야 합니다.

    2. Inner class로 생성을 해야할 경우, public static class로 선언이 되어야 합니다.

  • 위의 조건에 맞지 않는 경우, class를 찾지못하는 현상이 발생하여 customization이 적용되지 않습니다.

툴바 Customization

Feed 상단의 툴바를 커스터마이징할 수 있습니다.

  1. FeedToolbarHolder를 구현하는 class 를 생성합니다.

    Code Block
    languagejava
    public class CustomFeedToolbarHolder implements FeedToolbarHolder {
        private FeedActivityToolbar toolbar;
    
        @Override
        public View getView(final Activity activity) {
            // FeedActivityToolbar is a default toolbar view that you can only change the title and view's attributes. 
            // Create a custom view and return it if you would like to add more UI components.
            this.toolbar = new FeedActivityToolbar(activity);
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    activity.finish();
                }
            });
            toolbar.setTitle("BuzzAdBenefit Feed");
            toolbar.setBackgroundColor(Color.parseColor("#1290FF")); // 변경하려는 "색상코드" 를 입력
            return toolbar;
        }
    
        @Override
        public void onTotalRewardUpdated(int totalReward) {
            // Use this callback if you want to show the current total points that users can get
        }
    }


  2. FeedConfig 빌드 시점에 해당 FeedToolbarHolder class 를 지정합니다.

    Code Block
    languagejava
    final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
    	...
        .feedToolbarHolderClass(CustomFeedToolbarHolder.class)
        .build();


툴바 Height 변경

Customize 된 toolbar가 들어가는 layout의 height값이 기본적으로 고정되어 있습니다. Toolbar의 height 값을 수정하고 싶다면 다음과 같은 코드를 추가 해야합니다.

Code Block
// AndroidManifest.xml
<activity
    android:name="com.buzzvil.buzzad.benefit.presentation.feed.FeedActivity"
    android:theme="@style/AppTheme"
    tools:replace="android:theme"/>

// styles.xml
<style name="AppTheme" parent=...>
    <!-- Customize your theme here. -->
    ...
    <item name="actionBarSize>DESIRED_ACTION_BAR_HEIGHT</item>
</style>

Feed의 헤더 Customization

Feed 상단의 헤더 영역을 커스터마이징하여, 유저에게 해당 피드가 어떤 공간인지 상세히 안내할 수 있습니다.

  1. FeedHeaderViewAdapter 를 구현하는 class 를 생성합니다.

    Code Block
    languagejava
    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.bz_view_feed_header, parent, false);
        }
    
        @Override
        public void onBindView(final View view, final int reward) {
            // Display total reward on the header if needed.
            final View rewardLayout = view.findViewById(R.id.rewardLayout);
            if (reward == 0) {
                rewardLayout.setVisibility(View.GONE);
            } else {
                rewardLayout.setVisibility(View.VISIBLE);
                final TextView rewardTextView = view.findViewById(R.id.rewardText);
                final String rewardText = view.getContext().getString(R.string.bz_feed_header_view_reward_text, reward);
                rewardTextView.setText(rewardText);
            }
        }
    }


  2. FeedConfig 빌드 시점에 해당 FeedHeaderViewAdapter class 를 지정합니다.

    Code Block
    final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
    	...
        .feedHeaderViewAdapterClass(CustomFeedHeaderViewAdapter.class)
        .build();

Feed 광고 리스트 아이템 영역 Customization

Feed의 광고 리스트 아이템 뷰를 커스터마이징하고 광고 이벤트에 대한 콜백을 등록할 수 있습니다.

  1. AdsAdapter 를 상속받는 class 를 구현합니다.

    1. onCreateViewHolderonBindViewHolder 를 구현해 Feed 리스트에 보여줄 itemView 의 레이아웃 및 바인딩 로직을 커스터마이징합니다.

    2. CtaView의 getCtaTextView() 및 getRewardImageView() 함수를 호출하여 CtaView에 보여지는 텍스트 및 리워드 이미지에 대한 customization을 할 수 있습니다. (좀 더 유연한 customization을 위해 View를 새로 만들고 싶은 경우에는 아래 CtaView Customization 참조)

    3. (optional) onImpressedonClickedonRewardRequestedonRewardedonParticipated를 오버라이드하여 광고의 임프레션, 클릭, 리워드 요청, 리워드 지급 결과, 참여완료에 대한 이벤트 콜백을 받을 수 있습니다 (콜백의 정의 및 동작은 문서 참조)

      Code Block
      languagejava
      public class CustomAdsAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> {
      
          @Override
          public NativeAdViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
              final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
              final NativeAdView feedNativeAdView = (NativeAdView) inflater.inflate(R.layout.bz_view_feed_ad, parent, false);
              return new NativeAdViewHolder(feedNativeAdView);
          }
      
          @Override
          public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) {
              final NativeAdView view = (NativeAdView) holder.itemView;
      
              final Ad ad = nativeAd.getAd();
              final Creative.Type creativeType = ad.getCreative() == null ? null : ad.getCreative().getType();
      
              final MediaView mediaView = view.findViewById(R.id.mediaView);
              final LinearLayout titleLayout = view.findViewById(R.id.titleLayout);
              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 CtaView ctaView = view.findViewById(R.id.ctaView);
              ctaView.setBackgroundColor(Color.parseColor(“#3976FD”)); // (선택) 변경하려는 "색상코드"
              final CtaPresenter ctaPresenter = new CtaPresenter(ctaView); // CtaView should not be null
              ctaPresenter.bind(nativeAd);
      
              if (mediaView != null) {
                  mediaView.setCreative(ad.getCreative());
                  mediaView.addOnMediaErrorListener(new MediaView.OnMediaErrorListener() {
                      @Override
                      public void onVideoError(@NonNull MediaView mediaView, @NonNull VideoErrorStatus errorStatus, @Nullable String errorMessage) {
                          if (errorMessage != null) {
                              Toast.makeText(mediaView.getContext(), errorMessage, Toast.LENGTH_SHORT).show();
                          }
                      }
                  });
              }
              if (titleView != null) {
                  titleView.setText(ad.getTitle());
              }
      
              if (iconView != null) {
                  ImageLoader.getInstance().displayImage(ad.getIconUrl(), iconView);
              }
              if (descriptionView != null) {
                  descriptionView.setText(ad.getDescription());
              }
      
              final Collection<View> clickableViews = new ArrayList<>();
              clickableViews.add(ctaView);
              clickableViews.add(mediaView);
              clickableViews.add(titleLayout);
              clickableViews.add(descriptionView);
      
              view.setMediaView(mediaView);
              view.setClickableViews(clickableViews);
              view.setNativeAd(nativeAd);
              view.addOnNativeAdEventListener(new NativeAdView.OnNativeAdEventListener() {
                  @Override
                  public void onImpressed(final @NonNull NativeAdView view, final @NonNull NativeAd nativeAd) {
      
                  }
      
                  @Override
                  public void onClicked(@NonNull NativeAdView view, @NonNull NativeAd nativeAd) {
      
                  }
      
                  @Override
                  public void onRewardRequested(@NonNull NativeAdView view, @NonNull NativeAd nativeAd) {
      
                  }
      
                  @Override
                  public void onRewarded(@NonNull NativeAdView view, @NonNull NativeAd nativeAd, @Nullable NativeAdRewardResult nativeAdRewardResult) {
      
                  }
      
                  @Override
                  public void onParticipated(final @NonNull NativeAdView view, final @NonNull NativeAd nativeAd) {
                      ctaPresenter.bind(nativeAd);
                  }
              });
          }
      }


  2. FeedConfig 빌드 시점에 해당 AdsAdapter class 를 지정합니다.

    Code Block
    languagejava
    if (reward > 0) {
        customizedCtaVIew.showRewardImage(CtaView.ImageType.Default);
        customizedCtaVIew.setRewardText(String.format(Locale.US, "+%d", reward));
    } else {
        customizedCtaVIew.showRewardImage(null);
        customizedCtaVIew.setRewardText(null);
    }


CtaView (버튼) Customization

CtaView를 Default로 제공되는 View가 아닌, 다른 모양의 View로 만들고 싶으신 경우 다음과 같이 설정을 진행하면 됩니다.

...

Code Block
languagejava
if (reward > 0) {
    customizedCtaVIew.showRewardImage(CtaView.ImageType.Default);
    customizedCtaVIew.setRewardText(String.format(Locale.US, "+%d", reward));
} else {
    customizedCtaVIew.showRewardImage(null);
    customizedCtaVIew.setRewardText(null);
}

Image 타입의 광고 서포트

Feed에 할당되는 광고의 개수를 극대화 하기 위해, 기존에 버즈스크린 잠금화면에 할당하던 Full Screen 광고를 이미지의 일부를 Cropping 한 후 사용 (이하 "Image 타입의 광고")하실 수 있습니다. (자세한 구현 사항은 아래 그림 참조)

...

  1. View의 Height 조정: Image 타입의 광고는 기존의 mediaView 보다 상하 길이가 길기 때문에, customization 하시는 모든 view의 height를 wrap_content로 적용하고 기타 height를 고정하는 로직을 제거해야 합니다.

  2. View의 레이아웃 조정: NativeAd 를 이용해서 광고 뷰를 그리는 과정에서 현재 타입이 Image 인지 확인하여 title, description 을 위한 layout 을 없앱니다.

    Code Block
    languagejava
    if (Creative.Type.IMAGE.equals(ad.getCreative().getType())) {
        titleLayout.setVisibility(View.GONE);
        descriptionView.setVisibility(View.GONE);
    } else {
        titleLayout.setVisibility(View.VISIBLE);
        descriptionView.setVisibility(View.VISIBLE);
    }


  3. FeedConfig 설정: FeedConfig 빌드 시점에 imageTypeEnabled 를 true 로 설정해서 Image 타입 광고를 받을 수 있게 합니다.

    Code Block
    languagejava
    final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID")
    	...
    	.imageTypeEnabled(true)
    	.build();


Additional Usage

...

FeedFragment를 사용한 방식

기본적으로 제공되는 FeedActivity가 아닌 다른 방식으로 Feed를 보여주고 싶을때, FeedFragment를 사용할 수 있습니다.

...