...
Feed 타입을 연동하기 전, 공통 가이드의 연동 사항을 모두 적용했는지 확인해주세요.
Feed 의 커스터마이즈는 상단 툴바, 광고 리스트 아이템 영역, 헤더, 디자인 커스터마이즈가 가능합니다.
...
(중요) Basic Usage 를 모두 적용한 뒤, 하단의 Advanced Usage를 적용해해주세요.
...
Code Block | ||
---|---|---|
| ||
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()
콜백을 호출하여 상태를 확인한 후 광고가 있을때만 피드로 진입할 수 있도록 하는 것을 추천합니다.
feedHandler.getSize()
: 광고의 개수feedHandler.getTotalReward()
: 적립 가능한 총 포인트 금액
Code Block | ||
---|---|---|
| ||
Info | ||
오퍼월을 Feed 에 연동하는 경우, FeedConfig 설정에 |
Code Block | ||
---|---|---|
| ||
final FeedConfig feedConfig = new FeedConfig.Builder(context, "YOUR_FEED_UNIT_ID") ... int feedAdSize = feedHandler.getSizeautoLoadingEnabled(true); int feedTotalReward = feedHandler.getTotalReward(); } @Override public void onError(AdError error) { ... // 광고가 없을 경우 호출됩니다. error를 통해 발생한 error의 원인을 알 수 있습니다 } }.build(); |
유의사항
프리로드한
FeedHandler
와 동일한 객체에서startFeedActivity()
를 호출해야 합니다.주의사항 : 하나의
FeedHandler
인스턴스에서 광고를 load/preload 한 경우, 그 인스턴스는 계속 같은 광고를 들고 있게 됩니다. 그래서 activity에서 유저가 이탈하더라도 다시 해당 인스턴스로 startFeedActivity를 하는 경우 같은 광고 리스트를 보게 됩니다. 만약 피드에 진입할 때마다 새로 광고가 로드되는 것을 원하는 경우 새로운FeedHandler
인스턴스를 만들어서startFeedActivity()
를 호출해야 합니다.
FeedHandler를 일회성으로 객체를 생성하여 preload 기능을 사용할 경우, preload에 대한 결과를 받지 못할 수 있습니다. Memory Leak 방지를 위해 feedHandler에 weakReference를 적용하고 있기 때문입니다. FeedHandler의 변수 선언을 지역변수가 아닌 Class 변수로 하는 등 일회적이지 않은 방식으로 객체를 생성하셔야 합니다.
...
language | java |
---|
...
Recommended Usage
...
Feed의 광고 현황 확인
Basic Usage처럼 바로 startFeedActivity를 호출하는 경우 Feed 액티비티가 실행되면서 광고를 로드하게 되어, 유저에게 보여줄 수 있는 광고가 없어 빈 화면이 보이게 될 수도 있습니다. 이에 Feed 액티비티를 실행하기 전에 preload()
를 호출한 뒤 onPreloaded()
콜백을 호출하여 상태를 확인한 후 광고가 있을때만 피드로 진입할 수 있도록 하는 것을 추천합니다.
feedHandler.getSize()
: 광고의 개수feedHandler.getTotalReward()
: 적립 가능한 총 포인트 금액
Code Block | ||
---|---|---|
| ||
feedHandler.preload(new FeedHandler.FeedPreloadListener() { @Override public void onPreloaded() { // WeakReference가 적용된 FeedHandler가 지역변수로서int 선언이feedAdSize 되어서, 메모리에서 지워져 아래의 Listener 코드가 실행되지 않을 수 있습니다 final FeedHandler feedHandler = new FeedHandler(getFeedConfig()= feedHandler.getSize(); int feedTotalReward = feedHandler.getTotalReward(); feedHandler.preload(new FeedHandler.FeedPreloadListener() {} @Override public void onPreloadedonError(AdError error) { // 실행되지 않을 수 있습니다 } // 광고가 없을 경우 호출됩니다. error를 통해 @Override발생한 error의 원인을 알 수 있습니다 public void onError(AdError error) { // 실행되지 않을 수 있습니다 } }); } |
...
디자인 커스터마이즈
(중요) Feed Customization 주의사항
FeedToolbarHolder, FeedAdsAdapter, FeedHeaderViewAdapter class의 custom class를 생성할때 다음 조건중 하나를 사용해야합니다.
각 클래스는 inner class 가 아니어야 합니다.
Inner class로 생성을 해야할 경우, public static class로 선언이 되어야 합니다.
위의 조건에 맞지 않는 경우, class를 찾지못하는 현상이 발생하여 customization이 적용되지 않습니다.
툴바 Customization
Feed 상단의 툴바를 커스터마이징할 수 있습니다.
...
}
}); |
유의사항
프리로드한
FeedHandler
와 동일한 객체에서startFeedActivity()
를 호출해야 합니다.주의사항 : 하나의
FeedHandler
인스턴스에서 광고를 load/preload 한 경우, 그 인스턴스는 계속 같은 광고를 들고 있게 됩니다. 그래서 activity에서 유저가 이탈하더라도 다시 해당 인스턴스로 startFeedActivity를 하는 경우 같은 광고 리스트를 보게 됩니다. 만약 피드에 진입할 때마다 새로 광고가 로드되는 것을 원하는 경우 새로운FeedHandler
인스턴스를 만들어서startFeedActivity()
를 호출해야 합니다.
FeedHandler를 일회성으로 객체를 생성하여 preload 기능을 사용할 경우, preload에 대한 결과를 받지 못할 수 있습니다. Memory Leak 방지를 위해 feedHandler에 weakReference를 적용하고 있기 때문입니다. FeedHandler의 변수 선언을 지역변수가 아닌 Class 변수로 하는 등 일회적이지 않은 방식으로 객체를 생성하셔야 합니다.
Code Block | ||
---|---|---|
|
...
// |
...
일회성 |
...
사용의 |
...
예 |
...
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를 생성할때 다음 조건중 하나를 사용해야합니다.
각 클래스는 inner class 가 아니어야 합니다.
Inner class로 생성을 해야할 경우, public static class로 선언이 되어야 합니다.
위의 조건에 맞지 않는 경우, class를 찾지못하는 현상이 발생하여 customization이 적용되지 않습니다.
툴바 Customization
Feed 상단의 툴바를 커스터마이징할 수 있습니다.
FeedToolbarHolder
를 구현하는 class 를 생성합니다.Code Block language java 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. toolbar.setTitle("BuzzAdBenefit Feed"this.toolbar = new FeedActivityToolbar(activity); toolbar.setBackgroundColorsetNavigationOnClickListener(Colornew View.parseColorOnClickListener("#1290FF")); //{ 변경하려는 "색상코드" 를 입력 return toolbar; @Override } @Override public void onTotalRewardUpdatedonClick(intView totalRewardview) { // Use this callback if you want to show the current total points that users can get activity.finish(); } }
FeedConfig
빌드 시점에 해당FeedToolbarHolder
class 를 지정합니다.Code Block language java final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID") ... } .feedToolbarHolderClass(CustomFeedToolbarHolder.class)}); toolbar.buildsetTitle();
툴바 Height 변경
Customize 된 toolbar가 들어가는 layout의 height값이 기본적으로 고정되어 있습니다. Toolbar의 height 값을 수정하고 싶다면 다음과 같은 코드를 추가 해야합니다.
...
"BuzzAdBenefit Feed");
...
Feed의 헤더 Customization
Feed 상단의 헤더 영역을 커스터마이징하여, 유저에게 해당 피드가 어떤 공간인지 상세히 안내할 수 있습니다.
FeedHeaderViewAdapter
를 구현하는 class 를 생성합니다.Code Block language java 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) {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 } }
FeedConfig
빌드 시점에 해당FeedToolbarHolder
class 를 지정합니다.Code Block language java 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 상단의 헤더 영역을 커스터마이징하여, 유저에게 해당 피드가 어떤 공간인지 상세히 안내할 수 있습니다.
FeedHeaderViewAdapter
를 구현하는 class 를 생성합니다.
FeedConfig 빌드 시점에 해당 FeedHeaderViewAdapter class 를 지정합니다.Code Block language java public class CustomFeedHeaderViewAdapter implements FeedHeaderViewAdapter { @Override public View onCreateView(final Context context, final ViewGroup parent) { final LayoutInflater inflater = (LayoutInflater) rewardLayoutcontext.setVisibilitygetSystemService(View.GONEContext.LAYOUT_INFLATER_SERVICE); } else {return inflater.inflate(R.layout.bz_view_feed_header, parent, false); } @Override public void rewardLayout.setVisibilityonBindView(View.VISIBLE); final View view, final int reward) { final// TextViewDisplay rewardTextViewtotal = view.findViewById(R.id.rewardText); reward on the header if needed. final StringView rewardText = view.getContext().getString(R.string.bz_feed_header_view_reward_text, rewardrewardLayout = view.findViewById(R.id.rewardLayout); if (reward rewardTextView.setText(rewardText); == 0) { } } }
Code Block final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID") ...rewardLayout.setVisibility(View.GONE); } else { .feedHeaderViewAdapterClass(CustomFeedHeaderViewAdapter.class) .build();
Feed 광고 리스트 아이템 영역 Customization
Feed의 광고 리스트 아이템 뷰를 커스터마이징하고 광고 이벤트에 대한 콜백을 등록할 수 있습니다.
AdsAdapter
를 상속받는 class 를 구현합니다.onCreateViewHolder
,onBindViewHolder
를 구현해 Feed 리스트에 보여줄itemView
의 레이아웃 및 바인딩 로직을 커스터마이징합니다.CtaView의 getCtaTextView() 및 getRewardImageView() 함수를 호출하여 CtaView에 보여지는 텍스트 및 리워드 이미지에 대한 customization을 할 수 있습니다. (좀 더 유연한 customization을 위해 View를 새로 만들고 싶은 경우에는 아래 CtaView Customization 참조)
(optional) FeedConfig 빌드 시점에 해당 FeedHeaderViewAdapter class 를 지정합니다.
Code Block final FeedConfig feedConfig = new FeedConfig.Builder("YOUR_FEED_UNIT_ID") ... .feedHeaderViewAdapterClass(CustomFeedHeaderViewAdapter.class) .build();
onImpressed
, onClicked
, onRewardRequested
, onRewarded
, onParticipated
를 오버라이드하여 광고의 임프레션, 클릭, 리워드 요청, 리워드 지급 결과, 참여완료에 대한 이벤트 콜백을 받을 수 있습니다 (콜백의 정의 및 동작은 문서 참조)language | java |
---|
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);
}
}
} |
Feed 광고 리스트 아이템 영역 Customization
Feed의 광고 리스트 아이템 뷰를 커스터마이징하고 광고 이벤트에 대한 콜백을 등록할 수 있습니다.
AdsAdapter
를 상속받는 class 를 구현합니다.onCreateViewHolder
,onBindViewHolder
를 구현해 Feed 리스트에 보여줄itemView
의 레이아웃 및 바인딩 로직을 커스터마이징합니다.CtaView의 getCtaTextView() 및 getRewardImageView() 함수를 호출하여 CtaView에 보여지는 텍스트 및 리워드 이미지에 대한 customization을 할 수 있습니다. (좀 더 유연한 customization을 위해 View를 새로 만들고 싶은 경우에는 아래 CtaView Customization 참조)
(optional)
onImpressed
,onClicked
,onRewardRequested
,onRewarded
,onParticipated
를 오버라이드하여 광고의 임프레션, 클릭, 리워드 요청, 리워드 지급 결과, 참여완료에 대한 이벤트 콜백을 받을 수 있습니다 (콜백의 정의 및 동작은 문서 참조)Code Block language java public class CustomAdsAdapter extends AdsAdapter<AdsAdapter.NativeAdViewHolder> { @Override public NativeAdViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final Creative.TypeLayoutInflater creativeTypeinflater = adLayoutInflater.getCreative() == null ? null : ad.getCreative().getType(); from(parent.getContext()); final MediaViewNativeAdView mediaViewfeedNativeAdView = view.findViewById(NativeAdView) inflater.inflate(R.id.mediaViewlayout.bz_view_feed_ad, parent, false); finalreturn LinearLayout titleLayout = view.findViewById(R.id.titleLayoutnew NativeAdViewHolder(feedNativeAdView); } final TextView titleView = view.findViewById(R.id.textTitle); @Override public void onBindViewHolder(NativeAdViewHolder holder, NativeAd nativeAd) { final ImageViewNativeAdView iconViewview = view.findViewById(R.id.imageIcon);(NativeAdView) holder.itemView; final TextViewAd descriptionViewad = viewnativeAd.findViewByIdgetAd(R.id.textDescription); final CtaViewCreative.Type ctaViewcreativeType = viewad.findViewByIdgetCreative(R.id.ctaView); == null ? null : ctaView.setBackgroundColor(Color.parseColor(“#3976FD”)); // (선택) 변경하려는 "색상코드" ad.getCreative().getType(); final CtaPresenterMediaView ctaPresentermediaView = new CtaPresenter(ctaViewview.findViewById(R.id.mediaView); // CtaView should not be null final LinearLayout titleLayout = ctaPresenterview.bind(nativeAdfindViewById(R.id.titleLayout); final ifTextView (mediaViewtitleView != null) {= view.findViewById(R.id.textTitle); final ImageView iconView = mediaViewview.setCreativefindViewById(ad.getCreative())R.id.imageIcon); final TextView descriptionView = mediaViewview.addOnMediaErrorListener(new MediaView.OnMediaErrorListener() {findViewById(R.id.textDescription); final CtaView ctaView = view.findViewById(R.id.ctaView); @Override ctaView.setBackgroundColor(Color.parseColor(“#3976FD”)); // (선택) 변경하려는 "색상코드" final CtaPresenter ctaPresenter = publicnew void onVideoError(@NonNull MediaView mediaView, @NonNull VideoErrorStatus errorStatus, @Nullable String errorMessage) {CtaPresenter(ctaView); // CtaView should not be null ctaPresenter.bind(nativeAd); if (errorMessagemediaView != null) { ToastmediaView.makeTextsetCreative(mediaViewad.getContext(), errorMessage, Toast.LENGTH_SHORT).show(getCreative()); mediaView.setVideoEventListener(new VideoEventListener() } // Override and implement methods } }); } 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); } }); } }
FeedConfig
빌드 시점에 해당AdsAdapter
class 를 지정합니다.Code Block if (reward > 0) { customizedCtaVIew.showRewardImage(CtaView.ImageType.Default); customizedCtaVIew.setRewardText(String.format(Locale.US, "+%d", reward)); } else { customizedCtaVIew.showRewardImage(null);language java 를 지정합니다.
Code Block language java final FeedConfig feedConfig = new FeedConfig.Builder(context, "YOUR_FEED_UNIT_ID") ... .adsAdapterClass(CustomAdsAdapter.class) customizedCtaVIew.setRewardTextbuild(null); }
CtaView (버튼) Customization
...
DefaultAdsAdapter 를 그대로 사용하는 경우에는 별도의 추가 작업 없이도 Image 타입 광고를 제공 받으실 수 가능합니다. 아래 내용은 Customization을 위해 AdsAdapterClass 를 별도로 설정하였을 때에만 해당됩니다 (북마크).
Image 타입의 광고의 경우 기존 광고들과 다르게 icon, title, description 의 내용이 없습니다. 더불어 광고 영역 전체의 상하의 길이가 깁니다. 이런 상황에서 레이아웃을 알맞게 그리기 위한 추가 작업을 한 후 해당 광고 타입을 받을 수 있도록 FeedConfig 에 새로운 설정을 추가해야 합니다.
...