18

I got an email from AdMob today saying:

Change to native ads policy: Native ads will require MediaView to render the video or main image asset. In an effort to help you deliver a better ad experience more easily, beginning October 29th, native ads will require MediaView to render the video or main image asset. Ad units not compliant by this date will stop serving ads, which could impact your ad revenue.

I tried this out in my Android app, removing the separate handling of images with ImageView and video with MediaView, but I have found that the MediaView is not resizing the view's height according to the height of the image it displays.

In this codelab example from Google, a fixed height and width for the MediaView are used. I cannot do this, as this screen is responsive to the screen size, which will change depending on the device. The fact that the image can be dynamically resized is one of the main benefits for using UnifiedNativeAds instead of predefined ads such as banners.

This is how I need to be displaying the MediaView, using match_parent for width and wrap_content for height.

<com.google.android.gms.ads.formats.MediaView
            android:id="@+id/ad_media"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:adjustViewBounds="true"
            android:scaleType="fitXY"/>

This is what I am currently getting from the above code

This is what I need and expect it to look like from using wrap_content

In the previous case where we were able to render the images separately using ImageView, the wrap_content value correctly sized the image.

Does anyone have a workaround for this? How can I follow the new Google requirements without hardcoding the MediaView's height?

My full code can be found here, in my demo app on github.

Sarah
  • 183
  • 1
  • 8

5 Answers5

29
mediaView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
    @Override
    public void onChildViewAdded(View parent, View child) {
        if (child instanceof ImageView) {
            ImageView imageView = (ImageView) child;
            imageView.setAdjustViewBounds(true);
        }
    }

    @Override
    public void onChildViewRemoved(View parent, View child) {}
});
Robbie
  • 17,090
  • 4
  • 31
  • 66
Richard
  • 316
  • 3
  • 5
  • Can you add what you've changed/why/what the difference is? – Robbie Aug 31 '18 at 03:18
  • Thanks! This was exactly what I needed. – Sarah Sep 03 '18 at 09:25
  • 1
    Keep in mind, don't worry about what if it adds video. Because video is WebView and it fits the layout without problem. – Ataberk May 08 '19 at 21:17
  • @Richard or any other know according to https://support.google.com/admob/answer/6329638 (Only the ad titles, URLs, CTA, and image assets can be clickable (no clickable "white" space)), white area should not be clickable. If we do match parent and ad is portrait then it left with some clickable white space. Any workaround of this or it is not policy violation ? – Smeet Oct 05 '19 at 14:05
  • @Sarah or any other know according to support.google.com/admob/answer/6329638 (Only the ad titles, URLs, CTA, and image assets can be clickable (no clickable "white" space)), white area should not be clickable. If we do match parent and ad is portrait then it left with some clickable white space. Any workaround of this or it is not policy violation ? – Smeet Oct 05 '19 at 14:05
  • @Ataberk - can you confirm `wrap_content` weight works well in case of video? [Here](https://support.google.com/admob/answer/6329638) it says: `For native videos, the main asset MediaView must be at least 120x120dp (Android) or 120x120pts (iOS). Video ads will not serve to implementations with main asset MediaViews smaller than 120dp in any dimension.` – Primož Kralj May 12 '20 at 07:11
  • @PrimožKralj If MediaView is rendering video, wrap_content will not work consistently in all devices. You can try the Nexus 5X to test this behaviour but only in video content – Adelino May 26 '20 at 11:03
  • About video, are there any specs of what aspect ratio they can be? If I want the video to fit in width, I don't want it to cover entire screen vertically in case its aspect ratio is vertical, for example... How do you handle videos? – android developer Aug 03 '20 at 12:26
0

I was facing the same problem, after trying a lot with trial and error, I found that wrapping <FrameLayout...>(in which you are adding UnifiedNativeAdView) with ScrollView will resolve this problem.

Smeet
  • 3,558
  • 1
  • 28
  • 42
0
for (int i = 0; i < mediaView.getChildCount(); i++) {
    View view = mediaView.getChildAt(i);
    if (view instanceof ImageView) {
        ((ImageView) view).setAdjustViewBounds(true);
    }
}

This works for me.I tried Richard's answer,But it didn't works well in a RecyclerView.

0

If implementing Advanced Native Ads, use "imageScaleType" property of MediaView as suggested here in the official docs https://developers.google.com/admob/android/native/advanced#setting_imagescaletype

adView.mediaView.setImageScaleType(ImageView.ScaleType.CENTER_CROP)

or any other ScaleType as per requirement.

Damanpreet Singh
  • 359
  • 5
  • 11
0

To ensure that all media are as wide as possible and that they respect a maximum height (so there are no surprises depending on the dimensions of the media).

XML

<com.google.android.gms.ads.formats.MediaView
     android:id="@+id/ad_media"
     android:layout_gravity="center_horizontal"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />

JAVA

mediaView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
        @Override
        public void onChildViewAdded(View parent, View child) {
            float scale = context.getResources().getDisplayMetrics().density;
            
            int maxHeightPixels = 175;
            int maxHeightDp = (int) (maxHeightPixels * scale + 0.5f);

            if (child instanceof ImageView) { //Images
                ImageView imageView = (ImageView) child;
                imageView.setAdjustViewBounds(true);
                imageView.setMaxHeight(maxHeightDp);

            } else { //Videos
                ViewGroup.LayoutParams params = child.getLayoutParams();
                params.height = maxHeightDp;
                child.setLayoutParams(params);
            }
        }

        @Override
        public void onChildViewRemoved(View parent, View child) {}
    });