Пример реализации работы с NFC в Android

👁 1994

Спойлерок

Привет! Это пишет b00blik уже из будущего. Прошло несколько лет, и потому этот пост может быть слегка неактуален. Зато у меня есть другие рассказы: как я наполучал лещей в поиске иностранного оффера, как нищал русский айтишник в 2022, да даже про пинбол что-то есть. Залетай, расскажу!

Привет! У нас тут возникла задачка на работе, о решении которой я хотел бы с вами поделиться.

В общем, у нас есть внутрикорпоративное приложение с 3 кнопками (пришел, ушел на обед, ушел домой), которое внутри нашей электронной системы отмечает нас. Его написал мой напарник. Моя задача состояла в том, чтобы облегчить жизнь людям и запилить работу этого приложения с NFC-меткой.

Сперва, конечно, читаем доку.

У нас для такой цели была гордо выдана карточка московского метро 2013 года выпуска. Как потом оказалось, это карта типа Mifare Ultralight. Ну да ладно, читать её проще, чем Classic, а для идентификации просто строку байт будем использовать.

Добавим волшебные строчки с разрешениями в AndroidManifest.xml

<uses-permission android:name="android.permission.NFC" />

    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />
...

Для активити, в которой у нас будет обрабатываться Intent с NFC, пропишем intent-filter и meta-data

<intent-filter>
            <action android:name="android.nfc.action.TECH_DISCOVERED"/>
        </intent-filter>

        <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                   android:resource="@xml/nfc_tech_filter" />

В ресурсе nfc_tech_filter.xml укажем, с какого типа картой NFC будем работать

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

Теперь открываем Activity. Вот отрывок из моего onCreate-метода (тут важное замечание, вся работа с NFC описывается только в Activity)

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

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

            mPendingIntent = PendingIntent.getActivity(this, 0,
                    new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

            IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);

            try {
                ndef.addDataType("*/*");
            } catch (IntentFilter.MalformedMimeTypeException e) {
                throw new RuntimeException("fail", e);
            }

            mFilters = new IntentFilter[] {
                    ndef,
            };
            mTechLists = new String[][] { new String[] { MifareUltralight.class.getName() } };

            handleIntent(getIntent());
        }

Соответственно, напишем метод handleIntent, куда будем передавать наш NFC-шный интент:

public void handleIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
            Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            MifareUltralight mul = MifareUltralight.get(tagFromIntent);
            byte[] data;

            try {
                mul.connect();
                if (mul.getType() == MifareUltralight.TYPE_ULTRALIGHT) {
                    AppLog.d("type is ULTRALIGHT");
                }
                if (mul.getType() == MifareUltralight.TYPE_ULTRALIGHT_C) {
                    AppLog.d("type is ULTRALIGHT_C");
                }
                if (mul.getType() == MifareUltralight.TYPE_UNKNOWN) {
                    AppLog.d("type is UNKNOWN");
                }
                data = mul.readPages(0);
                String dataString = byteArrayToHex(data);
                AppLog.d(dataString);
                //а тут будем делать обработку данных, которые у нас уже есть
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

Собственно, там я написал уже обработчик, который просто сравнивал массивы данных и делал свою работу.

Мне кажется, довольно просто вышло.

9N9ke2GG5X8

Теперь отмечаемся вот такой штуковиной.