1

I'm implementing google native ads on android.Most of the code I copy/pasted from this example The only difference is I request bunch of ads instead of one ad.Here is load function:

  public void loadAds(String unitId,int count) {
        if (nativeAds.size()>0) {
            for(UnifiedNativeAd ad: nativeAds)
                ad.destroy();
        }
        nativeAds =new ArrayList();
        //load
        AdLoader.Builder builder = new AdLoader.Builder(context, unitId);

        builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
            // OnUnifiedNativeAdLoadedListener implementation.
            @Override
            public void onUnifiedNativeAdLoaded(UnifiedNativeAd nativeAd) {
                // You must call destroy on old ads when you are done with them,
                // otherwise you will have a memory leak.
                //nativeAd = unifiedNativeAd;
                int numAds =nativeAds.size();
                int insertTo=numAds==0? firstAdPosition : firstAdPosition +numAds*(AdStep +1);
                CategoryData item = new CategoryData();
                item.type = ItemData.TYPE_CATEGORIES_NATIVE_AD;
                if (insertTo<data.size())
                    data.add(insertTo, item);

                item = new CategoryData();
                item.type = ItemData.TYPE_CATEGORIES_SEPARATOR;
                if (insertTo<data.size())
                data.add(insertTo+1, item);

                nativeAds.add(nativeAd);
                Log.d("nativead","got ad body "+nativeAds.size()+":"+nativeAd.getBody());
                notifyItemRangeInserted(insertTo,2);
            }

        });

        VideoOptions videoOptions = new VideoOptions.Builder()
                .setStartMuted(true)
                .build();

        NativeAdOptions adOptions = new NativeAdOptions.Builder()
                .setVideoOptions(videoOptions)
                .build();

        builder.withNativeAdOptions(adOptions);

        AdLoader adLoader = builder.withAdListener(new AdListener() {
            @Override
            public void onAdFailedToLoad(int errorCode) {
                Log.d("nativead","error code " +errorCode);
                /*
                Toast.makeText(context, "Failed to load native ad: "
                        + errorCode, Toast.LENGTH_SHORT).show();
                 */
            }
        }).build();
        AdRequest adRequest;
       // get unpersonalized ads if needed
        if(AppModel.getAppData().gdpr.eea && AppModel.getAppData().gdpr.consentStatus!= ConsentStatus.PERSONALIZED) {
            Bundle extras = new Bundle();
            extras.putString("npa", "1");
            adRequest = new AdRequest.Builder().addNetworkExtrasBundle(AdMobAdapter.class,extras).build();
        } else {
            adRequest = new AdRequest.Builder().build();
        }
        adLoader.loadAds(adRequest,count);
        //adLoader.loadAd(adRequest);
    }

First time it loads ok, but if I restart the app it throws a bunch of errors:

I/Ads: Received log message: The ad request returned a no fill for the particular slot. The error log below that says 'Malformed native JSON response' is a benign warning that will be removed in a future SDK release.

Also error code 0 is passed into onAdFailedToLoad.If I clear app's data banners are loaded again but again only for single run

undefined
  • 623
  • 7
  • 27

1 Answers1

1

As you mentioned, in the comment above, you're testing it on real ad units (which is quite dangerous as you might get blocked for that).

You're getting NO_FILL, which means there is no inventory left to serve in the AdMob backend.

You can find out more about this issue (not an issue, we can call it a "thing") here.

To get proper results, always test with test ads, so that you get maximum fill rate for the ads while testing.

You'll find the ad unit ID's for test ads on this page.

And, if you still get NO_FILL error a lot in production, try using mediation to get ads from multiple ad sources. You'll never get 100% fill rate for your ads, though, so make sure you code accordingly to handle the NO_FILL.

Also, one more reminder, do not use live ads to test the app, you might get blocked by Admob/Google for doing that.

Vedprakash Wagh
  • 3,595
  • 3
  • 12
  • 33
  • I'm testing on release build.I don't see the reason to have test unit id there. – undefined Sep 10 '19 at 12:18
  • Even if you're testing on release builds, you'll get NO_FILL for your own account. Once more users start requesting the ads, your inventory will start filling up, and will start giving you more fill rate. Don't try to "test" real ads, you'll get banned for sure. If it works with test ID's, it'll work with the real ads, trust me on that. – Vedprakash Wagh Sep 10 '19 at 12:31
  • Indeed looks like my tablet been baned.It works perfectly on my phone.Thanks! – undefined Sep 10 '19 at 12:40
  • They don't just ban your device on which you're testing the ads. They'll ban your account if you test too many live ads. Do whatever you want with test ads/devices configured as test devices. – Vedprakash Wagh Sep 10 '19 at 13:12