Compile the Android port against API 37, which removed FingerprintManager (issue #5701) - #5723
Compile the Android port against API 37, which removed FingerprintManager (issue #5701)#5723shai-almog wants to merge 1 commit into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Cloudflare Preview
|
|
Compared 151 screenshots: 151 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 181 screenshots: 181 matched. |
79ea3e0 to
b535f01
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b535f01af7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
d7e90f7 to
c8276e3
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c8276e358d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ager (issue #5701) Android SDK Platform 37 removes android.hardware.fingerprint.FingerprintManager and Context.FINGERPRINT_SERVICE. cn1:buildAndroidGradleProject picks the newest installed platform, so a developer with 37 installed got compileSdkVersion 37 and 34 javac errors in AndroidBiometrics and AndroidSecureStorage -- port sources they never wrote, in an unmodified Hello World. Neither Android biometric API can be named from a file every application compiles. FingerprintManager is gone from 37; BiometricPrompt arrives in API 28, which is newer than the cn1-binaries android.jar the port jar is built against. So each moves into a package of its own, next to the ar, ai, cipher and nearby precedents, and AndroidBiometrics picks one at class-init through the new BiometricBackend interface: - com/codename1/impl/android/biometrics reaches BiometricPrompt directly. It is excluded from the port jar compile and compiled in the generated app. Its floor is API 28, where BiometricPrompt itself arrives, which is also the bottom of compileSdkInt's ladder -- so the builder's prune never fires in practice. Everything newer that it needs (BiometricManager is 29, canAuthenticate(int) and Authenticators are 30) is reached by name instead of compiled against, verified by checking every android.* reference in the compiled class against the SDK's api-versions.xml: none is newer than 28. Keeping the floor at the bottom of the ladder is what stops a project pinned to 28 or 29 from losing the package, which would have left its APK with no biometrics at all on an API 37 device, where the legacy backend's platform API no longer exists. - com/codename1/impl/android/fingerprint reaches the platform fingerprint API through the support library's FingerprintManagerCompat, so it compiles against every platform including 37 and is never deleted. That matters: an application compiled against 37 still RUNS on API 23-28, where the platform class it wraps is the only biometric API there is. The android.support.v4 spelling is what the port's other support-library users write; AndroidGradleBuilder rewrites it to androidx.core for every AndroidX app through androidx-class-mapping.csv, which was verified on the generated project rather than assumed. The backend's class name is a constant string at the Class.forName call so R8 keeps it, and a proguard keep rule states it outright as well. canAuthenticate asks for Authenticators.BIOMETRIC_STRONG where the platform offers it. The deprecated no-argument call AOSP defines as canAuthenticate(BIOMETRIC_WEAK) would advertise an authentication that cannot happen: every prompt in the port carries a CryptoObject, and BiometricPrompt defaults a crypto prompt to BIOMETRIC_STRONG and refuses anything weaker ("Only Strong biometrics supported with crypto"), so a Class 2 face on an API 30+ device answers the weak query and then fails the prompt. API 29 falls back to the no-argument call, which is the only query that platform has, and the fallback is driven by the overload being absent rather than by a version check. Making the fingerprint package compile at 37 also made the API 29+ path load-bearing, and it did not work. BiometricsApi29 reached BiometricPrompt by reflection and built its callback with java.lang.reflect.Proxy -- but BiometricPrompt.AuthenticationCallback is an abstract class, and Proxy accepts interfaces only, so every call threw IllegalArgumentException and the caller was told the hardware was unavailable. The new backend subclasses it directly, which is only possible now the file compiles against a modern platform. BiometricsApi29 is deleted with it, along with four cast-semantics baseline entries. Behaviour otherwise stands still, with one forced exception: from API 29, getAvailableBiometrics reports FINGERPRINT when the device has the sensor and a usable biometric is enrolled. It used to ask FingerprintManager exactly, and Android exposes no per-modality enrolment query to replace it. The port has three compiles and the biometrics exclusion is stated in all three: maven/android/pom.xml, Ports/Android/nbproject/project.properties and Ports/Android/build.xml. The first already carried the same list for ar, ai, cipher and nearby; the Ant pair is what build-test (8) runs. Verified by building scripts/hellocodenameone for Android at compileSdkVersion 37 / targetSdkVersion 37: assembleDebug succeeds and the APK carries both backends. A signature diff of android.jar 36 against 37, over the 258 android.* classes the port imports, finds FINGERPRINT_SERVICE as the only source-visible removal, so nothing else in the port is exposed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
c8276e3 to
b59c3eb
Compare
|
Compared 160 screenshots: 160 matched. Benchmark Results
Detailed Performance Metrics
|
|
Compared 149 screenshots: 149 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 144 screenshots: 144 matched. |
|
Compared 217 screenshots: 217 matched. |
Fixes #5701.
The bug
Android SDK Platform 37 removes
android.hardware.fingerprint.FingerprintManagerandContext.FINGERPRINT_SERVICE.cn1:buildAndroidGradleProjectselects the newest installed platform, so a developer with 37 installed gotcompileSdkVersion 37and 34 javac errors inAndroidBiometricsandAndroidSecureStorage— port sources they never wrote, in an unmodified Hello World.The change
Neither Android biometric API can be named from a file every application compiles.
FingerprintManagerexists in API 23-36;BiometricPromptexists from API 28, which is newer than the cn1-binariesandroid.jarthe port jar is built against. So each moves into a package of its own, next to thear,ai,cipherandnearbyprecedents:com/codename1/impl/android/biometrics—BiometricPrompt, excluded from the port jar compile and compiled in the generated app.com/codename1/impl/android/fingerprint—FingerprintManager, compiled everywhere and deleted by the builder fromcompileSdk37.AndroidBiometricspicks one at class-init through the newBiometricBackendinterface, with the class name a constant string at theClass.forNamecall so R8 keeps it; a proguard keep rule states it outright as well. A build pinned tocompileSdk28 loses the modern package instead and falls back to the legacy one, which its devices still answer.Reflection is not an option for either callback: both
FingerprintManager.AuthenticationCallbackandBiometricPrompt.AuthenticationCallbackare abstract classes, andjava.lang.reflect.Proxyimplements interfaces only.A second defect this uncovered
Deleting the legacy package makes the API 29+ path load-bearing, and it did not work.
BiometricsApi29reachedBiometricPromptby reflection and built its callback withProxy— so every call threwIllegalArgumentException: ... is not an interface, was swallowed, and the caller was told the hardware was unavailable. The new backend subclasses the callback directly, which is only possible now that the file compiles against a modern platform.BiometricsApi29is deleted with it, along with fourcast-semantics-baseline.txtentries.Behaviour change
One, and it is forced: from API 29,
getAvailableBiometrics()reportsFINGERPRINTwhen the device has the sensor and some biometric is enrolled. It used to askFingerprintManagerexactly, and Android exposes no per-modality enrolment query to replace it. Documented in the javadoc and the developer guide.Verification
scripts/hellocodenameonebuilds an APK atcompileSdkVersion 37/targetSdkVersion 37; the APK carriesbiometrics/BiometricPromptBackendand no fingerprint package.package android.hardware.fingerprint does not exist).android.jar36 against 37, over the 258android.*classes the port imports, findsFINGERPRINT_SERVICEas the only source-visible removal — so nothing else in the port is exposed at 37.androidandcodenameone-maven-plugin; cast-semantics, control-character and copyright gates clean; Vale clean on the edited guide page.AndroidBiometricSourceSelectionTestcases.Needs the builder half
BuildDaemoncarries its ownAndroidGradleBuilderand needs the same pruning, or a cloud build atcompileSdk28 will fail to compile the newbiometricspackage. That PR is codenameone/BuildDaemon#TBD.Not done, deliberately
CI's local Android app build stays pinned to
compileSdk36. It works at 37, but AGP 8.13.2 is only tested up to 36 andtargetSdk37 would move the instrumentation suite's runtime behaviour; raising it is a separate, deliberate change. The comments that blamed the pin onFingerprintManagerare updated.🤖 Generated with Claude Code