Skip to content

Commit f6fa53b

Browse files
Nicholas Ventimigliacopybara-github
authored andcommitted
Updated native ad Kotlin code snippets.
PiperOrigin-RevId: 806369234
1 parent 516f36e commit f6fa53b

File tree

2 files changed

+291
-46
lines changed
  • kotlin/advanced
    • APIDemo/app/src/main/java/com/google/android/gms/snippets
    • JetpackComposeDemo/app/src/main/java/com/google/android/gms/example/jetpackcomposedemo/snippets

2 files changed

+291
-46
lines changed

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

Lines changed: 140 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,23 @@
1414

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

17-
import android.content.Context
17+
import android.app.Activity
18+
import android.view.LayoutInflater
19+
import android.view.View
20+
import android.widget.FrameLayout
21+
import android.widget.ImageView
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
27+
import com.google.android.gms.ads.nativead.MediaView
2328
import com.google.android.gms.ads.nativead.NativeAd
24-
import com.google.android.gms.ads.nativead.NativeAdOptions
25-
import kotlinx.coroutines.CoroutineScope
26-
import kotlinx.coroutines.Dispatchers
27-
import kotlinx.coroutines.launch
29+
import com.google.android.gms.example.apidemo.databinding.NativeAdBinding
2830

2931
/** Kotlin code snippets for the developer guide. */
3032
internal class NativeAdSnippets {
3133

32-
private fun createAdLoader(context: Context) {
33-
// [START create_ad_loader]
34-
// It is recommended to call AdLoader.Builder on a background thread.
35-
CoroutineScope(Dispatchers.IO).launch {
36-
val adLoader =
37-
AdLoader.Builder(context, AD_UNIT_ID)
38-
.forNativeAd { nativeAd ->
39-
// The native ad loaded successfully. You can show the ad.
40-
}
41-
.withAdListener(
42-
object : AdListener() {
43-
override fun onAdFailedToLoad(adError: LoadAdError) {
44-
// The native ad load failed. Check the adError message for failure reasons.
45-
}
46-
}
47-
)
48-
// Use the NativeAdOptions.Builder class to specify individual options settings.
49-
.withNativeAdOptions(NativeAdOptions.Builder().build())
50-
.build()
51-
}
52-
// [END create_ad_loader]
53-
}
54-
55-
private fun setAdLoaderListener(adLoaderBuilder: AdLoader.Builder) {
56-
// [START set_ad_listener]
57-
adLoaderBuilder.withAdListener(
58-
// Override AdListener callbacks here.
59-
object : AdListener() {}
60-
)
61-
// [END set_ad_listener]
62-
}
63-
6434
private fun loadAd(adLoader: AdLoader) {
6535
// [START load_ad]
6636
adLoader.loadAd(AdRequest.Builder().build())
@@ -97,20 +67,144 @@ internal class NativeAdSnippets {
9767
// [END handle_ad_loaded]
9868
}
9969

70+
private fun addNativeAdView(
71+
activity: Activity,
72+
nativeAd: NativeAd,
73+
layoutInflater: LayoutInflater,
74+
frameLayout: FrameLayout,
75+
) {
76+
// [START add_ad_view]
77+
activity.runOnUiThread {
78+
// Inflate the native ad view and add it to the view hierarchy.
79+
val nativeAdBinding = NativeAdBinding.inflate(layoutInflater)
80+
val adView = nativeAdBinding.root
81+
82+
// Display and register the native ad asset views here.
83+
displayAndRegisterNativeAd(nativeAd, nativeAdBinding)
84+
85+
// Remove all old ad views and add the new native.
86+
frameLayout.removeAllViews()
87+
// Add the new native ad view to the view hierarchy.
88+
frameLayout.addView(adView)
89+
}
90+
// [END add_ad_view]
91+
}
92+
93+
// [START display_native_ad]
94+
private fun displayAndRegisterNativeAd(nativeAd: NativeAd, nativeAdBinding: NativeAdBinding) {
95+
// [START populate_native_ad_view]
96+
// Populate all native ad view assets with the native ad.
97+
nativeAdBinding.adMedia.mediaContent = nativeAd.mediaContent
98+
nativeAdBinding.adHeadline.text = nativeAd.headline
99+
100+
// Hide all native ad view assets that are not returned within the native ad.
101+
nativeAd.body?.let { body ->
102+
nativeAdBinding.adBody.text = body
103+
nativeAdBinding.adBody.visibility = View.VISIBLE
104+
} ?: run { nativeAdBinding.adBody.visibility = View.INVISIBLE }
105+
106+
nativeAd.callToAction?.let { callToAction ->
107+
nativeAdBinding.adCallToAction.text = callToAction
108+
nativeAdBinding.adCallToAction.visibility = View.VISIBLE
109+
} ?: run { nativeAdBinding.adCallToAction.visibility = View.INVISIBLE }
110+
111+
nativeAd.icon?.let { icon ->
112+
nativeAdBinding.adAppIcon.setImageDrawable(icon.drawable)
113+
nativeAdBinding.adAppIcon.visibility = View.VISIBLE
114+
} ?: run { nativeAdBinding.adAppIcon.visibility = View.GONE }
115+
116+
nativeAd.price?.let { price ->
117+
nativeAdBinding.adPrice.text = price
118+
nativeAdBinding.adPrice.visibility = View.VISIBLE
119+
} ?: run { nativeAdBinding.adPrice.visibility = View.INVISIBLE }
120+
121+
nativeAd.store?.let { store ->
122+
nativeAdBinding.adStore.text = store
123+
nativeAdBinding.adStore.visibility = View.VISIBLE
124+
} ?: run { nativeAdBinding.adStore.visibility = View.INVISIBLE }
125+
126+
nativeAd.starRating?.let { rating ->
127+
nativeAdBinding.adStars.rating = rating.toFloat()
128+
nativeAdBinding.adStars.visibility = View.VISIBLE
129+
} ?: run { nativeAdBinding.adStars.visibility = View.INVISIBLE }
130+
131+
nativeAd.advertiser?.let { advertiser ->
132+
nativeAdBinding.adAdvertiser.text = advertiser
133+
nativeAdBinding.adAdvertiser.visibility = View.VISIBLE
134+
} ?: run { nativeAdBinding.adAdvertiser.visibility = View.INVISIBLE }
135+
// [END populate_native_ad_view]
136+
137+
// [START register_native_ad_assets]
138+
// Register all native ad assets with the native ad view.
139+
val nativeAdView = nativeAdBinding.root
140+
nativeAdView.advertiserView = nativeAdBinding.adAdvertiser
141+
nativeAdView.bodyView = nativeAdBinding.adBody
142+
nativeAdView.callToActionView = nativeAdBinding.adCallToAction
143+
nativeAdView.headlineView = nativeAdBinding.adHeadline
144+
nativeAdView.iconView = nativeAdBinding.adAppIcon
145+
nativeAdView.priceView = nativeAdBinding.adPrice
146+
nativeAdView.starRatingView = nativeAdBinding.adStars
147+
nativeAdView.storeView = nativeAdBinding.adStore
148+
nativeAd.mediaContent?.let { nativeAdBinding.adMedia.setMediaContent(it) }
149+
nativeAdView.mediaView = nativeAdBinding.adMedia
150+
// [END register_native_ad_assets]
151+
152+
// [START set_native_ad]
153+
// This method tells the Google Mobile Ads SDK that you have finished populating your
154+
// native ad view with this native ad.
155+
nativeAdView.setNativeAd(nativeAd)
156+
// [END set_native_ad]
157+
}
158+
159+
// [END display_native_ad]
160+
100161
private fun destroyAd(nativeAd: NativeAd) {
101162
// [START destroy_ad]
102163
nativeAd.destroy()
103164
// [END destroy_ad]
104165
}
105166

106-
private companion object {
107-
// Test ad unit IDs.
108-
// For more information,
109-
// see https://developers.google.com/admob/android/test-ads.
110-
// and https://developers.google.com/ad-manager/mobile-ads-sdk/android/test-ads.
111-
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"
167+
private fun setEventCallback(adLoader: AdLoader.Builder) {
168+
// [START set_event_callback]
169+
adLoader
170+
.withAdListener(
171+
object : AdListener() {
172+
override fun onAdClosed() {
173+
// Called when the ad is closed.
174+
}
175+
176+
override fun onAdFailedToLoad(adError: LoadAdError) {
177+
// Called when an ad fails to load.
178+
}
179+
180+
override fun onAdOpened() {
181+
// Called when an ad opens full screen.
182+
}
183+
184+
override fun onAdLoaded() {
185+
// Called when an ad has loaded.
186+
}
187+
188+
override fun onAdClicked() {
189+
// Called when a click is recorded for an ad.
190+
}
191+
192+
override fun onAdImpression() {
193+
// Called when an impression is recorded for an ad.
194+
}
195+
196+
override fun onAdSwipeGestureClicked() {
197+
// Called when a swipe gesture is recorded for an ad.
198+
}
199+
}
200+
)
201+
.build()
202+
// [END set_event_callback]
203+
}
204+
205+
private fun setImageScaleType(mediaView: MediaView) {
206+
// [START set_image_scale_type]
207+
mediaView.setImageScaleType(ImageView.ScaleType.CENTER_CROP)
208+
// [END set_image_scale_type]
115209
}
116210
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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 android.content.Context
18+
import android.widget.ImageView
19+
import androidx.compose.foundation.layout.Box
20+
import androidx.compose.foundation.layout.Column
21+
import androidx.compose.foundation.layout.fillMaxHeight
22+
import androidx.compose.foundation.layout.fillMaxWidth
23+
import androidx.compose.foundation.layout.height
24+
import androidx.compose.foundation.layout.padding
25+
import androidx.compose.foundation.layout.wrapContentHeight
26+
import androidx.compose.material3.MaterialTheme
27+
import androidx.compose.material3.Text
28+
import androidx.compose.runtime.Composable
29+
import androidx.compose.runtime.DisposableEffect
30+
import androidx.compose.runtime.getValue
31+
import androidx.compose.runtime.mutableStateOf
32+
import androidx.compose.runtime.remember
33+
import androidx.compose.runtime.setValue
34+
import androidx.compose.ui.Alignment
35+
import androidx.compose.ui.Modifier
36+
import androidx.compose.ui.platform.LocalContext
37+
import androidx.compose.ui.unit.dp
38+
import com.example.jetpackcomposedemo.R
39+
import com.google.android.gms.ads.AdListener
40+
import com.google.android.gms.ads.AdLoader
41+
import com.google.android.gms.ads.AdRequest
42+
import com.google.android.gms.ads.LoadAdError
43+
import com.google.android.gms.ads.nativead.NativeAd
44+
import com.google.android.gms.compose_util.NativeAdAttribution
45+
import com.google.android.gms.compose_util.NativeAdHeadlineView
46+
import com.google.android.gms.compose_util.NativeAdMediaView
47+
import com.google.android.gms.compose_util.NativeAdView
48+
49+
/** Kotlin code snippets for the developer guide. */
50+
internal class NativeAdSnippets {
51+
52+
// [START define_native_ad_view]
53+
@Composable
54+
/** Display a native ad with a user defined template. */
55+
fun DisplayNativeAdView(nativeAd: NativeAd) {
56+
val context = LocalContext.current
57+
Box(modifier = Modifier.padding(8.dp).wrapContentHeight(Alignment.Top)) {
58+
// Call the NativeAdView composable to display the native ad.
59+
NativeAdView {
60+
// Inside the NativeAdView composable, display the native ad assets.
61+
Column(Modifier.align(Alignment.TopStart).wrapContentHeight(Alignment.Top)) {
62+
// Display the ad attribution. This is required.
63+
NativeAdAttribution(text = context.getString(R.string.attribution))
64+
// Display the headline asset. This is required.
65+
nativeAd.headline?.let {
66+
NativeAdHeadlineView { Text(text = it, style = MaterialTheme.typography.headlineLarge) }
67+
}
68+
// Display the media asset. This is required.
69+
NativeAdMediaView(Modifier.fillMaxWidth().height(500.dp).fillMaxHeight())
70+
}
71+
}
72+
}
73+
}
74+
75+
// [END define_native_ad_view]
76+
77+
// [START display_native_ad_screen]
78+
@Composable
79+
fun DisplayNativeAdScreen(adunitId: String) {
80+
var nativeAd by remember { mutableStateOf<NativeAd?>(null) }
81+
val context = LocalContext.current
82+
var isDisposed by remember { mutableStateOf(false) }
83+
84+
DisposableEffect(Unit) {
85+
// Load the native ad when we launch this screen
86+
loadNativeAd(
87+
context = context,
88+
adunitId,
89+
onAdLoaded = { ad ->
90+
// Handle the native ad being loaded.
91+
if (!isDisposed) {
92+
nativeAd = ad
93+
} else {
94+
// Destroy the native ad if loaded after the screen is disposed.
95+
ad.destroy()
96+
}
97+
},
98+
)
99+
// [START destroy_native_ad]
100+
// Destroy the native ad to prevent memory leaks when we dispose of this screen.
101+
onDispose {
102+
isDisposed = true
103+
nativeAd?.destroy()
104+
nativeAd = null
105+
}
106+
// [END destroy_native_ad]
107+
}
108+
109+
// Display the native ad view with a user defined template here.
110+
nativeAd?.let { adValue -> DisplayNativeAdView(adValue) }
111+
}
112+
113+
// [END display_native_ad_screen]
114+
115+
// [START load_native_ad_compose]
116+
fun loadNativeAd(context: Context, adUnitId: String, onAdLoaded: (NativeAd) -> Unit) {
117+
val adLoader =
118+
AdLoader.Builder(context, adUnitId)
119+
.forNativeAd { nativeAd -> onAdLoaded(nativeAd) }
120+
.withAdListener(
121+
object : AdListener() {
122+
override fun onAdFailedToLoad(error: LoadAdError) {
123+
// Native ad failed to load.
124+
}
125+
126+
override fun onAdLoaded() {
127+
// Native ad was loaded.
128+
}
129+
130+
override fun onAdImpression() {
131+
// Native ad recorded an impression.
132+
}
133+
134+
override fun onAdClicked() {
135+
// Native ad was clicked.
136+
}
137+
}
138+
)
139+
.build()
140+
adLoader.loadAd(AdRequest.Builder().build())
141+
}
142+
143+
// [END load_native_ad_compose]
144+
145+
@Composable
146+
fun SetImageScaleType() {
147+
// [START set_image_scale_type_compose]
148+
NativeAdMediaView(Modifier.fillMaxWidth(), scaleType = ImageView.ScaleType.CENTER_CROP)
149+
// [END set_image_scale_type_compose]
150+
}
151+
}

0 commit comments

Comments
 (0)