diff --git a/java/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippet.xml b/java/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippet.xml
new file mode 100644
index 000000000..b3125cb75
--- /dev/null
+++ b/java/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippet.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippets.xml b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippets.xml
new file mode 100644
index 000000000..b3125cb75
--- /dev/null
+++ b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdLayoutSnippets.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdSnippets.kt b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdSnippets.kt
index 0f3046d42..cd263eb86 100644
--- a/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdSnippets.kt
+++ b/kotlin/advanced/APIDemo/app/src/main/java/com/google/android/gms/snippets/NativeAdSnippets.kt
@@ -14,7 +14,11 @@
package com.google.android.gms.snippets
+import android.app.Activity
import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
import com.google.android.gms.ads.AdRequest
@@ -22,9 +26,6 @@ import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.admanager.AdManagerAdRequest
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdOptions
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
/** Kotlin code snippets for the developer guide. */
internal class NativeAdSnippets {
@@ -97,6 +98,106 @@ internal class NativeAdSnippets {
// [END handle_ad_loaded]
}
+ private fun handleAdLoadedWithDisplay(
+ adLoaderBuilder: AdLoader.Builder,
+ activity: Activity,
+ layoutInflater: LayoutInflater,
+ layoutPlaceholder: FrameLayout,
+ ) {
+ // [START handle_ad_loaded_with_display]
+ adLoaderBuilder
+ .forNativeAd { nativeAd ->
+ // This callback is invoked when a native ad is successfully loaded.
+ activity.runOnUiThread {
+ val nativeAdBinding = NativeAdBinding.inflate(layoutInflater)
+ val adView = nativeAdBinding.root
+
+ // Populate and register the native ad asset views.
+ displayNativeAdView(nativeAd, nativeAdBinding)
+
+ // Remove all old ad views and add the new native ad
+ // view to the view hierarchy.
+ layoutPlaceholder.removeAllViews()
+ layoutPlaceholder.addView(adView)
+ }
+ }
+ .build()
+ // [END handle_ad_loaded_with_display]
+ }
+
+ private fun displayNativeAdView(nativeAd: NativeAd, nativeAdBinding: NativeAdBinding) {
+ // [START display_native_ad]
+ val nativeAdView = nativeAdBinding.root
+
+ // Set the media view.
+ nativeAdView.mediaView = nativeAdBinding.adMedia
+
+ // Set other ad assets.
+ nativeAdView.headlineView = nativeAdBinding.adHeadline
+ nativeAdView.bodyView = nativeAdBinding.adBody
+ nativeAdView.callToActionView = nativeAdBinding.adCallToAction
+ nativeAdView.iconView = nativeAdBinding.adAppIcon
+ nativeAdView.priceView = nativeAdBinding.adPrice
+ nativeAdView.starRatingView = nativeAdBinding.adStars
+ nativeAdView.storeView = nativeAdBinding.adStore
+ nativeAdView.advertiserView = nativeAdBinding.adAdvertiser
+
+ nativeAdBinding.adHeadline.text = nativeAd.headline
+ nativeAd.mediaContent?.let { nativeAdBinding.adMedia.setMediaContent(it) }
+
+ if (nativeAd.body == null) {
+ nativeAdBinding.adBody.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adBody.text = nativeAd.body
+ nativeAdBinding.adBody.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.callToAction == null) {
+ nativeAdBinding.adCallToAction.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adCallToAction.text = nativeAd.callToAction
+ nativeAdBinding.adCallToAction.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.icon == null) {
+ nativeAdBinding.adAppIcon.visibility = View.GONE
+ } else {
+ nativeAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
+ nativeAdBinding.adAppIcon.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.price == null) {
+ nativeAdBinding.adPrice.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adPrice.text = nativeAd.price
+ nativeAdBinding.adPrice.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.store == null) {
+ nativeAdBinding.adStore.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adStore.text = nativeAd.store
+ nativeAdBinding.adStore.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.starRating == null) {
+ nativeAdBinding.adStars.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adStars.rating = nativeAd.starRating!!.toFloat()
+ nativeAdBinding.adStars.visibility = View.VISIBLE
+ }
+
+ if (nativeAd.advertiser == null) {
+ nativeAdBinding.adAdvertiser.visibility = View.INVISIBLE
+ } else {
+ nativeAdBinding.adAdvertiser.text = nativeAd.advertiser
+ nativeAdBinding.adAdvertiser.visibility = View.VISIBLE
+ }
+
+ nativeAdView.setNativeAd(nativeAd)
+ // [END display_native_ad]
+ }
+
private fun destroyAd(nativeAd: NativeAd) {
// [START destroy_ad]
nativeAd.destroy()
diff --git a/kotlin/advanced/JetpackComposeDemo/app/src/main/java/com/google/android/gms/example/jetpackcomposedemo/snippets/NativeAdSnippets.kt b/kotlin/advanced/JetpackComposeDemo/app/src/main/java/com/google/android/gms/example/jetpackcomposedemo/snippets/NativeAdSnippets.kt
new file mode 100644
index 000000000..8d672b86e
--- /dev/null
+++ b/kotlin/advanced/JetpackComposeDemo/app/src/main/java/com/google/android/gms/example/jetpackcomposedemo/snippets/NativeAdSnippets.kt
@@ -0,0 +1,138 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.android.gms.example.jetpackcomposedemo.snippets
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.unit.dp
+import com.example.jetpackcomposedemo.R
+import com.google.android.gms.ads.nativead.NativeAd
+import com.google.android.gms.compose_util.NativeAdAttribution
+import com.google.android.gms.compose_util.NativeAdHeadlineView
+import com.google.android.gms.compose_util.NativeAdMediaView
+import com.google.android.gms.compose_util.NativeAdView
+
+/** Kotlin code snippets for the developer guide. */
+internal class NativeAdSnippets {
+
+ // [START define_native_ad_view]
+ @Composable
+ /** Display a native ad with a user defined template. */
+ fun DisplayNativeAdView(nativeAd: NativeAd) {
+ val context = LocalContext.current
+ Box(modifier = Modifier.padding(8.dp).wrapContentHeight(Alignment.Top)) {
+ // Call the NativeAdView composable to display the native ad.
+ NativeAdView {
+ // Inside the NativeAdView composable, display the native ad assets.
+ Column(Modifier.align(Alignment.TopStart).wrapContentHeight(Alignment.Top)) {
+ // Display the ad attribution. This is required.
+ NativeAdAttribution(text = context.getString(R.string.attribution))
+ // Display the headline asset. This is required.
+ nativeAd.headline?.let {
+ NativeAdHeadlineView { Text(text = it, style = MaterialTheme.typography.headlineLarge) }
+ }
+ // Display the media asset. This is required.
+ NativeAdMediaView(Modifier.fillMaxWidth().height(500.dp).fillMaxHeight())
+ }
+ }
+ }
+ }
+
+ // [END define_native_ad_view]
+
+ // [START load_native_ad_for_display]
+ @Composable
+ fun loadAndDisplayNativeAd() {
+ var nativeAd by remember { mutableStateOf(null) }
+ val context = LocalContext.current
+ var isDisposed by remember { mutableStateOf(false) }
+
+ DisposableEffect(Unit) {
+ // Load the native ad when we launch this screen
+ loadNativeAd(
+ context = context,
+ onAdLoaded = { ad ->
+ // Handle the native ad being loaded.
+ if (!isDisposed) {
+ nativeAd = ad
+ } else {
+ // Destroy the native ad if loaded after the screen is disposed.
+ ad.destroy()
+ }
+ },
+ )
+ // Destroy the native ad to prevent memory leaks when we dispose of this screen.
+ onDispose {
+ isDisposed = true
+ nativeAd?.destroy()
+ nativeAd = null
+ }
+ }
+
+ // Display the native ad view with a user defined template.
+ nativeAd?.let { adValue -> displayNativeAdView(adValue) }
+ }
+
+ fun loadNativeAd(context: Context, onAdLoaded: (NativeAd) -> Unit) {
+ val adLoader =
+ AdLoader.Builder(context, NATIVE_AD_UNIT_ID)
+ .forNativeAd { nativeAd -> onAdLoaded(nativeAd) }
+ .withAdListener(
+ object : AdListener() {
+ override fun onAdFailedToLoad(error: LoadAdError) {
+ Log.e(TAG, "Native ad failed to load: ${error.message}")
+ }
+
+ override fun onAdLoaded() {
+ Log.d(TAG, "Native ad was loaded.")
+ }
+
+ override fun onAdImpression() {
+ Log.d(TAG, "Native ad recorded an impression.")
+ }
+
+ override fun onAdClicked() {
+ Log.d(TAG, "Native ad was clicked.")
+ }
+ }
+ )
+ .build()
+ adLoader.loadAd(AdRequest.Builder().build())
+ }
+
+ // [END load_native_ad_for_display]
+
+ private companion object {
+ // Test ad unit IDs.
+ // For more information,
+ // see https://developers.google.com/admob/android/test-ads.
+ // and https://developers.google.com/ad-manager/mobile-ads-sdk/android/test-ads.
+ const val AD_UNIT_ID = "ca-app-pub-3940256099942544/2247696110"
+ const val VIDEO_AD_UNIT_ID = "ca-app-pub-3940256099942544/1044960115"
+ const val ADMANAGER_AD_UNIT_ID = "/21775744923/example/native"
+ const val ADMANAGER_VIDEO_AD_UNIT_ID = "/21775744923/example/native-video"
+ }
+}