Hello,
I am developing an application to read a NFC Tag UID from NFC Reader (ACR122U-A9) device.
I used JAVA and javax.smartcardio API to detect the NFC Reader and Reading NFC Tag.
The functionality of the application is to display notification when the NFC Reader device is connect or disconnect from PC. Then if the device is connected and NFC Tag is presented then display the notification that NFC Tag is presented.
I tried to find the Event based api to implement above functionality but I cannot found so I used Java Timer and Polling for the NFC Reader Device and NFC Tag.
Following is my sample JAVA code that used for Polling for NFC device and Tag.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
public class NFC_Test {
static Timer timer;
public static void main(String[] args) {
try {
timer = new Timer();
timer.scheduleAtFixedRate(new NFC_Test.MyTask(), 0, 1000);
} catch (Exception ex) {
Logger.getLogger(NFC_Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
static class MyTask extends TimerTask {
public void run() {
try {
Class pcscterminal =
Class.forName("sun.security.smartcardio.PCSCTerminals");
Field contextId = pcscterminal.getDeclaredField("contextId");
contextId.setAccessible(true);
if (contextId.getLong(pcscterminal) != 0L) {
Class pcsc =
Class.forName("sun.security.smartcardio.PCSC");
Method SCardEstablishContext = pcsc.getDeclaredMethod(
"SCardEstablishContext", new Class[]{Integer.TYPE});
SCardEstablishContext.setAccessible(true);
Field SCARD_SCOPE_USER =
pcsc.getDeclaredField("SCARD_SCOPE_USER");
SCARD_SCOPE_USER.setAccessible(true);
long newId = ((Long) SCardEstablishContext.invoke(pcsc, new Object[]{Integer.valueOf(SCARD_SCOPE_USER.getInt(pcsc))})).longValue();
contextId.setLong(pcscterminal, newId);
}
} catch (Exception ex) {
}
TerminalFactory factory = null;
List<CardTerminal> terminals = null;
try {
factory = TerminalFactory.getDefault();
terminals = factory.terminals().list();
} catch (Exception ex) {
Logger.getLogger(NFC_Test.class.getName()).log(Level.SEVERE,null, ex);
}
if (factory != null && factory.terminals() != null && terminals
!= null && terminals.size() > 0) {
try {
CardTerminal terminal = terminals.get(0);
if (terminal != null) {
System.out.println(terminal);
if (terminal.isCardPresent()) {
System.out.println("Card");
} else {
System.out.println("No Card");
}
} else {
System.out.println("No terminal");
}
terminal = null;
} catch (Exception e) {
Logger.getLogger(NFC_Test.class.getName()).log(Level.SEVERE,null, e);
}
factory = null;
terminals = null;
Runtime.getRuntime().gc();
} else {
System.out.println("No terminal");
}
}
}
}
Above code is working fine in Windows OS but when I run it on MAC OS then application runs for 5-10 seconds perfectly but then it suddenly crash with the following memory error.
java(921,0x10b0c3000) malloc: *** mmap(size=140350941302784) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Java Result: 139
I searched on internet and cannot find anything regarding above memory error. When I contact ACS for same then they told me that the error message is not related to reader or card connection. It has something to do with memory management.
I already wrote the code for memory management to release the object when it is used in timer by assigning NULL value to it.
I used
http://ludovicrousseau.blogspot.com/2010/06/pcsc-sample-in-java.html[
^] for reference