Skip to content

Commit 3cd5fc7

Browse files
Nicholas Ventimigliacopybara-github
authored andcommitted
Updated native ad Kotlin code snippets.
PiperOrigin-RevId: 806369234
1 parent 1d6cc60 commit 3cd5fc7

2 files changed

Lines changed: 343 additions & 5 deletions

File tree

  • kotlin/advanced
    • APIDemo/app/src/main/java/com/google/android/gms/snippets
    • JetpackComposeDemo/app/src/main/java/com/google/android/gms/example/jetpackcomposedemo/snippets

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

Lines changed: 193 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@
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
1822
import com.google.android.gms.ads.AdListener
1923
import com.google.android.gms.ads.AdLoader
2024
import com.google.android.gms.ads.AdRequest
2125
import com.google.android.gms.ads.LoadAdError
2226
import com.google.android.gms.ads.admanager.AdManagerAdRequest
2327
import com.google.android.gms.ads.nativead.NativeAd
2428
import com.google.android.gms.ads.nativead.NativeAdOptions
29+
import com.google.android.gms.example.apidemo.databinding.NativeAdBinding
2530
import kotlinx.coroutines.CoroutineScope
2631
import kotlinx.coroutines.Dispatchers
2732
import kotlinx.coroutines.launch
@@ -36,12 +41,36 @@ internal class NativeAdSnippets {
3641
val adLoader =
3742
AdLoader.Builder(context, AD_UNIT_ID)
3843
.forNativeAd { nativeAd ->
39-
// The native ad loaded successfully. You can show the ad.
44+
// Called when a native ad is successfully loaded.
4045
}
4146
.withAdListener(
4247
object : AdListener() {
48+
override fun onAdClosed() {
49+
// Called when the ad is closed.
50+
}
51+
4352
override fun onAdFailedToLoad(adError: LoadAdError) {
44-
// The native ad load failed. Check the adError message for failure reasons.
53+
// Called when an ad fails to load.
54+
}
55+
56+
override fun onAdOpened() {
57+
// Called when an ad opens full screen.
58+
}
59+
60+
override fun onAdLoaded() {
61+
// Called when an ad has loaded.
62+
}
63+
64+
override fun onAdClicked() {
65+
// Called when a click is recorded for an ad.
66+
}
67+
68+
override fun onAdImpression() {
69+
// Called when an impression is recorded for an ad.
70+
}
71+
72+
override fun onAdSwipeGestureClicked() {
73+
// Called when a swipe gesture is recorded for an ad.
4574
}
4675
}
4776
)
@@ -97,20 +126,179 @@ internal class NativeAdSnippets {
97126
// [END handle_ad_loaded]
98127
}
99128

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

253+
private fun setEventCallback(adLoader: AdLoader.Builder) {
254+
// [START set_event_callback]
255+
adLoader
256+
.withAdListener(
257+
object : AdListener() {
258+
override fun onAdClosed() {
259+
// Called when the ad is closed.
260+
}
261+
262+
override fun onAdFailedToLoad(adError: LoadAdError) {
263+
// Called when an ad fails to load.
264+
}
265+
266+
override fun onAdOpened() {
267+
// Called when an ad opens full screen.
268+
}
269+
270+
override fun onAdLoaded() {
271+
// Called when an ad has loaded.
272+
}
273+
274+
override fun onAdClicked() {
275+
// Called when a click is recorded for an ad.
276+
}
277+
278+
override fun onAdImpression() {
279+
// Called when an impression is recorded for an ad.
280+
}
281+
282+
override fun onAdSwipeGestureClicked() {
283+
// Called when a swipe gesture is recorded for an ad.
284+
}
285+
}
286+
)
287+
.build()
288+
// [END set_event_callback]
289+
}
290+
291+
private fun setImageScaleType(mediaView: MediaView) {
292+
// [START set_image_scale_type]
293+
mediaView.imageScaleType = ImageView.ScaleType.CENTER_CROP
294+
// [END set_image_scale_type]
295+
}
296+
106297
private companion object {
107298
// Test ad unit IDs.
108299
// For more information,
109300
// see https://developers.google.com/admob/android/test-ads.
110301
// and https://developers.google.com/ad-manager/mobile-ads-sdk/android/test-ads.
111302
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"
115303
}
116304
}
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)