-
Notifications
You must be signed in to change notification settings - Fork 1
Support Android API level 27 (STF-772) #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5e168cb
432d75f
4301609
18a75f4
69d5653
dab8fa7
fdeec50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,8 +4,8 @@ Android SDK for collecting and reporting device data to MaxMind. | |
|
|
||
| ## Requirements | ||
|
|
||
| - Android API 29+ (Android 10+) | ||
| - Kotlin 1.9.22+ | ||
| - Android API 27+ (Android 8.1+) | ||
| - Kotlin 2.2.21+ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Claude noticed that CLAUDE.md is out of date regarding this. |
||
| - AndroidX libraries | ||
|
|
||
| ## Installation | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package com.maxmind.device.collector | ||
|
|
||
| import android.content.Context | ||
| import androidx.test.core.app.ApplicationProvider | ||
| import org.junit.jupiter.api.Assertions.assertNotNull | ||
| import org.junit.jupiter.api.Test | ||
| import org.junit.jupiter.api.extension.ExtendWith | ||
| import org.robolectric.annotation.Config | ||
| import tech.apter.junit.jupiter.robolectric.RobolectricExtension | ||
|
|
||
| /** | ||
| * Best-effort Robolectric smoke test for [DeviceIDsCollector] on API 27 (Android 8.1). | ||
| * | ||
| * On API < 28 the collector releases [android.media.MediaDrm] via the deprecated | ||
| * `release()` lifecycle call instead of `close()` (which only exists from API 28). | ||
| * This test pins the SDK to 27 and asserts that [DeviceIDsCollector.collect] returns a | ||
| * [com.maxmind.device.model.DeviceIDs] without throwing. | ||
| * | ||
| * Known limitation: Robolectric's MediaDrm shadow does not exercise the real | ||
| * `release()`/`close()` split, so this test cannot fully validate the cleanup branch — | ||
| * consistent with how [DeviceIDsCollectorTest] treats MediaDRM as null in unit tests. | ||
| * The real branch is validated by lint's NewApi check and (optionally) an instrumented | ||
| * test on an API-27 device. | ||
| */ | ||
| @ExtendWith(RobolectricExtension::class) | ||
| @Config(sdk = [27]) | ||
| internal class DeviceIDsCollectorApi27RobolectricTest { | ||
| @Test | ||
| internal fun `collect returns DeviceIDs without throwing on API 27`() { | ||
| val context = ApplicationProvider.getApplicationContext<Context>() | ||
| val collector = DeviceIDsCollector(context) | ||
|
|
||
| val result = collector.collect() | ||
|
|
||
| assertNotNull(result) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| package com.maxmind.device.collector.helper | ||
|
|
||
| import android.content.Context | ||
| import androidx.test.core.app.ApplicationProvider | ||
| import org.junit.jupiter.api.Assertions.assertEquals | ||
| import org.junit.jupiter.api.Assertions.assertNotNull | ||
| import org.junit.jupiter.api.Test | ||
| import org.junit.jupiter.api.extension.ExtendWith | ||
| import org.robolectric.Shadows | ||
| import org.robolectric.annotation.Config | ||
| import tech.apter.junit.jupiter.robolectric.RobolectricExtension | ||
|
|
||
| /** | ||
| * Robolectric-based tests for [InstallationInfoHelper] on API 27 (Android 8.1). | ||
| * | ||
| * On API < 28 the helper falls back to the deprecated int [android.content.pm.PackageInfo.versionCode] | ||
| * field (read as `.versionCode.toLong()`) and to [android.content.pm.PackageManager.getInstallerPackageName] | ||
| * for the installer. JUnit 5's Robolectric extension can only set `@Config(sdk)` at the class | ||
| * level, so this separate class pins the SDK to 27 to exercise those legacy branches; the | ||
| * API-28+ branches stay covered by [InstallationInfoHelperRobolectricTest] at sdk 29. | ||
| */ | ||
| @ExtendWith(RobolectricExtension::class) | ||
| @Config(sdk = [27]) | ||
| internal class InstallationInfoHelperApi27RobolectricTest { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about this, but from Claude:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know if this is possible. Claude updated the comments though. |
||
| @Test | ||
| internal fun `collect reads versionCode from legacy int field on API 27`() { | ||
| val context = ApplicationProvider.getApplicationContext<Context>() | ||
| val shadowPm = Shadows.shadowOf(context.packageManager) | ||
|
|
||
| val packageInfo = shadowPm.getInternalMutablePackageInfo(context.packageName) | ||
| // Set only the legacy int versionCode field. The API-28 longVersionCode accessor does | ||
| // not exist in the API-27 runtime Robolectric loads here, so we cannot (and need not) | ||
| // pack a major version. This also makes the test discriminate the branch: if the | ||
| // production guard regressed to read packageInfo.longVersionCode at API 27, collect() | ||
| // would throw NoSuchMethodError (it is not caught) and this assertion would never run. | ||
| @Suppress("DEPRECATION") | ||
| packageInfo.versionCode = 456 | ||
| packageInfo.versionName = "9.8.7" | ||
|
|
||
| val helper = InstallationInfoHelper(context) | ||
| val result = helper.collect() | ||
|
|
||
| assertEquals(456L, result.versionCode, "versionCode should come from the legacy int field on API 27") | ||
| assertEquals("9.8.7", result.versionName, "versionName should match stubbed value") | ||
| } | ||
|
|
||
| @Test | ||
| internal fun `collect resolves installer via legacy branch without throwing on API 27`() { | ||
| // On API < 30 the helper takes the getInstallerPackageName branch. The installer is | ||
| // typically null in the Robolectric environment; we only verify the legacy branch is | ||
| // exercised without throwing (mirroring the sdk-29 InstallationInfoHelperRobolectricTest). | ||
| val context = ApplicationProvider.getApplicationContext<Context>() | ||
| val helper = InstallationInfoHelper(context) | ||
|
|
||
| val result = helper.collect() | ||
|
|
||
| assertNotNull(result) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| [versions] | ||
| # SDK Versions | ||
| minSdk = "29" | ||
| minSdk = "27" | ||
| targetSdk = "36" | ||
| compileSdk = "36" | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request includes an update to the Kotlin version in the README (
Kotlin 1.9.22+toKotlin 2.2.21+). According to our general rules, we should avoid making out-of-scope edits to pre-existing content that is not the primary focus of the pull request. Please revert this change and address it in a separate PR or commit if necessary.References