Ich versuche, Facebook Native Ads zu implementieren, indem Sie sie als eine alternative Ansicht in meinem RecyclerAdapter einschließen. Hat jemand damit Erfahrungen gemacht? Ich habe meine ganze Klasse für gutes Maß eingeschlossen.Facebook Native Ads mit RecyclerAdapter
public class FeedRecyclerAdapter extends LoadingRowRecyclerAdapter implements AdListener {
private static final int VIEW_TYPE_FEED = 1;
private static final int VIEW_TYPE_AD = 2;
private final Context context;
private final List<Feed> feedItems;
private final ImageLoader feedItemImageLoader;
private FeedItemClickListener feedItemClickListener;
private boolean isLongPressed = false;
private NativeAd nativeAd;
private NativeAdsManager manager;
View adView;
public FeedRecyclerAdapter(Context context, List<Feed> feedItems, ImageLoader feedItemImageLoader, NativeAd nativeAd, NativeAdsManager manager) {
this.context = context;
this.feedItems = feedItems;
this.feedItemImageLoader = feedItemImageLoader;
this.nativeAd = nativeAd;
this.manager = manager;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_FEED:
return new FeedViewHolder(new FeedItemView(context));
case VIEW_TYPE_AD:
return new AdditionalHolder(LayoutInflater.from(context).inflate(R.layout.ad_test3, parent, false));
}
return super.onCreateViewHolder(parent, viewType);
}
public class AdditionalHolder extends RecyclerView.ViewHolder {
protected LinearLayout templateContainer;
protected ImageView blank_holder;
private LinearLayout nativeAdContainer;
private LinearLayout adView;
private AdChoicesView adChoicesView;
ImageView nativeAdIcon;
TextView nativeAdTitle;
TextView nativeAdBody;
MediaView nativeAdMedia;
TextView nativeAdSocialContext;
Button nativeAdCallToAction;
public AdditionalHolder(View view) {
super(view);
//// Add ad into the ad container.
nativeAdContainer = (LinearLayout) view.findViewById(R.id.ad_unit);
LayoutInflater inflater = LayoutInflater.from(context);
adView = (LinearLayout) inflater.inflate(R.layout.ad_test3, nativeAdContainer, false);
nativeAdContainer.addView(adView);
// Create native UI using the ad metadata.
nativeAdIcon = (ImageView) view.findViewById(R.id.native_ad_icon);
nativeAdTitle = (TextView) view.findViewById(R.id.native_ad_title);
nativeAdBody = (TextView) view.findViewById(R.id.native_ad_body);
nativeAdMedia = (MediaView) view.findViewById(R.id.native_ad_media);
nativeAdSocialContext = (TextView) view.findViewById(R.id.native_ad_social_context);
nativeAdCallToAction = (Button) view.findViewById(R.id.native_ad_call_to_action);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (getItemViewType(position) == VIEW_TYPE_FEED) {
bindFeedItemView((FeedViewHolder) viewHolder, position);
} else if (getItemViewType(position) == VIEW_TYPE_AD) {
AdditionalHolder new_holder = (AdditionalHolder) viewHolder;
try {
new_holder.templateContainer.removeViewInLayout(adView);
} catch (Exception e) {
e.printStackTrace();
}
nativeAd = manager.nextNativeAd();
try {
adView = NativeAdView.render(context, nativeAd, NativeAdView.Type.HEIGHT_300);
} catch (NullPointerException e) {
e.printStackTrace();
}
new_holder.templateContainer.addView(adView);
new_holder.blank_holder.setVisibility(View.GONE);
// Setting the Text.
new_holder.nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
new_holder.nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
new_holder.nativeAdTitle.setText(nativeAd.getAdTitle());
new_holder.nativeAdBody.setText(nativeAd.getAdBody());
// Downloading and setting the ad icon.
NativeAd.Image adIcon = nativeAd.getAdIcon();
NativeAd.downloadAndDisplayImage(adIcon, new_holder.nativeAdIcon);
// Download and setting the cover image.
NativeAd.Image adCoverImage = nativeAd.getAdCoverImage();
new_holder.nativeAdMedia.setNativeAd(nativeAd);
// Add adChoices icon
if (new_holder.adChoicesView == null) {
new_holder.adChoicesView = new AdChoicesView(context, nativeAd, true);
new_holder.adView.addView(new_holder.adChoicesView, 0);
}
nativeAd.registerViewForInteraction(new_holder.adView);
}
}
// Differentiate between feedItem views and nativeAds
@Override
public int getItemViewType(int position) {
int viewType = 1;
if ((position % 9 == 0) && position != 1) viewType = 2;
return viewType;
}
// For feedItems
private void bindFeedItemView(FeedViewHolder viewHolder, int position) {
final FeedItemView feedItemView = viewHolder.feedItemView;
final Feed feedDesign = feedItems.get(position);
// TODO we can probably conditionally show or hide these based on the type of feed item, same as in FeedActivitySingle
feedItemView.showOrHideEditButton(true);
feedItemView.showOrHideBuyButton(false);
feedItemView.showOrHideFlipButton(false);
feedItemView.showOrHidePriceText(false);
// Set the results into TextViews
feedItemView.setProductPriceText(String.valueOf(feedDesign.getDesign().getPrice()));
feedItemView.setDownloadsText(String.valueOf(feedDesign.getDesign().getDownloadCount()));
feedItemView.setLikesText(String.valueOf(feedDesign.getDesign().getLikesCount()));
feedItemView.setUsernameText(feedDesign.getDesign().getAuthor().getUsername());
feedItemView.setTimestampText(feedDesign.getTimestampText());
feedItemView.getSaveImage().setImageResource(feedDesign.isInPersonalGallery() ? R.drawable.ic_action_saved : R.drawable.ic_not_saved);
feedItemView.getLikeImage().setImageResource(feedDesign.isLiked() ? R.drawable.ic_action_like_feed_full : R.drawable.ic_action_like_feed);
feedItemView.getTrashImage().setVisibility(ParseHelper.isCurrentUser(feedDesign.getDesign().getAuthor().getObjectId()) ? View.VISIBLE : View.GONE);
feedItemView.getFeedSocialShareImage().setVisibility(View.VISIBLE);
feedItemImageLoader.DisplayImage(feedDesign.getDesign().getCompressedImage().getUrl(), feedItemView.getImage(), feedItemView.getProgressBar());
if(feedDesign.getDesign().getAuthor().getProfilePicture() != null) {
feedItemImageLoader.DisplayImage(feedDesign.getDesign().getAuthor().getProfilePicture().getUrl(), feedItemView.getProfilePicture(), null); // TODO should this use profilePictureFileCache?
} else {
viewHolder.feedItemView.getProfilePicture().setImageResource(R.drawable.ic_anonymous);
}
SetCommentViews(feedItemView, feedDesign.getComments());
SetClickListeners(feedItemView, feedDesign);
}
@Override
protected int getContentDataSize() {
return feedItems.size();
}
@Override
protected int getViewType(int position) {
if (position == 1) {
return VIEW_TYPE_FEED;
} else {
return VIEW_TYPE_AD;
}
}
// Facebook Ad methods
@Override
public void onError(Ad ad, AdError adError) {
}
@Override
public void onAdLoaded(Ad ad) {
}
@Override
public void onAdClicked(Ad ad) {
}
public void setFeedItemClickListener(FeedItemClickListener feedItemClickListener) {
this.feedItemClickListener = feedItemClickListener;
}
private void SetCommentViews(FeedItemView feedItemView, List<Comment> comments) {
feedItemView.getViewAllComments().setVisibility(View.VISIBLE);
feedItemView.setViewAllComments("View more comments");
// reset layouts to hidden
feedItemView.getComment1Layout().setVisibility(View.GONE);
feedItemView.getComment2Layout().setVisibility(View.GONE);
feedItemView.getComment3Layout().setVisibility(View.GONE);
if (comments == null || comments.size() == 0) {
feedItemView.getViewAllComments().setVisibility(View.GONE);
return;
}
// note these are meant to fall-through without break statements
switch (comments.size()) {
case 3:
feedItemView.getComment3Layout().setVisibility(View.VISIBLE);
feedItemView.setCommentUser3(comments.get(2).getAuthor().getUsername());
feedItemView.setCommentText3(comments.get(2).getComment());
case 2:
feedItemView.getComment2Layout().setVisibility(View.VISIBLE);
feedItemView.setCommentUser2(comments.get(1).getAuthor().getUsername());
feedItemView.setCommentText2(comments.get(1).getComment());
case 1:
feedItemView.getComment1Layout().setVisibility(View.VISIBLE);
feedItemView.setCommentUser1(comments.get(0).getAuthor().getUsername());
feedItemView.setCommentText1(comments.get(0).getComment());
break;
}
}
private void SetClickListeners(final FeedItemView feedItemView, final Feed feedDesign) {
// setup gesture detector with current view, view holder, and feed design
final GestureDetector gestureDetector = new GestureDetector(context, new GestureListener(feedDesign, feedItemView));
// set gesture detector on image view
feedItemView.setImageTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == ACTION_UP){
if (isLongPressed){
isLongPressed = false;
feedItemClickListener.onMarkteFeedImageLongPressed_Release();
Log.d("anyTAG","Up");
return true;
}
}
if (motionEvent.getAction() == ACTION_MOVE){
return true;
}
return gestureDetector.onTouchEvent(motionEvent);
}
});
feedItemView.setTrashImageClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onTrashClicked(feedDesign);
}
});
feedItemView.setFeedSocialShareClickListener(v -> {
if (feedItemClickListener != null) {
try {
feedItemClickListener.onSocialShareClicked(feedDesign);
} catch (IOException e) {
e.printStackTrace();
}
}
});
feedItemView.setLikeImageClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onLikeClicked(feedDesign, feedItemView);
}
});
feedItemView.setSaveImageClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onSaveClicked(feedDesign, feedItemView);
}
});
feedItemView.setAuthorClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onAuthorClicked(feedDesign);
}
});
feedItemView.setCommentTextClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onCreateCommentClicked(feedDesign);
}
});
feedItemView.setViewAllCommentsClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onCreateCommentClicked(feedDesign);
}
});
feedItemView.setEditImageClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onCreateEditImageClicked(feedDesign);
}
});
feedItemView.setCommentImageClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onCreateCommentClicked(feedDesign);
}
});
feedItemView.setCommentUser1ClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onAuthorClicked(feedDesign.getComments().get(0).getAuthor().getObjectId());
}
});
feedItemView.setCommentUser2ClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onAuthorClicked(feedDesign.getComments().get(1).getAuthor().getObjectId());
}
});
feedItemView.setCommentUser3ClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onAuthorClicked(feedDesign.getComments().get(2).getAuthor().getObjectId());
}
});
feedItemView.setProfilePictureClickListener(v -> {
if (feedItemClickListener != null) {
feedItemClickListener.onProfilePictureClicked(feedDesign);
}
});
}
class FeedViewHolder extends RecyclerView.ViewHolder {
FeedItemView feedItemView;
public FeedViewHolder(FeedItemView view) {
super(view);
this.feedItemView = view;
}
}
// Gesture detector for double tap
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
private Feed feedDesign;
private FeedItemView feedItemView;
public GestureListener(Feed feedDesign, FeedItemView feedItemView) {
this.feedDesign = feedDesign;
this.feedItemView = feedItemView;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onDoubleTap(MotionEvent event) {
Log.d("FeedRecyclerAdapter", feedDesign.getDesign().getCompressedImage().getUrl());
if (feedItemClickListener != null) {
feedItemClickListener.onImageDoubleTapped(feedDesign, feedItemView);
}
return true;
}
@Override
public void onLongPress(MotionEvent event) {
if (event.getAction() == ACTION_DOWN)
{
if (!isLongPressed){
isLongPressed = true;
feedItemClickListener.onMarketFeedImageLongPressed(feedDesign, feedDesign.getDisplayedSide());
}
}
}
}
}
ich die folgende Ausnahme erhalten:
07-01 16:32:12.509 23168-23168/com.elgami.customizer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.elgami.customizer, PID: 23168
java.lang.NullPointerException: Attempt to invoke virtual method 'com.facebook.ads.NativeAd com.facebook.ads.NativeAdsManager.nextNativeAd()' on a null object reference
at com.elgami.feed.FeedRecyclerAdapter.onBindViewHolder(FeedRecyclerAdapter.java:121)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5768)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5801)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5037)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4913)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2029)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1414)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1377)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:578)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3260)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3069)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3518)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:598)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at com.android.internal.policy.PhoneWindow$DecorView.onLayout(PhoneWindow.java:2678)
at android.view.View.layout(View.java:16636)
at android.view.ViewGroup.layout(ViewGroup.java:5437)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2171)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1931)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
at android.os.Ha
Zunächst scheint es, über diese Linie beschwert werden:
nativeAd = manager.nextNativeAd();
Hier ist ein Kern meine FeedActivity Klasse:
Dieser Fehler zeigt an, dass '' Manager' ist null' wenn Sie versuchen, 'nextNativeAd' darauf zu nennen. Sie sollten überprüfen, ob Sie tatsächlich einen gültigen Manager an Ihren Konstruktor übergeben. –
Wie würde ich das feststellen? – santafebound
Sie könnten beginnen, indem Sie suchen, wo Sie 'new FeedRecyclerAdapter (...) 'und überprüfe zum Beispiel, dass du nicht versehentlich einen literalen' null'-Wert als 'manager'-Argument an deinen Konstruktor übergibst. Wenn Sie nicht sofort sehen, warum Sie dort eine "Null" erhalten, schließen Sie einen Debugger an, um besser zu verstehen, was mit Ihrem Programm passiert, während es läuft. Es gibt gute Tipps unter http://stackoverflow.com/q/218384/1321716. Wenn Sie es immer noch nicht herausfinden können, aktualisieren Sie Ihren Code, um weiteren Code hinzuzufügen, damit andere versuchen können, Ihnen zu helfen. –