From 77a98cedb3c6df3a4bfe1813e8254bab38911ae9 Mon Sep 17 00:00:00 2001 From: Robert Jamison <65142411+robertjamison@users.noreply.github.com> Date: Sat, 11 Jul 2026 19:19:46 -0400 Subject: [PATCH 1/7] Updated JVM compiler to JVM_26 Updated Lint version (CVE-2025-14813) Updated toolchain version to 26 --- basic-ads/build.gradle.kts | 2 +- gradle.properties | 6 +++++- gradle/gradle-daemon-jvm.properties | 22 +++++++++++----------- gradle/libs.versions.toml | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/basic-ads/build.gradle.kts b/basic-ads/build.gradle.kts index 8439416..f179996 100644 --- a/basic-ads/build.gradle.kts +++ b/basic-ads/build.gradle.kts @@ -78,7 +78,7 @@ kotlin { withJava() compilerOptions { - jvmTarget.set(JvmTarget.JVM_17) + jvmTarget.set(JvmTarget.JVM_26) } } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 4583525..a113b6b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,4 +29,8 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true #Dokka org.gradle.caching=false org.gradle.configuration-cache=false -org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled \ No newline at end of file +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled + +#Security +# TODO: Update as updates become available +android.experimental.lint.version = 32.2.1 \ No newline at end of file diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 93ee2e5..5e9bc38 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1,12 +1,12 @@ #This file is generated by updateDaemonJvm -toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/402983f310a88ac68b3e883c7c91c760/redirect -toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/e50b80b5a11d194a898bc3e6211b7c4b/redirect -toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/402983f310a88ac68b3e883c7c91c760/redirect -toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/e50b80b5a11d194a898bc3e6211b7c4b/redirect -toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/f257be9f04bfdf169051808541767806/redirect -toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/1dcbacacca32618bd21ec5465779ade1/redirect -toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/402983f310a88ac68b3e883c7c91c760/redirect -toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/e50b80b5a11d194a898bc3e6211b7c4b/redirect -toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/476d3c08f4989328dee56d22e202d98d/redirect -toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/5a88b04b5e582b332d2e6bc12b45f1b9/redirect -toolchainVersion=21 +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d49876ee3db33100d35f5be9838c3b/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/6af2df4e19bc2c444a6c6acc6a01a6ae/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d49876ee3db33100d35f5be9838c3b/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/6af2df4e19bc2c444a6c6acc6a01a6ae/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/452dfc1cc9013972dc33eb709577c24f/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/8e89327856a245266587332a292623ce/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d49876ee3db33100d35f5be9838c3b/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/6af2df4e19bc2c444a6c6acc6a01a6ae/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/06247aa9c110fdcc3afc4c1b4da3a10a/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/496ddee07c4f214fc64845d4c1f671df/redirect +toolchainVersion=26 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 85a1651..905dbd4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # BUILD INFO -ads = "1.2.0" +ads = "1.2.1" build-sdk-compile = "37" build-sdk-min = "24" build-sdk-target = "37" From ed1fe579bad9f67608deabbb886df5c205c50dbf Mon Sep 17 00:00:00 2001 From: Robert Jamison <65142411+robertjamison@users.noreply.github.com> Date: Sat, 22 Aug 2026 20:08:27 -0400 Subject: [PATCH 2/7] Updated Kotlin to 2.4.10 and AdMob to 13.8.0, added v1.2.1 to VERSIONS.md --- VERSIONS.md | 3 ++- gradle/libs.versions.toml | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/VERSIONS.md b/VERSIONS.md index a4c7a3d..97799fb 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -35,4 +35,5 @@ Here's a list of the Basic-Ads dependency versions for each release after 0.2.0: | 1.1.1 | 2.3.0 | 1.10.0 | 1.9.1 | 24.9.0 / 12.14.0 | 4.0.0 / 3.1.0 | | 1.2.0-beta01 | 2.3.21 | 1.10.3 | 1.9.1 | 25.2.0 / 13.3.0 | 4.0.0 / 3.1.0 | | 1.2.0-beta02 | 2.4.0 | 1.11.1 | 1.10.0 | 25.4.0 / 13.3.0 | 4.0.0 / 3.1.0 | -| 1.2.0 | 2.4.0 | 1.11.1 | 1.10.0 | 25.4.0 / 13.3.0 | 4.0.0 / 3.1.0 | \ No newline at end of file +| 1.2.0 | 2.4.0 | 1.11.1 | 1.10.0 | 25.4.0 / 13.3.0 | 4.0.0 / 3.1.0 | +| 1.2.1 | 2.4.10 | 1.11.1 | 1.10.0 | 25.4.0 / 13.8.0 | 4.0.0 / 3.1.0 | \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 905dbd4..e1048e0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,10 +5,10 @@ build-sdk-compile = "37" build-sdk-min = "24" build-sdk-target = "37" build-ios-target-deployment = "13.0" -kotlin = "2.4.0" +kotlin = "2.4.10" agp = "9.2.1" # COCOAPODS DEPENDENCIES -cocoapods-admob = "13.3.0" +cocoapods-admob = "13.8.0" cocoapods-ump = "3.1.0" # DEPENDENCIES bcv = "0.18.1" @@ -17,8 +17,8 @@ compose = "1.11.1" google-play-services-ads = "25.4.0" android-core = "1.19.0" annotations = "1.10.0" -kover = "0.9.8" -logging = "0.2.6" +kover = "0.9.9" +logging = "0.3.1" android-ump = "4.0.0" maven-publish = "0.37.0" From adfde9b6ad721c0eda522150d51fb7dacf58e9aa Mon Sep 17 00:00:00 2001 From: Robert Jamison <65142411+robertjamison@users.noreply.github.com> Date: Sat, 22 Aug 2026 20:30:37 -0400 Subject: [PATCH 3/7] Add unit tests for `AdException`, `ConsentException`, `AdUnitId`, and `AdState` classes, enable `commonTest` dependencies in project configuration, and update Gradle to 9.7.1. --- basic-ads/build.gradle.kts | 4 ++++ .../app/lexilabs/basic/ads/AdExceptionTest.kt | 19 +++++++++++++++ .../app/lexilabs/basic/ads/AdStateTest.kt | 22 ++++++++++++++++++ .../app/lexilabs/basic/ads/AdUnitIdTest.kt | 23 +++++++++++++++++++ .../basic/ads/ConsentExceptionTest.kt | 14 +++++++++++ gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdExceptionTest.kt create mode 100644 basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdStateTest.kt create mode 100644 basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdUnitIdTest.kt create mode 100644 basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/ConsentExceptionTest.kt diff --git a/basic-ads/build.gradle.kts b/basic-ads/build.gradle.kts index f179996..9dd3f04 100644 --- a/basic-ads/build.gradle.kts +++ b/basic-ads/build.gradle.kts @@ -49,6 +49,9 @@ kotlin { implementation(libs.annotations) implementation(libs.lexilabs.basic.logging) } + commonTest.dependencies { + implementation(kotlin("test")) + } androidMain.dependencies { compileOnly(libs.google.play.services.ads) compileOnly(libs.android.core) @@ -76,6 +79,7 @@ kotlin { compileSdk = libs.versions.build.sdk.compile.get().toInt() minSdk = libs.versions.build.sdk.min.get().toInt() withJava() + withHostTest {} compilerOptions { jvmTarget.set(JvmTarget.JVM_26) diff --git a/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdExceptionTest.kt b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdExceptionTest.kt new file mode 100644 index 0000000..25d5a19 --- /dev/null +++ b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdExceptionTest.kt @@ -0,0 +1,19 @@ +package app.lexilabs.basic.ads + +import kotlin.test.Test +import kotlin.test.assertEquals + +class AdExceptionTest { + + @Test + fun testAdExceptionMessage() { + val exception = AdException("Network error") + assertEquals("AdMob failed to obtain, load, or show an ad: Network error", exception.message) + } + + @Test + fun testAdExceptionNullMessage() { + val exception = AdException(null) + assertEquals("AdMob failed to obtain, load, or show an ad: null", exception.message) + } +} diff --git a/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdStateTest.kt b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdStateTest.kt new file mode 100644 index 0000000..aac285f --- /dev/null +++ b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdStateTest.kt @@ -0,0 +1,22 @@ +package app.lexilabs.basic.ads + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +class AdStateTest { + + @Test + fun testAdStateValues() { + val states = AdState.entries.toTypedArray() + assertNotNull(states) + assertEquals(7, states.size) + assertEquals(AdState.NONE, AdState.valueOf("NONE")) + assertEquals(AdState.LOADING, AdState.valueOf("LOADING")) + assertEquals(AdState.READY, AdState.valueOf("READY")) + assertEquals(AdState.SHOWING, AdState.valueOf("SHOWING")) + assertEquals(AdState.SHOWN, AdState.valueOf("SHOWN")) + assertEquals(AdState.DISMISSED, AdState.valueOf("DISMISSED")) + assertEquals(AdState.FAILING, AdState.valueOf("FAILING")) + } +} diff --git a/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdUnitIdTest.kt b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdUnitIdTest.kt new file mode 100644 index 0000000..71e7e30 --- /dev/null +++ b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/AdUnitIdTest.kt @@ -0,0 +1,23 @@ +package app.lexilabs.basic.ads + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +class AdUnitIdTest { + + @Test + fun testDefaults() { + assertNotNull(AdUnitId.BANNER_DEFAULT) + assertNotNull(AdUnitId.INTERSTITIAL_DEFAULT) + assertNotNull(AdUnitId.REWARDED_DEFAULT) + assertNotNull(AdUnitId.REWARDED_INTERSTITIAL_DEFAULT) + assertNotNull(AdUnitId.NATIVE_DEFAULT) + } + + @Test + fun testAutoSelect() { + val selected = AdUnitId.autoSelect(androidAdUnitId = "test_id", iosAdUnitId = "test_id") + assertEquals("test_id", selected) + } +} diff --git a/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/ConsentExceptionTest.kt b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/ConsentExceptionTest.kt new file mode 100644 index 0000000..0d2938c --- /dev/null +++ b/basic-ads/src/commonTest/kotlin/app/lexilabs/basic/ads/ConsentExceptionTest.kt @@ -0,0 +1,14 @@ +package app.lexilabs.basic.ads + +import kotlin.test.Test +import kotlin.test.assertEquals + +class ConsentExceptionTest { + + @Test + @OptIn(DependsOnGoogleUserMessagingPlatform::class) + fun testConsentExceptionMessage() { + val exception = ConsentException("Configuration error") + assertEquals("UserMessagingPlatform failed to obtain, load, or show ConsentInformation: Configuration error", exception.message) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e1048e0..24b92e7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ build-sdk-min = "24" build-sdk-target = "37" build-ios-target-deployment = "13.0" kotlin = "2.4.10" -agp = "9.2.1" +agp = "9.5.0-alpha02" # COCOAPODS DEPENDENCIES cocoapods-admob = "13.8.0" cocoapods-ump = "3.1.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a9db115..ad7845b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From 3c3d953af7e437e4c5f75b662da6d0b1a93e24ea Mon Sep 17 00:00:00 2001 From: Anggrayudi H <12292380+anggrayudi@users.noreply.github.com> Date: Sun, 23 Aug 2026 07:34:26 +0700 Subject: [PATCH 4/7] fix(ios): stop firing onDismissed twice on full screen ads (#153) FullScreenContentDelegate called onDismissed() from both adWillDismissFullScreenContent and adDidDismissFullScreenContent. iOS splits dismissal into a will/did pair, whereas Android reports it once via onAdDismissedFullScreenContent, so the shared callback fired twice on iOS only. Android's single callback corresponds to adDidDismissFullScreenContent, so the call is dropped from the will variant and the log line kept. The duplicate was not only a double callback: the handlers set AdState.DISMISSED from onDismissed, and rememberRewardedAd and rememberInterstitialAd reload whenever the state is DISMISSED or NONE, so every dismissal on iOS also triggered a second load(). One fix covers InterstitialAdHandler, RewardedAdHandler and RewardedInterstitialAdHandler, which all share this delegate. Fixes #144 Co-authored-by: anggrayudi.hardiannico Co-authored-by: Claude Opus 5 (1M context) --- .../app/lexilabs/basic/ads/FullScreenContentDelegate.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/basic-ads/src/iosMain/kotlin/app/lexilabs/basic/ads/FullScreenContentDelegate.kt b/basic-ads/src/iosMain/kotlin/app/lexilabs/basic/ads/FullScreenContentDelegate.kt index b5d23c0..9840be7 100644 --- a/basic-ads/src/iosMain/kotlin/app/lexilabs/basic/ads/FullScreenContentDelegate.kt +++ b/basic-ads/src/iosMain/kotlin/app/lexilabs/basic/ads/FullScreenContentDelegate.kt @@ -48,8 +48,10 @@ public class FullScreenContentDelegate( override fun adWillDismissFullScreenContent(ad: GADFullScreenPresentingAdProtocol) { superclass + // Deliberately does not call onDismissed(). iOS splits dismissal into a will/did pair + // while Android reports it once, via onAdDismissedFullScreenContent, which corresponds to + // adDidDismissFullScreenContent above. Calling it here too fired the callback twice. Log.d(tag, "ad being dismissed soon") - onDismissed() } override fun adWillPresentFullScreenContent(ad: GADFullScreenPresentingAdProtocol) { From f24d7328a8bacd4a263a976fde4f0574afba69d7 Mon Sep 17 00:00:00 2001 From: Anggrayudi H <12292380+anggrayudi@users.noreply.github.com> Date: Sun, 23 Aug 2026 07:39:59 +0700 Subject: [PATCH 5/7] fix(android): keep the adaptive ad size the SDK produced (#155) AdSize round-tripped through width and height only. toCommon read those two values off the size returned by an adaptive factory, and toAndroid rebuilt a plain com.google.android.gms.ads.AdSize from them, so an adaptive request was silently downgraded to a fixed size one. Inspecting play-services-ads-api 25.4.0 shows why the dimensions are not enough: AdSize stores seven fields beyond width and height, including the size descriptor string sent with the request, and its only public constructor takes the two dimensions. The adaptive factories are static methods that populate the rest, so no reconstruction from width and height can reproduce their result. The instance produced by the SDK is now retained and handed back unchanged. Sizes built from explicit dimensions are unaffected, which is why AdSize(FULL_WIDTH, AUTO_HEIGHT) worked already: those sentinels are handled by the public constructor. Co-authored-by: anggrayudi.hardiannico Co-authored-by: Claude Opus 5 (1M context) --- .../kotlin/app/lexilabs/basic/ads/AdSize.kt | 26 +++++++++++++++++++ .../app/lexilabs/basic/ads/Converters.kt | 6 ++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/AdSize.kt b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/AdSize.kt index f3a40d0..96103bc 100644 --- a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/AdSize.kt +++ b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/AdSize.kt @@ -10,10 +10,36 @@ import android.content.Context */ public actual class AdSize public actual constructor(public actual val width: Int, public actual val height: Int) { + /** + * The size handed over by the Google Mobile Ads SDK, when this instance came from one of its + * factories rather than from a pair of dimensions. + */ + private var nativeAdSize: com.google.android.gms.ads.AdSize? = null + + /** + * Wraps a size produced by the Google Mobile Ads SDK. + * + * The adaptive factories return sizes carrying request metadata that goes beyond width and + * height, and the SDK exposes no public constructor accepting it. Rebuilding such a size from + * its dimensions alone silently turns an adaptive request into a fixed-size one, so the + * original instance is kept here and handed back unchanged by [toNative]. + */ + internal constructor(nativeAdSize: com.google.android.gms.ads.AdSize) : + this(nativeAdSize.width, nativeAdSize.height) { + this.nativeAdSize = nativeAdSize + } + init { com.google.android.gms.ads.AdSize(width, height) } + /** + * Returns the Google Mobile Ads size this represents, preserving the original instance when + * there is one. + */ + internal fun toNative(): com.google.android.gms.ads.AdSize = + nativeAdSize ?: com.google.android.gms.ads.AdSize(width, height) + public actual companion object { /** A constant for full-width ads. */ public actual val FULL_WIDTH: Int = com.google.android.gms.ads.AdSize.FULL_WIDTH diff --git a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt index d624634..1ae81b9 100644 --- a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt +++ b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt @@ -7,14 +7,12 @@ import android.content.ContextWrapper /** * Converts a common [AdSize] to a [com.google.android.gms.ads.AdSize]. */ -public fun AdSize.toAndroid(): com.google.android.gms.ads.AdSize = - com.google.android.gms.ads.AdSize(this.width, this.height) +public fun AdSize.toAndroid(): com.google.android.gms.ads.AdSize = this.toNative() /** * Converts a [com.google.android.gms.ads.AdSize] to a common [AdSize]. */ -public fun com.google.android.gms.ads.AdSize.toCommon(): AdSize = - AdSize(width = this.width, height = this.height) +public fun com.google.android.gms.ads.AdSize.toCommon(): AdSize = AdSize(this) /** * Converts a common [RequestConfiguration] to a [com.google.android.gms.ads.RequestConfiguration]. From 0710412315503072a9dc90bec1748c58eb630168 Mon Sep 17 00:00:00 2001 From: Anggrayudi H <12292380+anggrayudi@users.noreply.github.com> Date: Sun, 23 Aug 2026 07:49:09 +0700 Subject: [PATCH 6/7] fix(android): unwrap the full context chain when resolving the Activity (#154) getActivity stopped after five unwraps, so an Activity further down a wrapper chain was reported as absent. Its own KDoc already promised to traverse "until it finds the actual Activity or reaches the end of the chain", so the limit contradicted the documented behaviour. With i = 5 the loop body runs at most five times and therefore inspects at most five contexts: the receiver plus four unwraps. An Activity at the sixth position returns null, and every rememberX composable that resolves its Activity through LocalContext.current.getActivity() then fails in load() with "Activity Context must be set to non-null value in Android", even though an Activity was reachable. The traversal now continues to the end of the chain. The limit appears to have guarded against a non-terminating chain, so that protection is kept explicitly by stopping when a wrapper's base is itself. Co-authored-by: anggrayudi.hardiannico Co-authored-by: Claude Opus 5 (1M context) --- .../kotlin/app/lexilabs/basic/ads/Converters.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt index 1ae81b9..09b0b7a 100644 --- a/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt +++ b/basic-ads/src/androidMain/kotlin/app/lexilabs/basic/ads/Converters.kt @@ -70,11 +70,14 @@ public fun com.google.android.gms.ads.RequestConfiguration.PublisherPrivacyPerso */ public fun Context.getActivity(): Activity? { var context = this - var i = 5 - while (context is ContextWrapper && i > 0) { + while (context is ContextWrapper) { if (context is Activity) return context - context = context.baseContext - i -= 1 + val base = context.baseContext + // A wrapper whose base is itself would otherwise spin forever. This replaces a previous + // fixed limit of five unwraps, which gave up before reaching the Activity on deeply + // wrapped chains and returned null as though no Activity existed. + if (base === context) return null + context = base } return null } \ No newline at end of file From 0c4258192f4545f65e4710f4290b6f5868d15632 Mon Sep 17 00:00:00 2001 From: Robert Jamison <65142411+robertjamison@users.noreply.github.com> Date: Sat, 22 Aug 2026 21:07:30 -0400 Subject: [PATCH 7/7] Simplify `gradle.properties` by removing outdated comments and redundant settings --- gradle.properties | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gradle.properties b/gradle.properties index a113b6b..4583525 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,8 +29,4 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true #Dokka org.gradle.caching=false org.gradle.configuration-cache=false -org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled - -#Security -# TODO: Update as updates become available -android.experimental.lint.version = 32.2.1 \ No newline at end of file +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled \ No newline at end of file