在android中一个接一个地(顺序)扫描NFC卡

时间:2014-06-10 09:10:03

标签: android nfc

我开发了一个简单的Android应用程序,可以读取NFC卡上的NDEF消息。以下是该应用的代码 -

public class MainActivity extends Activity {

    public static final String MIME_TEXT_PLAIN = "text/plain";
    public static final String TAG = "NfcDemo";

    private TextView mTextView;
    private TextView mTextView2;
    private NfcAdapter mNfcAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textView_explanation);

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        if (mNfcAdapter == null) {
               Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
            finish();
            return;

        }

        if (!mNfcAdapter.isEnabled()) {
            mTextView.setText("NFC is disabled.");
        } else {
            mTextView.setText("Read Content : ");
        }

        handleIntent(getIntent());
    }

    @Override
    protected void onResume() {
        super.onResume();

        setupForegroundDispatch(this, mNfcAdapter);
    }

    @Override
    protected void onPause() {

        stopForegroundDispatch(this, mNfcAdapter);

        super.onPause();
    }

    @Override
    protected void onNewIntent(Intent intent) {
          handleIntent(intent);
    }

    private void handleIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

            String type = intent.getType();
            if (MIME_TEXT_PLAIN.equals(type)) {

                Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                new NdefReaderTask().execute(tag);

            } else {
                Log.d(TAG, "Wrong mime type: " + type);
            }
        } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {

            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            String[] techList = tag.getTechList();
            String searchedTech = Ndef.class.getName();

            for (String tech : techList) {
                if (searchedTech.equals(tech)) {
                    new NdefReaderTask().execute(tag);
                    break;
                }
            }
        }
    }

    public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);

        IntentFilter[] filters = new IntentFilter[1];
        String[][] techList = new String[][]{};

        filters[0] = new IntentFilter();
        filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
        filters[0].addCategory(Intent.CATEGORY_DEFAULT);
        try {
            filters[0].addDataType(MIME_TEXT_PLAIN);
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("Check your mime type.");
        }

        adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
    }

    public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
        adapter.disableForegroundDispatch(activity);
    }

    private class NdefReaderTask extends AsyncTask<Tag, Void, String> {

        @Override
        protected String doInBackground(Tag... params) {
            Tag tag = params[0];

            Ndef ndef = Ndef.get(tag);
            if (ndef == null) {
                // NDEF is not supported by this Tag.
                return null;
            }

            NdefMessage ndefMessage = ndef.getCachedNdefMessage();

            NdefRecord[] records = ndefMessage.getRecords();
            for (NdefRecord ndefRecord : records) {
                if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                    try {
                        return readText(ndefRecord);
                    } catch (UnsupportedEncodingException e) {
                        Log.e(TAG, "Unsupported Encoding", e);
                    }
                }
            }

            return null;
        }

        private String readText(NdefRecord record) throws UnsupportedEncodingException {

            byte[] payload = record.getPayload();
            String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
            int languageCodeLength = payload[0] & 0063;
            String languageCode = new String(payload, 1, languageCodeLength,"US-ASCII");
            return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
        }

        @Override
        protected void onPostExecute(String result) {
            if (result != null) {
                mTextView.setText("Read content: " + result);
                }

            }
        }
    }


}

现在我想要实现的是 - 一旦我读了一张卡并且它有一个特定的数据值,我希望我的应用程序应该等待几秒钟接受另一张卡作为输入,然后我想比较这两张卡中的数据。 我该如何实现这一目标?谢谢。

1 个答案:

答案 0 :(得分:1)

首先,不需要通过Ndef对象实例检索Android缓存的NDEF消息。 Android将为您处理此问题,并将在意图额外EXTRA_NDEF_MESSAGES中传递NDEF消息。因此,您可以使用handleIntent()方法立即检索NDEF消息:

private void handleIntent(Intent intent) {
    String action = intent.getAction();
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
        NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if ((rawMsgs != null) && (rawMsgs.length > 0)) {
            NdefMessage ndefMsg = (NdefMessage)rawMsgs[0];
            if (ndefMsg != null) {
                NdefRecord[] ndefRecs = ndefMsg.getRecords();
                if (ndefRecs != null) {
                    for (NdefRecord ndefRecord : records) {
                        if ((ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN) && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                            processTextRecord(ndefRecord);
                        }
                    }
                }
            }
        }
    }
}

其次,如果您想要在一定时间内扫描两个标签,您可以执行以下操作(我假设您只想执行该检查,如果您的标签包含文本记录而且您没有&# 39;请注意时间戳的潜在-1角落情况:

private long mLastTimestamp = -1;
private final static long TIMEOUT = 5 * 1000 * 1000;  // TIMEOUT between two taps in microseconds
private void processTextRecord(NdefRecord ndefRecord) {
    long currentTimestamp = System.nanoTime();
    if ((mLastTimestamp != -1) && ((currentTimestamp - mLastTimestamp) <= TIMEOUT)) {
        // two taps of a tag (or two different tags) have occured within TIMEOUT nanoseconds
        ...
    }
}