简体   繁体   English

Admob 原生广告视频不显示

[英]Admob native ads video not showing

I successfully set Admob native ads in my app, but the video not showing in the media content, it shows an empty area even the mediaContent is not null, I don't know if this problem happens in real code id and the app must be published in the store, but I tried the real unit id我在我的应用程序中成功设置了 Admob 原生广告,但是媒体内容中没有显示视频,即使mediaContent不是 null 也显示空白区域,我不知道这个问题是否发生在真实代码 ID 中,应用程序必须是在商店发布,但我尝试了真实的单位 ID

在此处输入图像描述

My code我的代码

native_ad_row xml native_ad_row xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nativeAdView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#FFFFFF"
        android:minHeight="50dp"
        android:orientation="vertical">

        <TextView style="@style/Theme.DummyAppKotlin.AdAttribution" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="20dp"
            android:paddingTop="3dp"
            android:paddingRight="20dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/ad_app_icon"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:adjustViewBounds="true"
                    android:paddingEnd="5dp"
                    android:paddingBottom="5dp" />

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/ad_headline"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:textColor="#0000FF"
                        android:textSize="16sp"
                        android:textStyle="bold" />

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">

                        <TextView
                            android:id="@+id/ad_advertiser"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:gravity="bottom"
                            android:textSize="14sp"
                            android:textStyle="bold" />

                        <RatingBar
                            android:id="@+id/ad_stars"
                            style="?android:attr/ratingBarStyleSmall"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:isIndicator="true"
                            android:numStars="5"
                            android:stepSize="0.5" />
                    </LinearLayout>

                </LinearLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/ad_body"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="20dp"
                    android:textSize="12sp" />

                <com.google.android.gms.ads.nativead.MediaView
                    android:id="@+id/ad_media"
                    android:layout_width="match_parent"
                    android:layout_height="175dp"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="5dp" />

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="end"
                    android:orientation="horizontal"
                    android:paddingTop="10dp"
                    android:paddingBottom="10dp">

                    <TextView
                        android:id="@+id/ad_price"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:paddingStart="5dp"
                        android:paddingLeft="5dp"
                        android:paddingEnd="5dp"
                        android:paddingRight="5dp"
                        android:textSize="12sp" />

                    <TextView
                        android:id="@+id/ad_store"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:paddingStart="5dp"
                        android:paddingLeft="5dp"
                        android:paddingEnd="5dp"
                        android:paddingRight="5dp"
                        android:textSize="12sp" />

                    <Button
                        android:id="@+id/ad_call_to_action"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:textSize="12sp" />

                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </LinearLayout>


</com.google.android.gms.ads.nativead.NativeAdView>

The NativeAdViewholder NativeAdViewholder

    inner class AdViewHolder(private val binding: NativeAdRowBinding) :
        RecyclerView.ViewHolder(binding.root) {

        private val videoOptions = VideoOptions.Builder()
            .setStartMuted(false)
            .build()

        fun bindAdData() {
            val adLoader =
                AdLoader.Builder(binding.root.context, "ca-app-pub-3940256099942544/1044960115")
                    .forNativeAd { nativeAd: NativeAd ->

                        this@PostAdapter.nativeAd = nativeAd
                        populateNativeADView(nativeAd)



                    }
                    .withAdListener(object : AdListener() {

                        override fun onAdClicked() {
                            super.onAdClicked()
                            Log.d(TAG, "onAdClicked: ")
                        }

                        override fun onAdClosed() {
                            super.onAdClosed()
                            Log.d(TAG, "onAdClosed: ")
                        }

                        override fun onAdLoaded() {
                            super.onAdLoaded()
                            Log.d(TAG, "onAdLoaded: ")
                        }

                        override fun onAdOpened() {
                            super.onAdOpened()
                            Log.d(TAG, "onAdOpened: ")
                        }

                        override fun onAdFailedToLoad(adError: LoadAdError) {
                            // Handle the failure by logging, altering the UI, and so on.
                            Toast.makeText(
                                binding.root.context,
                                adError.message,
                                Toast.LENGTH_SHORT
                            ).show()

                            Log.e(TAG, "onAdFailedToLoad: ${adError.cause.toString()}")
                        }
                    })
                    .withNativeAdOptions(
                        NativeAdOptions.Builder()
                            // Methods in the NativeAdOptions.Builder class can be
                            // used here to specify individual options settings.
                            .setVideoOptions(videoOptions).build()
                    )
                    .build()

            adLoader.loadAd(AdRequest.Builder().build())
        }

        private fun populateNativeADView(nativeAd: NativeAd) {
            val headLine = nativeAd.headline
            val body = nativeAd.body
            val callToAction = nativeAd.callToAction
            val icon = nativeAd.icon
            val price = nativeAd.price
            val store = nativeAd.store
            val storeRating = nativeAd.starRating
            val advertiser = nativeAd.advertiser
            val mediaContent = nativeAd.mediaContent

            if (headLine.isNullOrEmpty()) {
                binding.adHeadline.visibility = INVISIBLE
            } else {
                binding.adHeadline.visibility = View.VISIBLE
                binding.adHeadline.text = headLine
            }

            if (body.isNullOrEmpty()) {
                binding.adBody.visibility = INVISIBLE
            } else {
                binding.adBody.visibility = View.VISIBLE
                binding.adBody.text = headLine
            }
            if (icon == null) {
                binding.adAppIcon.visibility = INVISIBLE
            } else {
                binding.adAppIcon.visibility = View.VISIBLE
                binding.adAppIcon.setImageDrawable(icon.drawable)
            }
            if (storeRating == null) {
                binding.adStars.visibility = INVISIBLE
            } else {
                binding.adStars.visibility = View.VISIBLE
                binding.adStars.rating = storeRating.toFloat()
            }
            if (price.isNullOrEmpty()) {
                binding.adPrice.visibility = INVISIBLE
            } else {
                binding.adPrice.visibility = View.VISIBLE
                binding.adPrice.text = price
            }
            if (store.isNullOrEmpty()) {
                binding.adStore.visibility = INVISIBLE
            } else {
                binding.adStore.visibility = View.VISIBLE
                binding.adStore.text = store
            }
            if (advertiser.isNullOrEmpty()) {
                binding.adAdvertiser.visibility = INVISIBLE
            } else {
                binding.adAdvertiser.visibility = View.VISIBLE
                binding.adAdvertiser.text = advertiser
            }
            if (mediaContent == null ) {
                binding.adMedia.visibility = INVISIBLE
            } else {
                binding.adMedia.visibility = View.VISIBLE
                binding.adMedia.setMediaContent(mediaContent)
                Log.d(TAG, "setMediaContent: ${mediaContent.duration.toString()}")
            }
            if (callToAction.isNullOrEmpty()) {
                binding.adCallToAction.visibility = INVISIBLE
            } else {
                binding.adCallToAction.visibility = View.VISIBLE
                binding.adCallToAction.text = callToAction
                binding.nativeAdView.callToActionView = binding.adCallToAction

            }

            binding.nativeAdView.setNativeAd(nativeAd)
        }

in mainActivity在主活动中

 val testDeviceIds = Arrays.asList("ASOMEIDS")
        val configuration = RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build()
        MobileAds.setRequestConfiguration(configuration)
        if (Utils.hasInternetConnection(this)) {
            MobileAds.initialize(this) {
                Log.d(TAG, "onViewCreated: onInitCompleted")
            }
        }

Google updates their github samples apps to version 'com.google.android.gms:play-services-ads:21.0.0' you can try it, Advanced Native Kotlin sample can found here https://github.com/googleads/googleads-mobile-android-examples Google 将他们的 github 示例应用程序更新为版本'com.google.android.gms:play-services-ads:21.0.0'你可以试试,高级原生 Kotlin 示例可以在这里找到https://github.com/googleads/googleads -mobile-android-示例

first, create unified XML like this首先,像这样创建统一的 XML

<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#FFFFFF"
        android:minHeight="50dp"
        android:orientation="vertical">

        <TextView style="@style/AppTheme.AdAttribution"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingTop="3dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/ad_app_icon"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:adjustViewBounds="true"
                    android:paddingBottom="5dp"
                    android:paddingRight="5dp"
                    android:paddingEnd="5dp"/>

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/ad_headline"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:textColor="#0000FF"
                        android:textSize="16sp"
                        android:textStyle="bold" />

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">

                        <TextView
                            android:id="@+id/ad_advertiser"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:gravity="bottom"
                            android:textSize="14sp"
                            android:textStyle="bold"/>

                        <RatingBar
                            android:id="@+id/ad_stars"
                            style="?android:attr/ratingBarStyleSmall"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:isIndicator="true"
                            android:numStars="5"
                            android:stepSize="0.5" />
                    </LinearLayout>

                </LinearLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/ad_body"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="20dp"
                    android:layout_marginEnd="20dp"
                    android:textSize="12sp" />

                <com.google.android.gms.ads.nativead.MediaView
                    android:id="@+id/ad_media"
                    android:layout_gravity="center_horizontal"
                    android:layout_width="250dp"
                    android:layout_height="175dp"
                    android:layout_marginTop="5dp" />

                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="end"
                    android:orientation="horizontal"
                    android:paddingBottom="10dp"
                    android:paddingTop="10dp">

                    <TextView
                        android:id="@+id/ad_price"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:paddingLeft="5dp"
                        android:paddingStart="5dp"
                        android:paddingRight="5dp"
                        android:paddingEnd="5dp"
                        android:textSize="12sp" />

                    <TextView
                        android:id="@+id/ad_store"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:paddingLeft="5dp"
                        android:paddingStart="5dp"
                        android:paddingRight="5dp"
                        android:paddingEnd="5dp"
                        android:textSize="12sp" />

                    <Button
                        android:id="@+id/ad_call_to_action"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:textSize="12sp" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

second, implement the native ad in activity二、在activity中实现原生广告

const val ADMOB_AD_UNIT_ID = "ca-app-pub-3940256099942544/1044960115"
var currentNativeAd: NativeAd? = null

/** A simple activity class that displays native ad formats. */
class MainActivity : AppCompatActivity() {

  private lateinit var mainActivityBinding: ActivityMainBinding

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mainActivityBinding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(mainActivityBinding.root)

    // Initialize the Mobile Ads SDK.
    MobileAds.initialize(this) {}

    mainActivityBinding.refreshButton.setOnClickListener { refreshAd() }

    refreshAd()
  }

  /**
   * Populates a [NativeAdView] object with data from a given [NativeAd].
   *
   * @param nativeAd the object containing the ad's assets
   * @param unifiedAdBinding the binding object of the layout that has NativeAdView as the root view
   */
  private fun populateNativeAdView(nativeAd: NativeAd, unifiedAdBinding: AdUnifiedBinding) {
    val nativeAdView = unifiedAdBinding.root

    // Set the media view.
    nativeAdView.mediaView = unifiedAdBinding.adMedia

    // Set other ad assets.
    nativeAdView.headlineView = unifiedAdBinding.adHeadline
    nativeAdView.bodyView = unifiedAdBinding.adBody
    nativeAdView.callToActionView = unifiedAdBinding.adCallToAction
    nativeAdView.iconView = unifiedAdBinding.adAppIcon
    nativeAdView.priceView = unifiedAdBinding.adPrice
    nativeAdView.starRatingView = unifiedAdBinding.adStars
    nativeAdView.storeView = unifiedAdBinding.adStore
    nativeAdView.advertiserView = unifiedAdBinding.adAdvertiser

    // The headline and media content are guaranteed to be in every UnifiedNativeAd.
    unifiedAdBinding.adHeadline.text = nativeAd.headline
    nativeAd.mediaContent?.let { unifiedAdBinding.adMedia.setMediaContent(it) }

    // These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
    // check before trying to display them.
    if (nativeAd.body == null) {
      unifiedAdBinding.adBody.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adBody.visibility = View.VISIBLE
      unifiedAdBinding.adBody.text = nativeAd.body
    }

    if (nativeAd.callToAction == null) {
      unifiedAdBinding.adCallToAction.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adCallToAction.visibility = View.VISIBLE
      unifiedAdBinding.adCallToAction.text = nativeAd.callToAction
    }

    if (nativeAd.icon == null) {
      unifiedAdBinding.adAppIcon.visibility = View.GONE
    } else {
      unifiedAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
      unifiedAdBinding.adAppIcon.visibility = View.VISIBLE
    }

    if (nativeAd.price == null) {
      unifiedAdBinding.adPrice.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adPrice.visibility = View.VISIBLE
      unifiedAdBinding.adPrice.text = nativeAd.price
    }

    if (nativeAd.store == null) {
      unifiedAdBinding.adStore.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adStore.visibility = View.VISIBLE
      unifiedAdBinding.adStore.text = nativeAd.store
    }

    if (nativeAd.starRating == null) {
      unifiedAdBinding.adStars.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adStars.rating = nativeAd.starRating!!.toFloat()
      unifiedAdBinding.adStars.visibility = View.VISIBLE
    }

    if (nativeAd.advertiser == null) {
      unifiedAdBinding.adAdvertiser.visibility = View.INVISIBLE
    } else {
      unifiedAdBinding.adAdvertiser.text = nativeAd.advertiser
      unifiedAdBinding.adAdvertiser.visibility = View.VISIBLE
    }

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

    // Get the video controller for the ad. One will always be provided, even if the ad doesn't
    // have a video asset.
    val vc = nativeAd.mediaContent?.videoController

    // Updates the UI to say whether or not this ad has a video asset.
    if (vc != null && vc.hasVideoContent()) {
      // Create a new VideoLifecycleCallbacks object and pass it to the VideoController. The
      // VideoController will call methods on this object when events occur in the video
      // lifecycle.
      vc.videoLifecycleCallbacks =
        object : VideoController.VideoLifecycleCallbacks() {
          override fun onVideoEnd() {
            // Publishers should allow native ads to complete video playback before
            // refreshing or replacing them with another ad in the same UI location.
            mainActivityBinding.refreshButton.isEnabled = true
            mainActivityBinding.videostatusText.text = "Video status: Video playback has ended."
            super.onVideoEnd()
          }
        }
    } else {
      mainActivityBinding.videostatusText.text = "Video status: Ad does not contain a video asset."
      mainActivityBinding.refreshButton.isEnabled = true
    }
  }

  /**
   * Creates a request for a new native ad based on the boolean parameters and calls the
   * corresponding "populate" method when one is successfully returned.
   */
  private fun refreshAd() {
    mainActivityBinding.refreshButton.isEnabled = false

    val builder = AdLoader.Builder(this, ADMOB_AD_UNIT_ID)

    builder.forNativeAd { nativeAd ->
      // OnUnifiedNativeAdLoadedListener implementation.
      // If this callback occurs after the activity is destroyed, you must call
      // destroy and return or you may get a memory leak.
      var activityDestroyed = false
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        activityDestroyed = isDestroyed
      }
      if (activityDestroyed || isFinishing || isChangingConfigurations) {
        nativeAd.destroy()
        return@forNativeAd
      }
      // You must call destroy on old ads when you are done with them,
      // otherwise you will have a memory leak.
      currentNativeAd?.destroy()
      currentNativeAd = nativeAd
      val unifiedAdBinding = AdUnifiedBinding.inflate(layoutInflater)
      populateNativeAdView(nativeAd, unifiedAdBinding)
      mainActivityBinding.adFrame.removeAllViews()
      mainActivityBinding.adFrame.addView(unifiedAdBinding.root)
    }

    val videoOptions =
      VideoOptions.Builder().setStartMuted(mainActivityBinding.startMutedCheckbox.isChecked).build()

    val adOptions = NativeAdOptions.Builder().setVideoOptions(videoOptions).build()

    builder.withNativeAdOptions(adOptions)

    val adLoader =
      builder
        .withAdListener(
          object : AdListener() {
            override fun onAdFailedToLoad(loadAdError: LoadAdError) {
              val error =
                """
           domain: ${loadAdError.domain}, code: ${loadAdError.code}, message: ${loadAdError.message}
          """"
              mainActivityBinding.refreshButton.isEnabled = true
              Toast.makeText(
                this@MainActivity,
                "Failed to load native ad with error $error",
                Toast.LENGTH_SHORT
              )
                .show()
            }
          }
        )
        .build()

    adLoader.loadAd(AdRequest.Builder().build())

    mainActivityBinding.videostatusText.text = ""
  }

  override fun onDestroy() {
    currentNativeAd?.destroy()
    super.onDestroy()
  }
}

If you need to test it with a test key you need to replace the val testDeviceIds = Arrays.asList("ASOMEIDS") with your test device id, you can get it from your log once you run your app as this I/Ads: Use RequestConfiguration.Builder.setTestDeviceIds(Arrays.asList("33BE2250B43518CCDA7DE426D04EE231")) to get test ads on this device."如果您需要使用测试密钥对其进行测试,则需要将val testDeviceIds = Arrays.asList("ASOMEIDS")替换为您的测试设备 ID,一旦您将应用程序作为此 I/Ads 运行,您就可以从日志中获取它:使用 RequestConfiguration.Builder.setTestDeviceIds(Arrays.asList("33BE2250B43518CCDA7DE426D04EE231")) 在此设备上获取测试广告。"

or simply you can test it on an emulator because Android emulators are automatically configured as test devices.或者只是您可以在模拟器上对其进行测试,因为 Android 模拟器会自动配置为测试设备。

https://developers.google.com/admob/android/test-ads check this out. https://developers.google.com/admob/android/test-ads看看这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM