Skip to content

Commit b01c3a5

Browse files
Nicholas Ventimigliacopybara-github
authored andcommitted
Updated native ad Kotlin code snippets.
PiperOrigin-RevId: 806369234
1 parent 0a4f6f7 commit b01c3a5

File tree

3 files changed

+318
-3
lines changed

3 files changed

+318
-3
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<com.google.android.gms.ads.nativead.NativeAdView
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="wrap_content">
5+
<LinearLayout
6+
android:orientation="vertical">
7+
<LinearLayout
8+
android:orientation="horizontal">
9+
<ImageView
10+
android:id="@+id/ad_app_icon" />
11+
<TextView
12+
android:id="@+id/ad_headline" />
13+
</LinearLayout>
14+
<!--Add remaining assets such as the image and media view.-->
15+
</LinearLayout>
16+
</com.google.android.gms.ads.nativead.NativeAdView>

kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdSnippets.kt

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,21 @@
1414

1515
package com.google.android.gms.snippets
1616

17+
import android.app.Activity
1718
import android.content.Context
19+
import android.view.LayoutInflater
20+
import android.view.View
21+
import android.widget.FrameLayout
22+
import android.widget.ImageView
1823
import com.google.android.gms.ads.AdListener
1924
import com.google.android.gms.ads.AdLoader
2025
import com.google.android.gms.ads.AdRequest
2126
import com.google.android.gms.ads.LoadAdError
2227
import com.google.android.gms.ads.admanager.AdManagerAdRequest
28+
import com.google.android.gms.ads.nativead.MediaView
2329
import com.google.android.gms.ads.nativead.NativeAd
2430
import com.google.android.gms.ads.nativead.NativeAdOptions
31+
import com.google.android.gms.example.apidemo.databinding.NativeAdBinding
2532
import kotlinx.coroutines.CoroutineScope
2633
import kotlinx.coroutines.Dispatchers
2734
import kotlinx.coroutines.launch
@@ -97,20 +104,162 @@ internal class NativeAdSnippets {
97104
// [END handle_ad_loaded]
98105
}
99106

107+
private fun addNativeAdView(
108+
activity: Activity,
109+
nativeAd: NativeAd,
110+
layoutInflater: LayoutInflater,
111+
frameLayout: FrameLayout,
112+
) {
113+
// [START add_ad_view]
114+
activity.runOnUiThread {
115+
// Inflate the native ad view and add it to the view hierarchy.
116+
val nativeAdBinding = NativeAdBinding.inflate(layoutInflater)
117+
val adView = nativeAdBinding.root
118+
119+
// Display and register the native ad asset views here.
120+
displayNativeAd(nativeAd, nativeAdBinding)
121+
122+
// Remove all old ad views and add the new native.
123+
frameLayout.removeAllViews()
124+
// Add the new native ad view to the view hierarchy.
125+
frameLayout.addView(adView)
126+
}
127+
// [END add_ad_view]
128+
}
129+
130+
// [START display_native_ad]
131+
private fun displayNativeAd(nativeAd: NativeAd, nativeAdBinding: NativeAdBinding) {
132+
// [START populate_native_ad_view]
133+
// Populate all native ad view assets with the native ad.
134+
nativeAdBinding.adMedia.mediaContent = nativeAd.mediaContent
135+
nativeAdBinding.adAdvertiser.text = nativeAd.advertiser
136+
nativeAdBinding.adBody.text = nativeAd.body
137+
nativeAdBinding.adCallToAction.text = nativeAd.callToAction
138+
nativeAdBinding.adHeadline.text = nativeAd.headline
139+
nativeAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
140+
nativeAdBinding.adPrice.text = nativeAd.price
141+
nativeAd.starRating?.toFloat().also { value ->
142+
if (value != null) {
143+
nativeAdBinding.adStars.rating = value
144+
}
145+
}
146+
nativeAdBinding.adStore.text = nativeAd.store
147+
// [END populate_native_ad_view]
148+
149+
// [START hide_native_ad_view_assets]
150+
// Hide all native ad view assets that are not returned within the native ad.
151+
if (nativeAd.body == null) {
152+
nativeAdBinding.adBody.visibility = View.INVISIBLE
153+
} else {
154+
nativeAdBinding.adBody.text = nativeAd.body
155+
nativeAdBinding.adBody.visibility = View.VISIBLE
156+
}
157+
158+
if (nativeAd.callToAction == null) {
159+
nativeAdBinding.adCallToAction.visibility = View.INVISIBLE
160+
} else {
161+
nativeAdBinding.adCallToAction.text = nativeAd.callToAction
162+
nativeAdBinding.adCallToAction.visibility = View.VISIBLE
163+
}
164+
165+
if (nativeAd.icon == null) {
166+
nativeAdBinding.adAppIcon.visibility = View.GONE
167+
} else {
168+
nativeAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
169+
nativeAdBinding.adAppIcon.visibility = View.VISIBLE
170+
}
171+
172+
if (nativeAd.price == null) {
173+
nativeAdBinding.adPrice.visibility = View.INVISIBLE
174+
} else {
175+
nativeAdBinding.adPrice.text = nativeAd.price
176+
nativeAdBinding.adPrice.visibility = View.VISIBLE
177+
}
178+
179+
if (nativeAd.store == null) {
180+
nativeAdBinding.adStore.visibility = View.INVISIBLE
181+
} else {
182+
nativeAdBinding.adStore.text = nativeAd.store
183+
nativeAdBinding.adStore.visibility = View.VISIBLE
184+
}
185+
186+
if (nativeAd.starRating == null) {
187+
nativeAdBinding.adStars.visibility = View.INVISIBLE
188+
} else {
189+
nativeAdBinding.adStars.rating = nativeAd.starRating!!.toFloat()
190+
nativeAdBinding.adStars.visibility = View.VISIBLE
191+
}
192+
193+
if (nativeAd.advertiser == null) {
194+
nativeAdBinding.adAdvertiser.visibility = View.INVISIBLE
195+
} else {
196+
nativeAdBinding.adAdvertiser.text = nativeAd.advertiser
197+
nativeAdBinding.adAdvertiser.visibility = View.VISIBLE
198+
}
199+
// [END hide_native_ad_view_assets]
200+
201+
// [START register_native_ad_assets]
202+
// Register all native ad assets with the native ad view.
203+
val nativeAdView = nativeAdBinding.root
204+
nativeAdView.advertiserView = nativeAdBinding.adAdvertiser
205+
nativeAdView.bodyView = nativeAdBinding.adBody
206+
nativeAdView.callToActionView = nativeAdBinding.adCallToAction
207+
nativeAdView.headlineView = nativeAdBinding.adHeadline
208+
nativeAdView.iconView = nativeAdBinding.adAppIcon
209+
nativeAdView.priceView = nativeAdBinding.adPrice
210+
nativeAdView.starRatingView = nativeAdBinding.adStars
211+
nativeAdView.storeView = nativeAdBinding.adStore
212+
nativeAd.mediaContent?.let { nativeAdBinding.adMedia.setMediaContent(it) }
213+
nativeAdView.mediaView = nativeAdBinding.adMedia
214+
// [END register_native_ad_assets]
215+
216+
// [START set_native_ad]
217+
// This method tells the Google Mobile Ads SDK that you have finished populating your
218+
// native ad view with this native ad.
219+
nativeAdView.setNativeAd(nativeAd)
220+
// [END set_native_ad]
221+
}
222+
223+
// [END display_native_ad]
224+
100225
private fun destroyAd(nativeAd: NativeAd) {
101226
// [START destroy_ad]
102227
nativeAd.destroy()
103228
// [END destroy_ad]
104229
}
105230

231+
private fun setEventCallback(adLoader: AdLoader.Builder) {
232+
// [START set_event_callback]
233+
adLoader
234+
.withAdListener(
235+
object : AdListener() {
236+
override fun onAdFailedToLoad(adError: LoadAdError) {
237+
// Handle the failure.
238+
}
239+
240+
override fun onAdClicked() {
241+
// Log the click event or other custom behavior.
242+
}
243+
}
244+
)
245+
.build()
246+
// [END set_event_callback]
247+
}
248+
249+
// [START set_image_scale_type_compose]
250+
private fun setImageScaleType(mediaView: MediaView) {
251+
// [START set_image_scale_type]
252+
mediaView.setImageScaleType(ImageView.ScaleType.CENTER_CROP)
253+
// [END set_image_scale_type]
254+
}
255+
256+
// [END set_image_scale_type_compose]
257+
106258
private companion object {
107259
// Test ad unit IDs.
108260
// For more information,
109261
// see https://developers.google.com/admob/android/test-ads.
110262
// and https://developers.google.com/ad-manager/mobile-ads-sdk/android/test-ads.
111263
const val AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"
112-
const val VIDEO_AD_UNIT_ID = "ca-app-pub-3940256099942544/1044960115"
113-
const val ADMANAGER_AD_UNIT_ID = "/21775744923/example/native"
114-
const val ADMANAGER_VIDEO_AD_UNIT_ID = "/21775744923/example/native-video"
115264
}
116265
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.android.gms.example.jetpackcomposedemo.snippets
16+
17+
import androidx.compose.foundation.layout.Box
18+
import androidx.compose.foundation.layout.Column
19+
import androidx.compose.foundation.layout.fillMaxHeight
20+
import androidx.compose.foundation.layout.fillMaxWidth
21+
import androidx.compose.foundation.layout.height
22+
import androidx.compose.foundation.layout.padding
23+
import androidx.compose.foundation.layout.wrapContentHeight
24+
import androidx.compose.material3.MaterialTheme
25+
import androidx.compose.material3.Text
26+
import androidx.compose.runtime.Composable
27+
import androidx.compose.ui.Alignment
28+
import androidx.compose.ui.Modifier
29+
import androidx.compose.ui.platform.LocalContext
30+
import androidx.compose.ui.unit.dp
31+
import com.example.jetpackcomposedemo.R
32+
import com.google.android.gms.ads.nativead.NativeAd
33+
import com.google.android.gms.compose_util.NativeAdAttribution
34+
import com.google.android.gms.compose_util.NativeAdHeadlineView
35+
import com.google.android.gms.compose_util.NativeAdMediaView
36+
import com.google.android.gms.compose_util.NativeAdView
37+
38+
/** Kotlin code snippets for the developer guide. */
39+
internal class NativeAdSnippets {
40+
41+
// [START define_native_ad_view]
42+
@Composable
43+
/** Display a native ad with a user defined template. */
44+
fun DefineNativeAdView(nativeAd: NativeAd) {
45+
val context = LocalContext.current
46+
Box(modifier = Modifier.padding(8.dp).wrapContentHeight(Alignment.Top)) {
47+
// Call the NativeAdView composable to display the native ad.
48+
NativeAdView {
49+
// Inside the NativeAdView composable, display the native ad assets.
50+
Column(Modifier.align(Alignment.TopStart).wrapContentHeight(Alignment.Top)) {
51+
// Display the ad attribution. This is required.
52+
NativeAdAttribution(text = context.getString(R.string.attribution))
53+
// Display the headline asset. This is required.
54+
nativeAd.headline?.let {
55+
NativeAdHeadlineView { Text(text = it, style = MaterialTheme.typography.headlineLarge) }
56+
}
57+
// Display the media asset. This is required.
58+
NativeAdMediaView(Modifier.fillMaxWidth().height(500.dp).fillMaxHeight())
59+
}
60+
}
61+
}
62+
}
63+
64+
// [END define_native_ad_view]
65+
66+
// [START display_native_ad_screen]
67+
@Composable
68+
fun DisplayNativeAdScreen() {
69+
var nativeAd by remember { mutableStateOf<NativeAd?>(null) }
70+
val context = LocalContext.current
71+
var isDisposed by remember { mutableStateOf(false) }
72+
73+
DisposableEffect(Unit) {
74+
// Load the native ad when we launch this screen
75+
loadNativeAd(
76+
context = context,
77+
onAdLoaded = { ad ->
78+
// Handle the native ad being loaded.
79+
if (!isDisposed) {
80+
nativeAd = ad
81+
} else {
82+
// Destroy the native ad if loaded after the screen is disposed.
83+
ad.destroy()
84+
}
85+
},
86+
)
87+
// [START destroy_native_ad]
88+
// Destroy the native ad to prevent memory leaks when we dispose of this screen.
89+
onDispose {
90+
isDisposed = true
91+
nativeAd?.destroy()
92+
nativeAd = null
93+
}
94+
// [END destroy_native_ad]
95+
}
96+
97+
// Display the native ad view with a user defined template.
98+
nativeAd?.let { adValue -> displayNativeAdView(adValue) }
99+
}
100+
101+
// [END display_native_ad_screen]
102+
103+
// [START load_native_ad_compose]
104+
fun loadNativeAd(context: Context, onAdLoaded: (NativeAd) -> Unit) {
105+
val adLoader =
106+
AdLoader.Builder(context, AD_UNIT_ID)
107+
.forNativeAd { nativeAd -> onAdLoaded(nativeAd) }
108+
.withAdListener(
109+
object : AdListener() {
110+
override fun onAdFailedToLoad(error: LoadAdError) {
111+
Log.e(TAG, "Native ad failed to load: ${error.message}")
112+
}
113+
114+
override fun onAdLoaded() {
115+
Log.d(TAG, "Native ad was loaded.")
116+
}
117+
118+
override fun onAdImpression() {
119+
Log.d(TAG, "Native ad recorded an impression.")
120+
}
121+
122+
override fun onAdClicked() {
123+
Log.d(TAG, "Native ad was clicked.")
124+
}
125+
}
126+
)
127+
.build()
128+
adLoader.loadAd(AdRequest.Builder().build())
129+
}
130+
131+
// [END load_native_ad_compose]
132+
133+
@Composable
134+
fun SetImageScaleType() {
135+
// [START set_image_scale_type_compose]
136+
NativeAdMediaView(Modifier.fillMaxWidth(), scaleType = ImageView.ScaleType.CENTER_CROP)
137+
// [END set_image_scale_type_compose]
138+
}
139+
140+
private companion object {
141+
// Test ad unit IDs.
142+
// For more information,
143+
// see https://developers.google.com/admob/android/test-ads.
144+
// and https://developers.google.com/ad-manager/mobile-ads-sdk/android/test-ads.
145+
const val AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"
146+
const val VIDEO_AD_UNIT_ID = "ca-app-pub-3940256099942544/1044960115"
147+
const val ADMANAGER_AD_UNIT_ID = "/21775744923/example/native"
148+
const val ADMANAGER_VIDEO_AD_UNIT_ID = "/21775744923/example/native-video"
149+
}
150+
}

0 commit comments

Comments
 (0)