Skip to main content

Jetpack Compose

This guide explains how to integrate the GFP Android SDK into a UI built with Jetpack Compose.

warning

Versions below androidx.compose:compose-bom:2024.09.03 may have a bug in Compose that could cause events like impressions or clicks to not fire correctly. To ensure proper ad integration, please use version 2024.09.03 or higher.

Getting Started

To render GFP SDK ads in a Jetpack Compose-based UI, we primarily use AndroidView. To prevent unnecessary or duplicate ad loading due to recomposition, manage the AdParam object required for ad loading using remember, or pass it as a parameter to the composable rendering the ad. When loading ads, use LaunchedEffect or DisposableEffect with AdParam as the key to load ads via GfpAdLoader, ensuring no duplicate requests with the same AdParam. Once the ad is loaded, render it using either an AdView or AdManager, depending on the ad type. If you stop displaying the ad or move off-screen, release resources via AndroidView.onRelease or DisposableEffect.


For banners, there are two supported loading methods: one using GfpAdLoader and one without. When using GfpAdLoader, manage the loaded GfpBannerAdView with State to display the ad.

With GfpAdLoader

@Composable
fun BannerAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
var adLoader by remember { mutableStateOf<GfpAdLoader?>(null) }
var bannerAdView by remember { mutableStateOf<GfpBannerAdView?>(null) }

LaunchedEffect(adParam) {
adLoader = GfpAdLoader.Builder(context, adParam)
.withAdListener(/* . . . */)
.withBannerAd {
bannerAdView = it
}
.build()
.also { loadAd() }
}

bannerAdView?.let { adView ->
AndroidView(
modifier = modifier,
factory = { adView },
onRelease = { view ->
view.destroy()
adLoader?.cancel()
}
)
}
}

Without GfpAdLoader

@Composable
fun BannerAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
AndroidView(
modifier = modifier,
factory = { context ->
GfpBannerAdView(context, adParam).apply {
setAdListener(/* . . . */)
loadAd()
}
},
onRelease = { view ->
view.destroy()
}
)
}

Native Normal

The Native Normal ad in the GFP SDK currently only supports Android View rendering. In Compose environments, it is rendered using AndroidViewBinding. To integrate, you will need an xml layout file for rendering the ad and include compose.ui:ui-viewbinding as a dependency in your gradle setup.

buildFeatures {
compose = true
viewBinding = true
}
dependencies {
// . . .
implementation("androidx.compose.ui:ui-viewbinding:<compose-version>")
}
@Composable
fun NativeAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
var adLoader by remember { mutableStateOf<GfpAdLoader?>(null) }
var nativeAd by remember { mutableStateOf<GfpNativeAd?>(null) }

LaunchedEffect(adParam) {
adLoader = GfpAdLoader.Builder(context, adParam)
.withAdListener(/* . . . */)
.withNativeAd {
nativeAd = it
}
.build()
.also { loadAd() }
}

nativeAd?.let { ad ->
AndroidViewBinding(
factory = LayoutNativeAdBinding::inflate,
modifier = modifier,
onRelease = { adLoader?.cancel() }
) {
with(nativeAdView) {
assetsContainer = assetsContainerLayout
adChoicesView = adChoices
mediaView = media
titleView = title.apply { text = ad.title }
bodyView = body.apply { text = ad.body }
callToActionView = callToAction.apply { text = ad.callToAction }
advertiserView = advertiser.apply { text = ad.advertiserName }
iconView = icon.apply {
ad.icon?.let { setImageDrawable(it.drawable) } ?: run { visibility = GONE }
}
socialContextView = socialContext.apply {
ad.socialContext?.let { text = it } ?: run { visibility = GONE }
}
noticeView = notice.apply {
ad.notice?.let { text = it } ?: run { visibility = GONE }
}
setNativeAd(ad)
}
}
}
}
info

The layout_native_ad.xml code is omitted.


Native Simple

Once loading is complete via GfpAdLoader, manage the received GfpNativeSimpleAd object using State, and set it in the GfpNativeSimpleAdView using AndroidView's factory or update.

@Composable
fun NativeSimpleAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
var adLoader by remember { mutableStateOf<GfpAdLoader?>(null) }
var nativeSimpleAd by remember { mutableStateOf<GfpNativeSimpleAd?>(null) }

LaunchedEffect(adParam) {
adLoader = GfpAdLoader.Builder(context, adParam)
.withAdListener(/* . . . */)
.withNativeSimpleAd {
nativeSimpleAd = it
}
.build()
.also { loadAd() }
}

nativeSimpleAd?.let { ad ->
AndroidView(
modifier = modifier,
factory = { context -> GfpNativeSimpleAdView(context) },
update = { view -> view.setNativeSimpleAd(ad) },
onRelease = { adLoader?.cancel() }
)
}
}

Rewarded & Interstitial

For rewarded and interstitial ads, load the ad through AdManager and manage the ad load completion status using State by listening to AdEventListener. Once loading is complete, display an ad button. The context passed to the showAd function needs to be cast to an Activity. Since AndroidView is not used for resource release, call destroy() in DisposableEffect's onDispose.

Rewarded

@Composable
fun RewardedAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
var adManager by remember { mutableStateOf<GfpRewardedAdManager?>(null) }
var isAdLoaded by remember { mutableStateOf(false) }

DisposableEffect(adParam) {
adManager = GfpRewardedAdManager(context, adParam).apply {
setAdListener(object : RewardedAdListener() {
override fun onAdLoaded(ad: GfpRewardedAd) {
isAdLoaded = true
}
})
loadAd()
}

onDispose {
adManager?.destroy()
}
}

if (isAdLoaded) {
Button(
onClick = { adManager?.showAd(context as Activity) },
modifier = modifier
) {
Text(text = "Show Rewarded AD")
}
}
}

Interstitial

@Composable
fun InterstitialAdView(
adParam: AdParam,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
var adManager by remember { mutableStateOf<GfpInterstitialAdManager?>(null) }
var isAdLoaded by remember { mutableStateOf(false) }

DisposableEffect(adParam) {
adManager = GfpInterstitialAdManager(context, adParam).apply {
setAdListener(object : InterstitialAdListener() {
override fun onAdLoaded(ad: GfpInterstitialAd) {
isAdLoaded = true
}
})
loadAd()
}

onDispose {
adManager?.destroy()
}
}

if (isAdLoaded) {
Button(
onClick = { adManager?.showAd(contextas Activity) },
modifier = modifier
) {
Text(text = "Show Interstitial AD")
}
}
}

info

You can check the complete code sample in the sample app repository.