Skip to content

Add com.codename1.nfc: NDEF read/write, ISO-DEP/MIFARE/FeliCa, HCE#4996

Open
shai-almog wants to merge 9 commits into
masterfrom
add-nfc-api
Open

Add com.codename1.nfc: NDEF read/write, ISO-DEP/MIFARE/FeliCa, HCE#4996
shai-almog wants to merge 9 commits into
masterfrom
add-nfc-api

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

Promotes NFC to a first-class device API alongside Location, Capture and the recently-added Biometrics. A single Nfc entry point exposes the platform NFC controller; typed errors / async returns mirror the com.codename1.security design.

The matching cloud-build daemon changes ship in BuildDaemon PR codenameone/BuildDaemon#80.

Public surface (com.codename1.nfc)

  • Nfc, NfcException, NfcError (NOT_AVAILABLE / DISABLED / TAG_LOST / READ_ONLY / CAPACITY_EXCEEDED / UNKNOWN_AID / ...).
  • NdefMessage + NdefRecord with typed factories (createUri, createText, createMime, createExternal, createApplicationRecord) and a parser tolerant of the SR / IL flags.
  • Tag, TagType, TagTechnology + per-technology subclasses: IsoDep, MifareClassic, MifareUltralight, NfcA / NfcB / NfcF (FeliCa) / NfcV.
  • NfcReadOptions (alert copy, tech filter, FeliCa system codes, auto-SELECT AIDs, timeout) and NfcListener for multi-tag sessions.
  • HostCardEmulationService + ApduResponse for HCE.

Ports

  • Android wraps NfcAdapter.enableReaderMode + android.nfc.tech.*; HostApduService is bridged by CodenameOneHostApduService so subclassing com.codename1.nfc.HostCardEmulationService is enough -- the manifest entry + apduservice.xml are generated at build time.
  • iOS wraps NFCNDEFReaderSession + NFCTagReaderSession (NFCISO7816Tag, NFCMiFareTag, NFCFeliCaTag) and weak-links CoreNFC.framework. The native block is gated on a new CN1_INCLUDE_NFC define that IPhoneBuilder uncomments only when the classpath scanner saw a com.codename1.nfc reference. Apps that never use NFC ship without any CoreNFC symbols and pass Apple's API-usage scan without a CoreNFC privacy manifest.
  • JavaSE simulator gets a Simulate -> NFC submenu (virtual tag with editable NDEF, configurable read outcome, tag-tap, HCE APDU dialog).
  • All other platforms -- the fallback base class returns false from canRead() and completes every async call with NfcError.NOT_AVAILABLE.

Build pipeline (maven/codenameone-maven-plugin)

  • Android: auto-inject android.permission.NFC + <uses-feature android:name="android.hardware.nfc"> when the scanner sees com.codename1.nfc.*; add BIND_NFC_SERVICE + nfc.hce feature + the CodenameOneHostApduService manifest entry + a generated res/xml/apduservice.xml when HostCardEmulationService is referenced or the android.hceAids hint is set.
  • iOS: link CoreNFC.framework + default NFCReaderUsageDescription + readersession.formats entitlement; for HCE, inject com.apple.developer.nfc.hce + select-identifiers entitlements derived from ios.hceAids / android.hceAids. The CN1_INCLUDE_NFC define in CodenameOne_GLViewController.h is flipped on only when NFC is referenced.

Test plan

  • Build an app that does NOT reference com.codename1.nfc.* on both Android and iOS; verify no NFC manifest / plist / entitlement entries are injected and that the iOS binary contains no CoreNFC symbols (App Store API-usage scan).
  • Build an app calling Nfc.getInstance().readNdef(...); verify Android gets the NFC permission + feature and iOS gets CoreNFC.framework + the reader-session entitlement + NFCReaderUsageDescription.
  • Build an app subclassing HostCardEmulationService with android.hceAids set; verify Android gets the CodenameOneHostApduService manifest entry + a generated apduservice.xml, and iOS gets the HCE entitlements + select-identifiers.
  • Tap a writable NDEF tag on Android with Nfc.getInstance().writeNdef(...); verify the tag is updated.
  • Tap an EMV card with tag.getIsoDep().transceive(selectAid); verify the SW1/SW2 status word comes back.
  • Open the simulator's Simulate -> NFC menu and exercise the virtual tag (URI / text edits, tap, read-only toggle, HCE APDU).
  • Run the JavaSE / Ant test-javase suite -- no regressions in unrelated APIs.
  • Confirm Vale + spotbugs are clean on the new files (ASCII-only, /// markdown javadoc, no LI_LAZY_INIT_STATIC).

🤖 Generated with Claude Code

shai-almog and others added 2 commits May 21, 2026 18:15
Promotes NFC to a first-class device API alongside Location, Capture and
the recently-added Biometrics. A single Nfc entry point exposes the
platform NFC controller and the typed errors / async returns mirror the
com.codename1.security design.

Public surface (com.codename1.nfc):
  - Nfc, NfcException, NfcError (NOT_AVAILABLE / DISABLED / TAG_LOST /
    READ_ONLY / CAPACITY_EXCEEDED / UNKNOWN_AID / ...).
  - NdefMessage + NdefRecord with typed factories (createUri,
    createText, createMime, createExternal, createApplicationRecord)
    and a parser tolerant of the SR / IL flags.
  - Tag, TagType, TagTechnology + per-technology subclasses: IsoDep,
    MifareClassic, MifareUltralight, NfcA / NfcB / NfcF (FeliCa) /
    NfcV.
  - NfcReadOptions (alert copy, tech filter, FeliCa system codes,
    auto-SELECT AIDs, timeout) and NfcListener for multi-tag sessions.
  - HostCardEmulationService + ApduResponse for HCE.

Android port wraps NfcAdapter.enableReaderMode + android.nfc.tech.*;
HostApduService is bridged by CodenameOneHostApduService. iOS port
wraps NFCNDEFReaderSession + NFCTagReaderSession (NFCISO7816Tag,
NFCMiFareTag, NFCFeliCaTag) and weak-links CoreNFC.framework. JavaSE
simulator gets a Simulate -> NFC submenu (virtual tag with editable
NDEF, configurable read outcome, tag-tap, HCE APDU dialog).

The iOS native block is gated on a new CN1_INCLUDE_NFC define that
IPhoneBuilder uncomments only when the classpath scanner saw a
com.codename1.nfc reference. Apps that never use NFC ship without any
CoreNFC symbols and pass Apple's API-usage scan without a CoreNFC
privacy manifest.

Build pipeline (maven/codenameone-maven-plugin):
  - Android: auto-inject android.permission.NFC + uses-feature when
    the scanner sees com.codename1.nfc.*; add BIND_NFC_SERVICE +
    nfc.hce feature + the CodenameOneHostApduService manifest entry +
    a generated res/xml/apduservice.xml when HostCardEmulationService
    is referenced or the android.hceAids hint is set.
  - iOS: link CoreNFC.framework + default NFCReaderUsageDescription +
    readersession.formats entitlement; for HCE, inject
    com.apple.developer.nfc.hce + select-identifiers entitlements
    derived from ios.hceAids / android.hceAids.

The matching backend changes ship in BuildDaemon PR #80.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AndroidGradleBuilder.build() already declares a `File xmlDir` near the
top of the method (it points to res/xml inside the unzipped sources).
The HCE block introduced in the prior commit declared a second
`File xmlDir` pointing at src/main/res/xml, which javac rejects as a
variable already defined in the method. Rename the HCE-side local to
hceXmlDir so it no longer shadows the existing variable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 21, 2026

Compared 20 screenshots: 20 matched.
✅ JavaScript-port screenshot tests passed.

@github-actions
Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 21, 2026

Compared 11 screenshots: 11 matched.
✅ JavaSE simulator integration screenshots matched stored baselines.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Image references: No unused images detected (report)

The linker on native-ios CI rejected the NFC build:

  Undefined symbols for architecture arm64:
    "_com_codename1_impl_ios_IOSNative_isNfcSupported___R_boolean",
        referenced from:
        _com_codename1_impl_ios_IOSNfc_isSupported___R_boolean in
        com_codename1_impl_ios_IOSNfc.o

ParparVM emits the canonical `___R_<returnType>` suffix on non-void
native method symbols generated from recently-introduced Java sources.
The IOSBiometrics block predates the convention switch and is kept on
the legacy `__` form for compatibility, but newly-added natives have to
use the suffix or the link step fails.

Rename the four boolean-returning NFC natives:
  - isNfcSupported__         -> isNfcSupported___R_boolean
  - canReadNfc__             -> canReadNfc___R_boolean
  - canReadNfcTags__         -> canReadNfcTags___R_boolean
  - canHostEmulateNfc__      -> canHostEmulateNfc___R_boolean

Void NFC natives (startNdefRead etc.) already use the parameter-only
form which is unchanged between the two conventions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 21, 2026

Compared 110 screenshots: 110 matched.

Native Android coverage

  • 📊 Line coverage: 11.90% (6755/56788 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.66% (33986/351672), branch 4.16% (1388/33359), complexity 5.20% (1665/32007), method 9.04% (1354/14973), class 14.72% (302/2051)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 11.90% (6755/56788 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.66% (33986/351672), branch 4.16% (1388/33359), complexity 5.20% (1665/32007), method 9.04% (1354/14973), class 14.72% (302/2051)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 1060.000 ms
Base64 CN1 encode 119.000 ms
Base64 encode ratio (CN1/native) 0.112x (88.8% faster)
Base64 native decode 1285.000 ms
Base64 CN1 decode 510.000 ms
Base64 decode ratio (CN1/native) 0.397x (60.3% faster)
Image encode benchmark status skipped (SIMD unsupported)

build-test (8) flagged three DM_DEFAULT_ENCODING violations in
NdefRecord.toUtf8 / .toAscii / .fromUtf8 -- each catch block was
falling back to s.getBytes() / new String(bytes) without specifying
an encoding, which SpotBugs treats as platform-dependent and forbids.

UTF-8 and US-ASCII are both required by the JLS to be present on
every JVM (rt.jar's StandardCharsets enumerates them as required),
so the catch is dead code. Match the pattern StringUtil.getBytes
already uses in this codebase and throw a RuntimeException instead
of falling through to the default encoding.

Also fix two Microsoft.Contractions warnings on
Near-Field-Communication.asciidoc -- the developer-guide quality gate
treats Vale errors as build-breaking. Rewrite "does not" -> "doesn't"
on lines 89 and 95 to match the rest of the guide's style.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 21, 2026

Compared 110 screenshots: 110 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 249 seconds

Build and Run Timing

Metric Duration
Simulator Boot 82000 ms
Simulator Boot (Run) 1000 ms
App Install 14000 ms
App Launch 5000 ms
Test Execution 317000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 542.000 ms
Base64 CN1 encode 1468.000 ms
Base64 encode ratio (CN1/native) 2.708x (170.8% slower)
Base64 native decode 331.000 ms
Base64 CN1 decode 994.000 ms
Base64 decode ratio (CN1/native) 3.003x (200.3% slower)
Base64 SIMD encode 423.000 ms
Base64 encode ratio (SIMD/native) 0.780x (22.0% faster)
Base64 encode ratio (SIMD/CN1) 0.288x (71.2% faster)
Base64 SIMD decode 386.000 ms
Base64 decode ratio (SIMD/native) 1.166x (16.6% slower)
Base64 decode ratio (SIMD/CN1) 0.388x (61.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 75.000 ms
Image createMask (SIMD on) 9.000 ms
Image createMask ratio (SIMD on/off) 0.120x (88.0% faster)
Image applyMask (SIMD off) 144.000 ms
Image applyMask (SIMD on) 59.000 ms
Image applyMask ratio (SIMD on/off) 0.410x (59.0% faster)
Image modifyAlpha (SIMD off) 121.000 ms
Image modifyAlpha (SIMD on) 57.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.471x (52.9% faster)
Image modifyAlpha removeColor (SIMD off) 140.000 ms
Image modifyAlpha removeColor (SIMD on) 88.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.629x (37.1% faster)
Image PNG encode (SIMD off) 1148.000 ms
Image PNG encode (SIMD on) 1038.000 ms
Image PNG encode ratio (SIMD on/off) 0.904x (9.6% faster)
Image JPEG encode 471.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 21, 2026

Compared 110 screenshots: 110 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 292 seconds

Build and Run Timing

Metric Duration
Simulator Boot 98000 ms
Simulator Boot (Run) 1000 ms
App Install 13000 ms
App Launch 16000 ms
Test Execution 341000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 981.000 ms
Base64 CN1 encode 2342.000 ms
Base64 encode ratio (CN1/native) 2.387x (138.7% slower)
Base64 native decode 442.000 ms
Base64 CN1 decode 1988.000 ms
Base64 decode ratio (CN1/native) 4.498x (349.8% slower)
Base64 SIMD encode 450.000 ms
Base64 encode ratio (SIMD/native) 0.459x (54.1% faster)
Base64 encode ratio (SIMD/CN1) 0.192x (80.8% faster)
Base64 SIMD decode 513.000 ms
Base64 decode ratio (SIMD/native) 1.161x (16.1% slower)
Base64 decode ratio (SIMD/CN1) 0.258x (74.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 58.000 ms
Image createMask (SIMD on) 10.000 ms
Image createMask ratio (SIMD on/off) 0.172x (82.8% faster)
Image applyMask (SIMD off) 175.000 ms
Image applyMask (SIMD on) 119.000 ms
Image applyMask ratio (SIMD on/off) 0.680x (32.0% faster)
Image modifyAlpha (SIMD off) 238.000 ms
Image modifyAlpha (SIMD on) 136.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.571x (42.9% faster)
Image modifyAlpha removeColor (SIMD off) 268.000 ms
Image modifyAlpha removeColor (SIMD on) 232.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.866x (13.4% faster)
Image PNG encode (SIMD off) 1557.000 ms
Image PNG encode (SIMD on) 1080.000 ms
Image PNG encode ratio (SIMD on/off) 0.694x (30.6% faster)
Image JPEG encode 824.000 ms

shai-almog and others added 2 commits May 21, 2026 20:46
build-test (8) flagged ten SpotBugs violations across the NFC code:

  - Nfc.readNdef / writeNdef declare anonymous SuccessCallback chains
    inside instance methods, so javac synthesises an outer-Nfc
    reference into each ($1, $2, $3, $4) even though none of them
    touch `this`. Extract the chaining work to chainReadNdef /
    chainWriteNdef static helpers so the inner classes live in a
    static context.

  - AndroidNfc.deliverTag's callSerially Runnable captured a synthetic
    outer-AndroidNfc reference for the same reason. Hoist the Runnable
    into a scheduleTagDelivery static helper that takes the snapshot
    explicitly.

  - IOSNfc.IOSTag's read/write/lock methods used an anonymous
    TagOpInvoker functional interface implementation per call. Replace
    the indirection with a static bindTagOp helper that returns the
    IOSNative bridge (or rejects the AsyncResource) plus direct
    invocations from each IOSTag method; the inner interface is gone.

  - IOSNfc.registerHostCardEmulationService /
    unregisterHostCardEmulationService were `synchronized` (instance
    lock) while mutating the static `hceService` field, which would
    not serialise updates if multiple IOSNfc instances ever existed.
    Switch to synchronized(IOSNfc.class) so all callers serialise
    against the same monitor (SpotBugs
    SSD_DO_NOT_USE_INSTANCE_LOCK_ON_SHARED_STATIC_DATA).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PMD flagged five forbidden violations in the NFC core sources:

  - MissingOverride x 4: the anonymous SuccessCallback / Throwable
    callbacks inside Nfc.chainReadNdef and Nfc.chainWriteNdef were
    missing the @OverRide annotation on each onSucess(...) method.
    Add @OverRide on every anonymous implementation (PMD only flagged
    the outer four but the inner ones are equivalent so they get the
    annotation too).

  - ForLoopCanBeForeach: NfcReadOptions.setIsoSelectAids walked the
    incoming byte[][] with an explicit index; the index was never used
    on its own. Convert to an enhanced-for loop over the array.

The build-test (8) PMD scan is restricted to core sources (per the
QUALITY_REPORT_TARGET_DIRS list), so AndroidNfc / IOSNfc / JavaSENfc
do not need analogous annotation churn -- the existing Android port
uses both styles freely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

shai-almog and others added 3 commits May 21, 2026 23:31
The Ports/Android module compiles with javac.source=1.6 (see
Ports/Android/nbproject/project.properties), so locals captured by
anonymous inner classes have to be declared final --- Java 8's
effectively-final semantics don't apply at -source 1.6.

build-test (8) blew up on the Ant-driven Android compile step with
four errors against AndroidNfc.armReader: the activity, a (NfcAdapter),
flags and extras locals were referenced inside the runOnUiThread
Runnable but were not declared final. Add the final modifier on each.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SpotBugs MS_PKGPROTECT (Normal / Low) flagged 14 fields across
ApduResponse, MifareClassic and NdefRecord: each was a public static
final byte[]. The `final` only protects the reference, not the array
contents, so one caller could mutate the shared instance and corrupt
every subsequent read of the well-known constant.

Convert all 14 to public static accessor methods that return a fresh
defensive copy:

  - NdefRecord.RTD_TEXT / RTD_URI / RTD_SMART_POSTER / RTD_ANDROID_APP
    -> rtdText() / rtdUri() / rtdSmartPoster() / rtdAndroidApp().
    The underlying byte arrays stay as private static finals so the
    factory methods inside NdefRecord (createText, createUri,
    createApplicationRecord, getTextPayload, getUriPayload) keep
    referencing the shared instance directly --- they don't mutate.

  - ApduResponse.SW_SUCCESS / SW_FILE_NOT_FOUND / SW_INS_NOT_SUPPORTED
    / SW_CLA_NOT_SUPPORTED / SW_WRONG_LENGTH /
    SW_SECURITY_NOT_SATISFIED / SW_UNKNOWN_ERROR -> swSuccess() etc.
    HCE response paths allocate a fresh 2-byte array per call which
    is negligible against the APDU round-trip cost.

  - MifareClassic.KEY_DEFAULT / KEY_MIFARE_APPLICATION_DIRECTORY /
    KEY_NFC_FORUM -> keyDefault() / keyMifareApplicationDirectory() /
    keyNfcForum(). Each returns a fresh 6-byte copy so an app passing
    the key to authenticateSectorWithKeyA can't be tripped up if the
    platform Mifare implementation mutates the input.

Update internal callers (CodenameOneHostApduService, IOSNfc.nativeHceApdu,
JavaSENfc.simulateApdu / SimIsoDep, Nfc class-level Javadoc, and the
HCE example in Near-Field-Communication.asciidoc).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	Ports/iOSPort/nativeSources/IOSNative.m
#	scripts/cn1playground/tools/src/main/java/com/codenameone/playground/tools/GenerateCN1AccessRegistry.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant