2015-02-20 2 views
1

Я новичок в разработке с помощью ACR или NFC Reader, особенно для Android. И недавно мне нужно использовать ACR35, и у меня есть SDK и пример от this acs official website. И в качестве примера он отлично работает. И теперь мне нужно создать действие, которое всегда будет готово проверить, не используется ли nfc-карта. Но проблема в том, что я не знаю, как определить, когда nfc-карта прослушивается, и я не знаю, что делать дальше, и я не могу найти выход из примера, поскольку он обнаруживает карту nfc, когда я касаюсь «передать», он не делает это автоматически. Пожалуйста, дайте мне пример кода. Спасибо за ваш ответ.Как использовать ACR35 NFC Reader в Android

ответ

0

Сначала вы вызываете команду Reset для активации устройства. Когда устройство засыпает (через 4 секунды по умолчанию) * трюк заключается в том, чтобы сохранить его в живых.

Вы можете добиться этого, перезапустив новую команду PowerOn каждый раз, когда предыдущий тайм-аут PowerOn. Что-то вроде этого

void powerOn() { 
if (!mReader.piccPowerOn(mPiccTimeout, mPiccCardType)) { 
    powerOn(); 
} else { 
    askNfcForItsId(); 
} 

Не забудьте позвонить POWERON после прочтения НКА в противном случае он заснет после 1-го НКА карты.

* таймаут сброса может быть установлен между 4 и 20 секунд

4

Немного поздно, но это может помочь кому-то. Я нашел следующий проект на git-хабе. Он показывает, как читать идентификатор тега от acr35 here .

Я использую acr35 в течение некоторого времени, чтобы прочитать идентификатор тега. По моему опыту, это устройство с ошибкой на Android. Я тестировал около 10 устройств и работал только на 3 ...

Я читал оттуда каждую секунду. Он возвращает результаты с последней карты, даже если ее больше нет. Следовательно; Я должен сбросить его дважды за каждое успешное чтение, и потребуется около 6 секунд, чтобы снова включить устройство в состояние чтения ... Также будьте очень осторожны при многопоточности.

Моя реализация на основе данного проекта - добавил простой замок, чтобы остановить запрашивая карту после преуспевающим чтения + полный сброс устройства, filternig же UUID, который читался в очень короткое время после того, как он был прочитан ранее:

ACR3x класс

import com.acs.audiojack.AudioJackReader; 

import android.media.AudioManager; 
import sk.tido.util.ByteHex; 

import java.util.Date; 

/** 
* This class allows control of the ACR35 reader sleep state and PICC commands 
*/ 
public class Acr3x { 

    private Acr3xTransmitter transmitter; 
    private AudioManager mAudioManager; 
    private AudioJackReader mReader; 

    private boolean firstReset = true; /** Is this the first reset of the reader? */ 

    /** APDU command for reading a card's UID */ 
    private final byte[] apdu = { (byte) 0xFF, (byte) 0xCA, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; 
    /** Timeout for APDU response (in <b>seconds</b>) */ 
    private final int timeout = 1; 
    private int acr3xCardType = AudioJackReader.PICC_CARD_TYPE_ISO14443_TYPE_A 
      | AudioJackReader.PICC_CARD_TYPE_ISO14443_TYPE_B 
      | AudioJackReader.PICC_CARD_TYPE_FELICA_212KBPS 
      | AudioJackReader.PICC_CARD_TYPE_FELICA_424KBPS 
      | AudioJackReader.PICC_CARD_TYPE_AUTO_RATS; 

    private int acr3xStartAudioLevel = 0; 

    private Object locking = new Object(); 

    private String lastUuid = ""; 
    private Date lastUuidDate = new Date(); 


    public Acr3x(AudioManager mAudioManager){ 
     this.mAudioManager = mAudioManager; 
    } 

    public void start(final Acr3xNotifListener listener){ 
     Runnable r = new Runnable(){ 

      @Override 
      public void run() { 
       if(mReader == null){ 
        mReader = new AudioJackReader(mAudioManager); 
       } 
       System.out.println("ACR35 reader start"); 

       acr3xStartAudioLevel = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); 
       System.out.println("acr3x start audio stream level: " + acr3xStartAudioLevel); 
       mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 
         mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0); 
       System.out.println("acr3x set audio stream level: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 

       mReader.start(); 
       mReader.setSleepTimeout(30); 
       mReader.setOnFirmwareVersionAvailableListener(new AudioJackReader.OnFirmwareVersionAvailableListener() { 
        @Override 
        public void onFirmwareVersionAvailable(AudioJackReader reader, 
         String firmwareVersion) { 
         System.out.println("acr3x firmware version: " + firmwareVersion); 
         if(listener != null){ 
          listener.onFirmwareVersionAvailable(firmwareVersion); 
         } 
         Acr3x.this.read(listener); 

        } 
       }); 
       mReader.reset(new AudioJackReader.OnResetCompleteListener(){ 

        @Override 
        public void onResetComplete(AudioJackReader arg0) { 
         mReader.getFirmwareVersion(); 

        } 

       }); 
      } 
     }; 

     Thread t = new Thread(r, "Acr3xInitThread"); 
     t.start(); 

    } 


    /** 
    * Sets the ACR35 reader to continuously poll for the presence of a card. If a card is found, 
    * the UID will be returned to the Apache Cordova application 
    * 
    * @param callbackContext: the callback context provided by Cordova 
    * @param cardType: the integer representing card type 
    */ 
    public void read(final Acr3xNotifListener callbackContext){ 
     System.out.println("acr3x setting up for reading..."); 
     firstReset = true; 

     /* Set the PICC response APDU callback */ 
     mReader.setOnPiccResponseApduAvailableListener 
       (new AudioJackReader.OnPiccResponseApduAvailableListener() { 
        @Override 
        public void onPiccResponseApduAvailable(AudioJackReader reader, 
                  byte[] responseApdu) { 
         /* Update the connection status of the transmitter */ 
         transmitter.updateStatus(true); 

         /* Print out the UID */ 
         String uuid = ByteHex.bytesToHex(responseApdu); 

         if(uuid.equalsIgnoreCase("0x9000")){ 
          return; 
         } 

         if(uuid.endsWith("9000")){ 
          uuid = uuid.substring(0, uuid.length() - 4); 
         } 

         if(uuid.equals(lastUuid)){ // na odfiltrovanie opakujucich sa uuid z citacky z predchadzajuceho citania 
          if(new Date().getTime() - lastUuidDate.getTime() < 3000){ 
           return; 
          } 
         } 

         lastUuid = uuid; 
         lastUuidDate = new Date(); 

         synchronized(locking){ 

          System.out.println("acr3x uuid: " + uuid); 

          if(callbackContext != null){ 
           callbackContext.onUUIDAavailable(uuid); 
          } 
          System.out.println("acr3x restarting reader"); 
          transmitter.kill(); 
          try { 
           locking.wait(2000); 
          } catch (InterruptedException e) { 
           // TODO Auto-generated catch block 
           e.printStackTrace(); 
          } 
         } 

         read(callbackContext); 



        } 
       }); 

     /* Set the reset complete callback */ 
     mReader.setOnResetCompleteListener(new AudioJackReader.OnResetCompleteListener() { 
      @Override 
      public void onResetComplete(AudioJackReader reader) { 
       System.out.println("acr3x reset complete"); 

       /* If this is the first reset, the ACR35 reader must be turned off and back on again 
        to work reliably... */ 
       Thread t = null; 
       if(firstReset){ //firstReset 
        t = new Thread(new Runnable() { 
         public void run() { 
          try{ 
           /* Set the reader asleep */ 
           mReader.sleep(); 
           /* Wait one second */ 
           Thread.sleep(500); 
           /* Reset the reader */ 
           mReader.reset(); 

           firstReset = false; 
          } catch (InterruptedException e) { 
           e.printStackTrace(); 
           // TODO: add exception handling 
          } 
         } 
        }); 

       } else { 
        /* Create a new transmitter for the UID read command */ 
        transmitter = new Acr3xTransmitter(mReader, mAudioManager, timeout, 
          apdu, acr3xCardType, locking); 
        t = new Thread(transmitter); 
       } 
       t.start(); 
      } 
     }); 

     mReader.start(); 
     mReader.reset(); 
     System.out.println("acr3x setup complete"); 
    } 

    public void stop(){ 
     if(transmitter != null){ 
      transmitter.kill(); 
     } 

     System.out.println("acr3x restoring audio level: " + acr3xStartAudioLevel); 
     mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,acr3xStartAudioLevel, 0); 
     System.out.println("acr3x set audio stream level: " + mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)); 

     if(mReader != null){ 
      mReader.stop(); 
     } 
    } 

} 

класс передатчик

import com.acs.audiojack.AudioJackReader; 

import android.media.AudioManager; 

/** 
* This class sets up an independent thread for card polling, and is linked to the 
* <code>setOnPiccResponseApduAvailableListener</code> callback function 
*/ 

public class Acr3xTransmitter implements Runnable { 

    private AudioJackReader mReader; 
    private AudioManager mAudioManager; 
    //private CallbackContext mContext; 

    private boolean killMe = false;   /** Stop the polling thread? */ 
    private int itersWithoutResponse = 0; /** The number of iterations that have passed with no 
               response from the reader */ 
    private boolean readerConnected = true; /** Is the reader currently connected? */ 

    private int cardType; 
    private int timeout; 
    private byte[] apdu; 
    private Object locking; 

    /** 
    * @param mReader: AudioJack reader service 
    * @param mAudioManager: system audio service 
    * @param mContext: context for plugin results 
    * @param timeout: time in <b>seconds</b> to wait for commands to complete 
    * @param apdu: byte array containing the command to be sent 
    * @param cardType: the integer representing card type 
    */ 
    public Acr3xTransmitter(AudioJackReader mReader, AudioManager mAudioManager, 
         int timeout, byte[] apdu, int cardType, Object locking){ 
     this.mReader = mReader; 
     this.mAudioManager = mAudioManager; 
     this.timeout = timeout; 
     this.apdu = apdu; 
     this.cardType = cardType; 
     this.locking = locking; 
    } 


    /** 
    * Stops the polling thread 
    */ 
    public void kill(){ 
     killMe = true; 
    } 


    /** 
    * Updates the connection status of the reader (links to APDU response callback) 
    */ 
    public void updateStatus(boolean status){ 
     readerConnected = status; 
    } 

    /** 
    * Sends the APDU command for reading a card UID every second 
    */ 
    @Override 
    public void run() { 
     try { 
      /* Wait one second for stability */ 
      Thread.sleep(1000); 

      while (!killMe) { 
       synchronized(locking){ 

        if(killMe){ 
         continue; 
        } 
        /* If the reader is not connected, increment no. of iterations without response */ 
        if(!readerConnected){ 
         itersWithoutResponse++; 
        } 
        /* Else, reset the number of iterations without a response */ 
        else{ 
         itersWithoutResponse = 0; 
        } 
        /* Reset the connection state */ 
        readerConnected = false; 

        if(itersWithoutResponse == 4) { 
         /* Communicate to the Cordova application that the reader is disconnected */ 
         System.out.println("acr3x disconnected"); 
         /* Kill this thread */ 
         kill(); 
        } else if(!mAudioManager.isWiredHeadsetOn()) { 
         System.out.println("acr3x not connected"); 
         /* Kill this thread */ 
         kill(); 
        } else{ 
         System.out.println("acr3x reading..."); 
         /* Power on the PICC */ 
         mReader.piccPowerOn(timeout, cardType); 
         /* Transmit the APDU */ 
         mReader.piccTransmit(timeout, apdu); 


        } 
       } 
       /* Repeat every second */ 
       Thread.sleep(1000); 
      } 
      /* Power off the PICC */ 
      mReader.piccPowerOff(); 
      /* Set the reader asleep */ 
      mReader.sleep(); 
      /* Stop the reader service */ 
      mReader.stop(); 

      synchronized(locking){ 
       locking.notifyAll(); 
      } 

     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      // TODO: add exception handling 
     } 
    } 

} 

интерфейса слушателя:

public interface Acr3xNotifListener { 

public void onUUIDAavailable(String uuid); 
public void onFirmwareVersionAvailable(String firmwareVersion); 

}

+0

Добро пожаловать на переполнение стека! Хотя ссылка, которую вы предоставили, может ответить на вопрос, лучше всего поместить основные части вашего решения прямо в ответ, если страница в ссылке исчезнет в будущем. – Kmeixner

+0

Я добавил к реализации. – smory

+0

спас мой день. @smory tyvm! – TGIO

Смежные вопросы