[英]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.