728x90

이 코드는 이 코드를 위해 작성하였습니다.



java에서 smartcardio라이브러리를 이용하면 nfc제어를 쉽게 구현할 수 있다.


nfc리더기가 연결되어 있으면 터미널 초기화가 가능하다. 현재 사용중인 acr 1251 리더기는 PICC, SAM 두개의 터미널이 있는데


기본적으로 PICC를 사용한다. (SAM은 태그에 보호기술이 들어간 것에 사용)


IsCardPresent() 메소드는 리더기 위에 카드가 있는지 검사하며 있을 경우 터미널에 대한 채널을 GetCardAndOpenChannel() 메소드로 오픈한다.


SendCommand() 메소드를 통해 올려진 카드(혹은 핸드폰)에 데이터를 보낸다.


위 안드로이드 어플리케이션과 통신하기 위해 Select AID과정을 거치는데 그에 해당하는 바이트열이 selectCardAID()메소드에 있는 것이다.


NFCMain.java

package nfc_simple;

import javax.smartcardio.*;

import java.nio.ByteBuffer;
import java.util.*;

public class NFCMain {
    private static final String UNKNOWN_CMD_SW = "0000";
    private static final String SELECT_OK_SW = "9000";
    
    public void run() {
        CardTerminal terminal;
        CardChannel channel;
        
        while (true) {
            // 터미널 초기화
            try {
                terminal = InitializeTerminal();
                
                if(IsCardPresent(terminal)) {                                   // 리더기 위에 카드(핸드폰)가 있을 경우
                    channel = GetCardAndOpenChannel(terminal);
                    
                    String response = selectCardAID(channel);
                    
                    System.out.println(response);
                }
                
                Thread.sleep(2000);
                
            } catch (CardException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    public CardTerminal InitializeTerminal() throws CardException { 
        // Get terminal 
        System.out.println("Searching for terminals..."); 
        CardTerminal terminal = null; 
        TerminalFactory factory = TerminalFactory.getDefault(); 
        List<CardTerminal> terminals = factory.terminals().list(); 
      
        //Print list of terminals 
        for(CardTerminal ter:terminals) { 
            System.out.println("Found: "  +ter.getName().toString()); 
            terminal = terminals.get(0);// We assume just one is connected 
        } 
     
        return terminal; 
    }
    
    public boolean IsCardPresent(CardTerminal terminal) throws CardException {
        System.out.println("Waiting for card...");
        
        boolean isCard = false;
        
        while (!isCard) {
            isCard = terminal.waitForCardPresent(0);
            if(isCard)
                System.out.println("Card was found! :-)");
        }
        
        return true;
    }
    
    public CardChannel GetCardAndOpenChannel(CardTerminal terminal) throws CardException {
        Card card = terminal.connect("*");
        CardChannel channel = card.getBasicChannel();
        
        byte[] baReadUID = new byte[5];
        baReadUID = new byte[]{(byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00};
        
        // tag의 uid (unique ID)를 얻은 후 출력
        System.out.println("UID : " + SendCommand(baReadUID, channel));
        
        return channel;
    }
    
    public String selectCardAID(CardChannel channel) {
        
        byte[] baSelectCardAID = new byte[11];
        baSelectCardAID = new byte[]{(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte)0x05,(byte) 0xF2, (byte) 0x22, (byte) 0x22, (byte) 0x22, (byte) 0x22};
        
        return SendCommand(baSelectCardAID, channel);
    }
    
    public static String SendCommand(byte[] cmd, CardChannel channel) { 
        String response = "";
        byte[] baResp = new byte[258];
         
        ByteBuffer bufCmd = ByteBuffer.wrap(cmd);
        ByteBuffer bufResp = ByteBuffer.wrap(baResp);
         
        int output = 0;
         
        try { 
            output = channel.transmit(bufCmd, bufResp); 
        } catch(CardException ex){ 
            ex.printStackTrace(); 
        } 

        for (int i = 0; i < output; i++) {
            response += String.format("%02X", baResp[i]); 
        }
          
        return response;  
    }
}



728x90

+ Recent posts