A rather popular way to integrate native ads into mobile applications is to display blocks of ads in the list through an equal amount of data elements. For example, in the popular client myMail, a block of advertisements is displayed in the inbox every N letters. This experience does not shine with novelty, and has previously been successfully applied on Twitter. It is worth mentioning that Admob has certain rules for advertising in mobile applications , the failure of which is fraught with blocking Admob account. An important point - application developers have the right to display no more than 3 advertising banners on 1 page with scrollable content, and so that only 1 banner is displayed at a time in the visible part of the screen. These rules relate to banners, and it is still unknown whether the new rules regarding native advertising will be given. Nevertheless, it is worth considering this when developing.dependencies { //… compile 'com.google.android.gms:play-services-ads:7.8.0' //… } public class AdmobFetcher { private static final int PREFETCHED_ADS_SIZE = 2; private static final int MAX_FETCH_ATTEMPT = 4; private AdLoader adLoader; private List<NativeAd> mPrefetchedAdList = new ArrayList<NativeAd>(); private Map<Integer, NativeAd> adMapAtIndex = new HashMap<Integer, NativeAd>(); private int mNoOfFetchedAds; private int mFetchFailCount; private WeakReference<Context> mContext = new WeakReference<Context>(null); private String admobReleaseUnitId; } private synchronized void setupAds() { // unitId. String admobUnitId = mContext.get().getResources().getString(R.string.test_admob_unit_id); // String admobUnitId = mAdmobReleaseUnitId; adLoader = new AdLoader.Builder(mContext.get(), admobUnitId) .forAppInstallAd(new NativeAppInstallAd.OnAppInstallAdLoadedListener() { @Override public void onAppInstallAdLoaded(NativeAppInstallAd appInstallAd) { onAdFetched(appInstallAd); } }) .forContentAd(new NativeContentAd.OnContentAdLoadedListener() { @Override public void onContentAdLoaded(NativeContentAd contentAd) { onAdFetched(contentAd); } }) .withAdListener(new AdListener() { @Override public void onAdFailedToLoad(int errorCode) { mFetchFailCount++; // - ensurePrefetchAmount(); //, // } }) .withNativeAdOptions(new NativeAdOptions.Builder().build()).build(); } <string name="test_admob_unit_id">ca-app-pub-3940256099942544/2247696110</string> private synchronized void onAdFetched(NativeAd adNative) { if (canUseThisAd(adNative)) { mPrefetchedAdList.add(adNative); // mNoOfFetchedAds++; } // mFetchFailCount = 0; ensurePrefetchAmount(); // notifyObserversOfAdSizeChange(); } // private void notifyObserversOfAdSizeChange() { for (AdmobListener listener : mAdNativeListeners) { listener.onAdCountChanged(); } } //, , , , // private synchronized void ensurePrefetchAmount() { if (mPrefetchedAdList.size() < PREFETCHED_ADS_SIZE && (mFetchFailCount < MAX_FETCH_ATTEMPT)) { fetchAd(); } } // , private boolean canUseThisAd(NativeAd adNative) { if (adNative != null) { CharSequence header = null, body = null; if (adNative instanceof NativeContentAd) { NativeContentAd ad = (NativeContentAd) adNative; header = ad.getHeadline(); body = ad.getBody(); } else if (adNative instanceof NativeAppInstallAd) { NativeAppInstallAd ad = (NativeAppInstallAd) adNative; header = ad.getHeadline(); body = ad.getBody(); } // , :) return !TextUtils.isEmpty(header)&& !TextUtils.isEmpty(body); } } return false; } // public synchronized void prefetchAds(Context context) { mContext = new WeakReference<Context>(context); setupAds(); // (. ) fetchAd(); // } private synchronized void fetchAd() { Context context = mContext.get(); if (context != null) { // adLoader.loadAd(getAdRequest()); } else { mFetchFailCount++; // , } } private synchronized AdRequest getAdRequest() { AdRequest.Builder adBldr = new AdRequest.Builder(); //.addTestDevice(AdRequest.DEVICE_ID_EMULATOR); // unitId return adBldr.build(); } public synchronized NativeAd getAdForIndex(final int index) { // NativeAd adNative = adMapAtIndex.get(index); // , if (adNative == null && mPrefetchedAdList.size() > 0) { // adNative = mPrefetchedAdList.remove(0); // , if (adNative != null) { adMapAtIndex.put(index, adNative); } } // , ensurePrefetchAmount(); return adNative; } public synchronized void addListener(AdmobListener listener) { mAdNativeListeners.add(listener); } public interface AdmobListener { void onAdCountChanged(); } public class AdmobAdapterWrapper extends BaseAdapter implements AdmobFetcher.AdmobListener { private BaseAdapter mAdapter; public BaseAdapter getAdapter() { return mAdapter; } public void setAdapter(BaseAdapter adapter) { mAdapter = adapter; mAdapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { notifyDataSetChanged(); } @Override public void onInvalidated() { notifyDataSetInvalidated(); } }); } AdmobFetcher adFetcher; Context mContext; private final static int VIEW_TYPE_COUNT = 2; private final static int VIEW_TYPE_AD_CONTENT = 1; private final static int VIEW_TYPE_AD_INSTALL = 2; private final static int DEFAULT_NO_OF_DATA_BETWEEN_ADS = 10; private final static int DEFAULT_LIMIT_OF_ADS = 3; private int mNoOfDataBetweenAds; public int getNoOfDataBetweenAds() { return mNoOfDataBetweenAds; } public void setNoOfDataBetweenAds(int mNoOfDataBetweenAds) { this.mNoOfDataBetweenAds = mNoOfDataBetweenAds; } private int mLimitOfAds; public int getLimitOfAds() { return mLimitOfAds; } public void setLimitOfAds(int mLimitOfAds) { this.mLimitOfAds = mLimitOfAds; } private int mContentAdsLayoutId; public int getContentAdsLayoutId() { return mContentAdsLayoutId; } public void setContentAdsLayoutId(int mContentAdsLayoutId) { this.mContentAdsLayoutId = mContentAdsLayoutId; } private int mInstallAdsLayoutId; public int getInstallAdsLayoutId() { return mInstallAdsLayoutId; } public void setInstallAdsLayoutId(int mInstallAdsLayoutId) { this.mInstallAdsLayoutId = mInstallAdsLayoutId; } public AdmobAdapterWrapper(Context context) { setNoOfDataBetweenAds(DEFAULT_NO_OF_DATA_BETWEEN_ADS); setLimitOfAds(DEFAULT_LIMIT_OF_ADS); setContentAdsLayoutId(R.layout.adcontentlistview_item); setInstallAdsLayoutId(R.layout.adinstalllistview_item); mContext = context; adFetcher = new AdmobFetcher(); adFetcher.addListener(this); // adFetcher.prefetchAds(context); } @Override public void onAdCountChanged() { notifyDataSetChanged(); } } adFetcher = new AdmobFetcher(); adFetcher.addListener(this); @Override public int getCount() { if (mAdapter != null) { int noOfAds = getAdsCountToPublish(); return mAdapter.getCount() > 0 ? mAdapter.getCount() + noOfAds : 0; } else { return 0; } } public int getAdsCountToPublish(){ int noOfAds = Math.min(adFetcher.getFetchedAdsCount(), mAdapter.getCount() / getNoOfDataBetweenAds()); return Math.min(noOfAds, getLimitOfAds()); } @Override public Object getItem(int position) { if (canShowAdAtPosition(position)) { // //: 5 , position=11 //adPos 1 int adPos = getAdIndex(position); return adFetcher.getAdForIndex(adPos); } else { int origPos = getOriginalContentPosition(position); return mAdapter.getItem(origPos); } } @Override public long getItemId(int position) { return position; } @Override public int getViewTypeCount() { return VIEW_TYPE_COUNT + getAdapter().getViewTypeCount(); } @Override public int getItemViewType(int position) { if (canShowAdAtPosition(position)) { int adPos = getAdIndex(position); NativeAd ad = adFetcher.getAdForIndex(adPos); return ad instanceof NativeAppInstallAd ? VIEW_TYPE_AD_INSTALL : VIEW_TYPE_AD_CONTENT; } else { int origPos = getOriginalContentPosition(position); return mAdapter.getItemViewType(origPos); } } protected int getOriginalContentPosition(int position) { int noOfAds = getAdsCountToPublish(); // No of spaces for ads in the dataset, according to ad placement rules // , , int adSpacesCount = position / (getNoOfDataBetweenAds() + 1); return position - Math.min(adSpacesCount, noOfAds); } protected boolean canShowAdAtPosition(int position) { // , ? // ? return isAdPosition(position) && isAdAvailable(position); } private int getAdIndex(int position) { return (position / getNoOfDataBetweenAds()) - 1; } private boolean isAdPosition(int position) { return (position + 1) % (getNoOfDataBetweenAds() + 1) == 0; } private boolean isAdAvailable(int position) { int adIndex = getAdIndex(position); // return position >= getNoOfDataBetweenAds() && adIndex >= 0 && adIndex < getLimitOfAds() && adFetcher.getFetchedAdsCount() > adIndex; } mAdapter.getCount() / getNoOfDataBetweenAds() <com.google.android.gms.ads.formats.NativeContentAdView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tvHeader" android:layout_width="match_parent" android:layout_height="wrap_content"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="2dp"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ivLogo"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="5dp"> <TextView android:id="@+id/tvDescription" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/tvAdvertiser" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp"/> </LinearLayout> </LinearLayout> <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/ivImage" android:scaleType="center" android:layout_marginTop="2dp" android:background="#00FFFFFF"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="10dp" android:paddingRight="10dp" android:layout_marginTop="2dp" android:id="@+id/btnAction"/> </LinearLayout> </com.google.android.gms.ads.formats.NativeContentAdView> <com.google.android.gms.ads.formats.NativeAppInstallAdView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/tvHeader" android:layout_width="match_parent" android:layout_height="wrap_content"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="2dp"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ivLogo"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="5dp"> <TextView android:id="@+id/tvDescription" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="1dp"> <TextView android:id="@+id/tvStore" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true"/> <TextView android:id="@+id/tvPrice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true"/> </RelativeLayout> </LinearLayout> </LinearLayout> <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:id="@+id/ivImage" android:scaleType="center" android:layout_marginTop="2dp" android:background="#00FFFFFF"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="10dp" android:paddingRight="10dp" android:layout_marginTop="2dp" android:id="@+id/btnAction"/> </LinearLayout> </com.google.android.gms.ads.formats.NativeAppInstallAdView> @Override public View getView(int position, View convertView, ViewGroup parent) { switch (getItemViewType(position)) { case VIEW_TYPE_AD_INSTALL: NativeAppInstallAdView lvi1; NativeAppInstallAd ad1 = (NativeAppInstallAd) getItem(position); if (convertView == null) { lvi1 = getInstallAdView(parent, ad1); } else { lvi1 = (NativeAppInstallAdView) convertView; bindInstallAdView(lvi1, ad1); } return lvi1; case VIEW_TYPE_AD_CONTENT: NativeContentAdView lvi2; NativeContentAd ad2 = (NativeContentAd) getItem(position); if (convertView == null) { lvi2 = getContentAdView(parent, ad2); } else { lvi2 = (NativeContentAdView) convertView; bindContentAdView(lvi2, ad2); } return lvi2; default: int origPos = getOriginalContentPosition(position); return mAdapter.getView(origPos, convertView, parent); } } private NativeContentAdView getContentAdView(ViewGroup parent, NativeContentAd ad) { LayoutInflater inflater = (LayoutInflater) parent.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); NativeContentAdView adView = (NativeContentAdView) inflater .inflate(getContentAdsLayoutId(), parent, false); bindContentAdView(adView, ad); return adView; } private NativeAppInstallAdView getInstallAdView(ViewGroup parent, NativeAppInstallAd ad) { LayoutInflater inflater = (LayoutInflater) parent.getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); NativeAppInstallAdView adView = (NativeAppInstallAdView) inflater .inflate(getInstallAdsLayoutId(), parent, false); bindInstallAdView(adView, ad); return adView; } private void bindContentAdView(NativeContentAdView adView, NativeContentAd ad) { if (adView == null || ad == null) return; TextView tvHeader = (TextView) adView.findViewById(R.id.tvHeader); tvHeader.setText(ad.getHeadline()); adView.setHeadlineView(tvHeader); TextView tvDescription = (TextView) adView.findViewById(R.id.tvDescription); tvDescription.setText(ad.getBody()); adView.setBodyView(tvDescription); ImageView ivLogo = (ImageView) adView.findViewById(R.id.ivLogo); if(ad.getLogo()!=null) ivLogo.setImageDrawable(ad.getLogo().getDrawable()); adView.setLogoView(ivLogo); Button btnAction = (Button) adView.findViewById(R.id.btnAction); btnAction.setText(ad.getCallToAction()); adView.setCallToActionView(btnAction); TextView tvAdvertiser = (TextView) adView.findViewById(R.id.tvAdvertiser); tvAdvertiser.setText(ad.getAdvertiser()); adView.setAdvertiserView(tvAdvertiser); ImageView ivImage = (ImageView) adView.findViewById(R.id.ivImage); if (ad.getImages() != null && ad.getImages().size() > 0) { ivImage.setImageDrawable(ad.getImages().get(0).getDrawable()); ivImage.setVisibility(View.VISIBLE); } else ivImage.setVisibility(View.GONE); adView.setImageView(ivImage); adView.setNativeAd(ad); } private void bindInstallAdView(NativeAppInstallAdView adView, NativeAppInstallAd ad) { if (adView == null || ad == null) return; TextView tvHeader = (TextView) adView.findViewById(R.id.tvHeader); tvHeader.setText(ad.getHeadline()); adView.setHeadlineView(tvHeader); TextView tvDescription = (TextView) adView.findViewById(R.id.tvDescription); tvDescription.setText(ad.getBody()); adView.setBodyView(tvDescription); ImageView ivLogo = (ImageView) adView.findViewById(R.id.ivLogo); if(ad.getIcon()!=null) ivLogo.setImageDrawable(ad.getIcon().getDrawable()); adView.setIconView(ivLogo); Button btnAction = (Button) adView.findViewById(R.id.btnAction); btnAction.setText(ad.getCallToAction()); adView.setCallToActionView(btnAction); TextView tvStore = (TextView) adView.findViewById(R.id.tvStore); tvStore.setText(ad.getStore()); adView.setStoreView(tvStore); TextView tvPrice = (TextView) adView.findViewById(R.id.tvPrice); tvPrice.setText(ad.getPrice()); adView.setPriceView(tvPrice); ImageView ivImage = (ImageView) adView.findViewById(R.id.ivImage); if (ad.getImages() != null && ad.getImages().size() > 0) { ivImage.setImageDrawable(ad.getImages().get(0).getDrawable()); ivImage.setVisibility(View.VISIBLE); } else ivImage.setVisibility(View.GONE); adView.setImageView(ivImage); adView.setNativeAd(ad); } } TextView tvHeader = (TextView) adView.findViewById(R.id.tvHeader); tvHeader.setText(ad.getHeadline()); // adView tvHeader adView.setHeadlineView(tvHeader); <ListView android:id="@+id/lvMessages" android:layout_width="match_parent" android:layout_height="match_parent"/> ListView lvMessages; AdmobAdapterWrapper adapterWrapper; //... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initListViewItems(); } private void initListViewItems() { lvMessages = (ListView) findViewById(R.id.lvMessages); // ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1); adapterWrapper = new AdmobAdapterWrapper(this); adapterWrapper.setAdapter(adapter); // -. // layout //adapterWrapper.setInstallAdsLayoutId(R.layout.your_installad_layout); //adapterWrapper.setcontentAdsLayoutId(R.layout.your_installad_layout); // adapterWrapper.setLimitOfAds(3); // 10 . // , Admob's //, . adapterWrapper.setNoOfDataBetweenAds(10); lvMessages.setAdapter(adapterWrapper); // - // final String sItem = "item #"; ArrayList<String> lst = new ArrayList<String>(100); for(int i=1;i<=100;i++) lst.add(sItem.concat(Integer.toString(i))); adapter.addAll(lst); adapter.notifyDataSetChanged(); } // @Override protected void onDestroy() { super.onDestroy(); adapterWrapper.destroyAds(); } 
W/Ads﹕ Failed to load ad: 0, as described, for example, here try to run not on an emulator, but on a real device, and without access to the root. Another reason may be a lack of advertising on the Admob server, in this case, you should wait some time after the first launch and try again (this is how it was with me).
Source: https://habr.com/ru/post/269517/
All Articles