Skip to content

NFC reader support #1416

@tresf

Description

@tresf

Enhancement request to add NFC/smart card reader support.

TODO:

  • File upstream bug for macOS issue (Done via QZ-29 private bug report).
    This is already fixed in JDK17+
  • Collect use-case from customer
  • Develop API, e.g. qz.nfc.listDevices, etc.
  • Milestone
  • Document
  • Release

WIP:

package com.company;

import javax.smartcardio.*;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        try {
            // FIXME: macOS: Force the library path inside the code
            // System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/PCSC");

            TerminalFactory factory = TerminalFactory.getDefault();
            CardTerminals terminalManager = factory.terminals();

            // List ALL terminals, even if no card is present
            List<CardTerminal> terminals = terminalManager.list(CardTerminals.State.ALL);

            if (terminals.isEmpty()) {
                System.out.println("Java still can't see the readers shown in system_profiler.");
                return;
            }

            System.out.println("Success! Found these readers:");
            for (CardTerminal t : terminals) {
                System.out.println("-> " + t.getName());
            }

            // The 'PICC' slot is the one for tapping NFC tags
            CardTerminal reader = terminals.stream()
                    .filter(t -> t.getName().contains("PICC"))
                    .findFirst()
                    .orElse(terminals.get(0));

            System.out.println("\nUsing: " + reader.getName());
            System.out.println("Please tap an NFC tag...");

            if (reader.waitForCardPresent(10000)) { // wait 10 seconds
                Card card = reader.connect("*");
                byte[] response = card.getBasicChannel().transmit(
                        new CommandAPDU(new byte[]{(byte)0xFF, (byte)0xCA, (byte)0x00, (byte)0x00, (byte)0x00})
                ).getData();

                System.out.println("Card UID: " + bytesToHex(response));
                card.disconnect(false);
            } else {
                System.out.println("Timeout: No card was tapped.");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) sb.append(String.format("%02X ", b));
        return sb.toString().trim();
    }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions