| | |
| | | package com.dayu.recharge.tools; |
| | | |
| | | import android.annotation.TargetApi; |
| | | import android.app.Activity; |
| | | import android.nfc.NfcAdapter; |
| | | import android.nfc.Tag; |
| | | import android.nfc.tech.IsoDep; |
| | | import android.nfc.tech.MifareClassic; |
| | | import android.os.Build; |
| | | import android.util.Log; |
| | | |
| | |
| | | |
| | | // Weak reference to prevent retain loop. mAccountCallback is responsible for exiting |
| | | // foreground mode before it becomes invalid (e.g. during onPause() or onStop()). |
| | | private WeakReference<AccountCallback> mAccountCallback; |
| | | private AccountCallback mAccountCallback; |
| | | |
| | | Activity mActivity; |
| | | |
| | | public interface AccountCallback { |
| | | public void onAccountReceived(Tag tag); |
| | | //实体卡回调 |
| | | public void physicalCardDoing(Tag tag); |
| | | |
| | | //虚拟卡回调 |
| | | public void virtualCardDoing(Tag tag); |
| | | } |
| | | |
| | | public LoyaltyCardReader(AccountCallback accountCallback) { |
| | | mAccountCallback = new WeakReference<AccountCallback>(accountCallback); |
| | | public LoyaltyCardReader(Activity activity, AccountCallback accountCallback) { |
| | | mActivity = activity; |
| | | mAccountCallback = accountCallback; |
| | | } |
| | | |
| | | /** |
| | |
| | | @Override |
| | | public void onTagDiscovered(Tag tag) { |
| | | Log.i(TAG, "New tag discovered"); |
| | | mAccountCallback.get().onAccountReceived(tag); |
| | | // Android's Host-based Card Emulation (HCE) feature implements the ISO-DEP (ISO 14443-4) |
| | | // protocol. |
| | | // |
| | | // In order to communicate with a device using HCE, the discovered tag should be processed |
| | | // using the IsoDep class. |
| | | IsoDep isoDep = IsoDep.get(tag); |
| | | if (isoDep != null) { |
| | | try { |
| | | // Connect to the remote NFC device |
| | | isoDep.connect(); |
| | | // Build SELECT AID command for our loyalty card service. |
| | | // This command tells the remote device which service we wish to communicate with. |
| | | Log.i(TAG, "Requesting remote AID: " + SAMPLE_LOYALTY_CARD_AID); |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | byte[] command = BuildSelectApdu(SAMPLE_LOYALTY_CARD_AID); |
| | | |
| | | // Send command to remote device |
| | | Log.i(TAG, "Sending: " + ByteArrayToHexString(command)); |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | byte[] result = isoDep.transceive(command); |
| | | // If AID is successfully selected, 0x9000 is returned as the status word (last 2 |
| | | // bytes of the result) by convention. Everything before the status word is |
| | | // optional payload, which is used here to hold the account number. |
| | | int resultLength = result.length; |
| | | byte[] statusWord = {result[resultLength - 2], result[resultLength - 1]}; |
| | | byte[] payload = Arrays.copyOf(result, resultLength - 2); |
| | | if (Arrays.equals(SELECT_OK_SW, statusWord)) { |
| | | // The remote NFC device will immediately respond with its stored account number |
| | | String accountNumber = new String(payload, "UTF-8"); |
| | | Log.i(TAG, "Received: " + accountNumber); |
| | | // Inform CardReaderFragment of received account number |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | MifareClassic mifareClassic= MifareClassic.get(tag); |
| | | //普通M1卡 |
| | | if (mifareClassic!=null){ |
| | | mActivity.runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | mAccountCallback.physicalCardDoing(tag); |
| | | } |
| | | } catch (IOException e) { |
| | | Log.e(TAG, "Error communicating with card: " + e.toString()); |
| | | }); |
| | | }else { |
| | | // Android 的基于主机的卡仿真 (HCE) 功能实现了 ISO-DEP (ISO 14443-4) 协议。为了使用 HCE 与设备通信,应使用 IsoDep 类处理发现的标记。 |
| | | IsoDep isoDep = IsoDep.get(tag); |
| | | if (isoDep != null) { |
| | | try { |
| | | // Connect to the remote NFC device |
| | | isoDep.connect(); |
| | | // Build SELECT AID command for our loyalty card service. |
| | | // This command tells the remote device which service we wish to communicate with. |
| | | Log.i(TAG, "Requesting remote AID: " + SAMPLE_LOYALTY_CARD_AID); |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | byte[] command = BuildSelectApdu(SAMPLE_LOYALTY_CARD_AID); |
| | | |
| | | // Send command to remote device |
| | | Log.i(TAG, "Sending: " + ByteArrayToHexString(command)); |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | byte[] result = isoDep.transceive(command); |
| | | // If AID is successfully selected, 0x9000 is returned as the status word (last 2 |
| | | // bytes of the result) by convention. Everything before the status word is |
| | | // optional payload, which is used here to hold the account number. |
| | | int resultLength = result.length; |
| | | byte[] statusWord = {result[resultLength - 2], result[resultLength - 1]}; |
| | | byte[] payload = Arrays.copyOf(result, resultLength - 2); |
| | | if (Arrays.equals(SELECT_OK_SW, statusWord)) { |
| | | // The remote NFC device will immediately respond with its stored account number |
| | | String accountNumber = new String(payload, "UTF-8"); |
| | | Log.i(TAG, "Received: " + accountNumber); |
| | | // Inform CardReaderFragment of received account number |
| | | // mAccountCallback.get().onAccountReceived(); |
| | | } |
| | | } catch (IOException e) { |
| | | Log.e(TAG, "Error communicating with card: " + e.toString()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | /** |