sbugert / react-native-admob

A react-native component for Google AdMob banners
BSD 2-Clause "Simplified" License
1.13k stars 532 forks source link

WIP: Native Ad Support #505

Open MorganTrudeau opened 4 years ago

MorganTrudeau commented 4 years ago

I am building support for Google AdMob Native ads on IOS and Android. I am using Native Ad templates to display ads (https://developers.google.com/admob/ios/native/templates). There will be support for both small and medium templates

Sample App Working project here https://github.com/MorganTrudeau/native-ad-sample

IOS: IOS is currently working. I am loading ads into small and medium xib files. I could only get these nib files to load if they were included in the app's ios project and not in the react-native-ad-mob package. If anyone knows if this is possible that would be great. As it stands they must be added to the app's ios project and linked in Copy Bundle Resources.

Android: Coming soon...

Medium Template

image

Small Template

image

MorganTrudeau commented 4 years ago

Note to self check pull requests before starting coding...

I see this has been done.

willymulyana commented 4 years ago

Hi, it's just when I need native ads with admob. Is it already merged/shipped? Any sample project would be helpful. Thanks for this awesome addition!

Edit: Saw the sample project. Can admob native ads fully use custom components and style? Referring to fbads, the idea of native ads is also to make ad style aligned with app style. To be honest, i was forced to use admob as I can't use fbads, Facebook seem not supporting any payout bank accounts from my country (Indonesia), such a blocker.

ammarahm-ed commented 4 years ago

I have tested this feature. It is working on android too. Until this is merged, here is a quick guide to use native ads:

import {AdMobNative} from 'react-native-google-admob';

//Then in your component:

 <AdMobNative
      style={{
        width: '100%',
        height: 370, // You need to provide fixed height or else ad will not show properly
        // medium sized ad is 370 & small ad is 100 or 91 to be exact.
      }}
     adSize="medium" // or "small"
     adUnitID= {YOUR_NATIVE_AD_ID}
  />

During usage I found out that the app crashes when you navigate from one screen to another while the ad is loading. This usually occurs due to nativeAdView being removed before onUnifiedNativeAdLoaded is called. This causes the app to crash when you navigate away from a view before ad is loaded properly.

Hence here is the fix I am used currently which works:

 public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
                // Show the ad.

                sendEvent(RNAdMobNativeViewManager.EVENT_AD_LOADED, null);

                populateUnifiedNativeAdView(unifiedNativeAd, nativeAdView);

                //calculate ad size and layout

                if (nativeAdView == null) return; // ADD THIS LINE HERE
                nativeAdView.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
                        MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
                nativeAdView.layout(0, 0, nativeAdView.getMeasuredWidth(), nativeAdView.getMeasuredHeight());
            }

And in change populateUnifiedNativeAdView function to this:

     private void populateUnifiedNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdView adView) {

        nativeAdView = (UnifiedNativeAdView) findViewById(R.id.native_ad_view);
        primaryView = (TextView) findViewById(R.id.primary);
        secondaryView = (TextView) findViewById(R.id.secondary);
        secondaryParentView = (LinearLayout) findViewById(R.id.body);

        ratingBar = (RatingBar) findViewById(R.id.rating_bar);

        if (ratingBar != null) {
            ratingBar.setEnabled(false);
        }

        tertiaryView = (TextView) findViewById(R.id.tertiary);
        tertiaryParentView = (LinearLayout) findViewById(R.id.third_line);
        callToActionView = (Button) findViewById(R.id.cta);
        iconView = (ImageView) findViewById(R.id.icon);
        mediaView = (MediaView) findViewById(R.id.media_view);
        primaryParentView = (LinearLayout) findViewById(R.id.headline);
        callToActionParentView = (LinearLayout) findViewById(R.id.cta_parent);
        background = (LinearLayout) findViewById(R.id.background);

        if (nativeAdView == null

        ) {
            return;
        }

        String store = nativeAd.getStore();
        String advertiser = nativeAd.getAdvertiser();
        String headline = nativeAd.getHeadline();
        String body = nativeAd.getBody();
        String cta = nativeAd.getCallToAction();
        Double starRating = nativeAd.getStarRating();
        Image icon = nativeAd.getIcon();

        String tertiaryText;

        if (nativeAdView == null
        ) {
            return;
        }

        nativeAdView.setCallToActionView(callToActionParentView);
        nativeAdView.setHeadlineView(primaryParentView);
        nativeAdView.setMediaView(mediaView);

        if (adHasOnlyStore(nativeAd)) {
            nativeAdView.setStoreView(tertiaryView);
            tertiaryParentView.setVisibility(VISIBLE);
            tertiaryText = store;
        } else if (adHasOnlyAdvertiser(nativeAd)) {
            nativeAdView.setAdvertiserView(tertiaryView);
            tertiaryParentView.setVisibility(VISIBLE);
            secondaryView.setLines(1);
            tertiaryText = advertiser;
        } else if (adHasBothStoreAndAdvertiser(nativeAd)) {
            nativeAdView.setAdvertiserView(tertiaryView);
            tertiaryParentView.setVisibility(VISIBLE);
            secondaryView.setLines(1);
            tertiaryText = advertiser;
        } else {
            tertiaryText = "";
            tertiaryParentView.setVisibility(GONE);
            secondaryView.setLines(3);
        }

        if (nativeAdView == null

        ) {
            return;
        }

        primaryView.setText(headline);
        tertiaryView.setText(tertiaryText);
        callToActionView.setText(cta);

        // Set the secondary view to be the star rating if available.
        // Otherwise fall back to the body text.

        if (nativeAdView == null
        ) {
            return;
        }

        if (starRating != null && starRating > 0) {
            secondaryView.setVisibility(GONE);
            ratingBar.setVisibility(VISIBLE);
            ratingBar.setMax(5);
            nativeAdView.setStarRatingView(ratingBar);
        } else {
            secondaryView.setText(body);
            secondaryView.setVisibility(VISIBLE);
            ratingBar.setVisibility(GONE);
            nativeAdView.setBodyView(secondaryView);
        }

        if (nativeAdView == null

        ) {
            return;
        }

        if (icon != null) {
            iconView.setVisibility(VISIBLE);
            iconView.setImageDrawable(icon.getDrawable());
        } else {
            iconView.setVisibility(GONE);
        }

        if (nativeAdView == null

        ) {
            return;
        }

        // This method tells the Google Mobile Ads SDK that you have finished populating your
        // native ad view with this native ad.
        adView.setNativeAd(nativeAd);

        // Get the video controller for the ad. One will always be provided, even if the ad doesn't
        // have a video asset.
        VideoController vc = nativeAd.getVideoController();
    }
ammarahm-ed commented 4 years ago

Although this is working on android after making a few fixes, still a video never plays in the ad. I have tried a lot and even compared with the NativeExample provided by google AdMob itself, videos work there but they fail to load in react native, the controls and everything shows except the video never playing.

perrosnk commented 4 years ago

Any updates?

MorganTrudeau commented 4 years ago

Hello everyone.

Thank you @ammarahm-ed for looking into this crash. I have committed your code to this branch.

@ashishfeels I have also update README with native ad usage, reference and additional installation information.

I cannot debug videos right now. I propose we merge this and open another issue regarding videos not playing. This is progress.

ammarahm-ed commented 4 years ago

For the video to work on android, you need to use an ImageView for showing the Image and MediaView on for playing video I think. @MorganTrudeau

ammarahm-ed commented 4 years ago

However I have built a module here : https://github.com/ammarahm-ed/react-native-admob-native-ads

since this seems to not be merged, there are older pull requests too for native ads which have not been addressed.

so I have created something that might help people finally.

Identical Working on Android and iOS

Style your ads as you wish!

No need to manage .xml or .xib layout files to match ad style to app theme!

Adding styles is as simple as adding styles to any other react-native View

I hope it will help someone who is lost.

@perrosnk

MorganTrudeau commented 4 years ago

@ammarahm-ed Thanks for the insight on the video. I will try this! Also your module looks great. i like the react-native styling. Would be great to have all this functionality in this library. We can work on improving this feature here.

My pleasure @ashishfeels!

ammarahm-ed commented 4 years ago

@MorganTrudeau the maintainers don't seem to be active here. and yes, the styling is a breeze. You can take the code from there but it is pluggable with this library directly, just put the xib files.

ammarahm-ed commented 4 years ago

@MorganTrudeau maybe it is due to the fact that react-native-firebase now has admob support built-in. but it does not support native ads.

afkcodes commented 4 years ago

@MorganTrudeau i don't know how much i can help but i will be happy to contribute. @ammarahm-ed thanks to you also brother

paddy57 commented 4 years ago

I was using this native ad support to react- native, for video ads, it loads a teaser type of image and when video starts play (from videos callback mathods, no sound though), the video disappears, anyone solves the video to work in RN @ammarahm-ed @MorganTrudeau